/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */

package org.apache.geode.modules.session.catalina;

import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpSession;

import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;

import org.apache.geode.Statistics;
import org.apache.geode.cache.AttributesMutator;
import org.apache.geode.cache.CacheListener;
import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.InterestResultPolicy;
import org.apache.geode.cache.RegionAttributes;
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.client.ClientCache;
import org.apache.geode.cache.client.ClientRegionFactory;
import org.apache.geode.cache.client.ClientRegionShortcut;
import org.apache.geode.cache.client.internal.InternalClientCache;
import org.apache.geode.cache.client.internal.PoolImpl;
import org.apache.geode.cache.execute.Function;
import org.apache.geode.cache.execute.FunctionException;
import org.apache.geode.cache.execute.ResultCollector;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.modules.session.catalina.callback.SessionExpirationCacheListener;
import org.apache.geode.modules.util.BootstrappingFunction;
import org.apache.geode.modules.util.CreateRegionFunction;
import org.apache.geode.modules.util.DebugCacheListener;
import org.apache.geode.modules.util.RegionConfiguration;
import org.apache.geode.modules.util.RegionStatus;
import org.apache.geode.modules.util.SessionCustomExpiry;
import org.apache.geode.modules.util.TouchPartitionedRegionEntriesFunction;
import org.apache.geode.modules.util.TouchReplicatedRegionEntriesFunction;

public class ClientServerSessionCacheJUnitTest extends AbstractSessionCacheJUnitTest {

  private List<RegionStatus> regionStatusResultList = new ArrayList<>();
  private ClientCache cache = mock(GemFireCacheImpl.class);
  private ResultCollector collector = mock(ResultCollector.class);
  private Statistics stats = mock(Statistics.class);
  @SuppressWarnings("unchecked")
  private ClientRegionFactory<String, HttpSession> regionFactory = mock(ClientRegionFactory.class);
  @SuppressWarnings("unchecked")
  private RegionAttributes<String, HttpSession> attributes = mock(RegionAttributes.class);

  @Before
  public void setUp() {
    sessionCache = spy(new ClientServerSessionCache(sessionManager, cache));
    doReturn(emptyExecution).when((ClientServerSessionCache) sessionCache)
        .getExecutionForFunctionOnServers();
    doReturn(emptyExecution).when((ClientServerSessionCache) sessionCache)
        .getExecutionForFunctionOnServersWithArguments(any());
    doReturn(emptyExecution).when((ClientServerSessionCache) sessionCache)
        .getExecutionForFunctionOnServerWithRegionConfiguration(any());
    doReturn(emptyExecution).when((ClientServerSessionCache) sessionCache)
        .getExecutionForFunctionOnRegionWithFilter(any());

    when(sessionManager.getLogger()).thenReturn(logger);
    when(sessionManager.getEnableLocalCache()).thenReturn(true);
    when(sessionManager.getRegionName()).thenReturn(sessionRegionName);
    when(sessionManager.getMaxInactiveInterval())
        .thenReturn(RegionConfiguration.DEFAULT_MAX_INACTIVE_INTERVAL);

    when(cache.getDistributedSystem()).thenReturn(distributedSystem);
    doReturn(regionFactory).when(cache)
        .createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU);
    when(((InternalClientCache) cache).isClient()).thenReturn(true);

    when(emptyExecution.execute(any(Function.class))).thenReturn(collector);
    when(emptyExecution.execute(any(String.class))).thenReturn(collector);

    when(collector.getResult()).thenReturn(regionStatusResultList);

    when(distributedSystem.createAtomicStatistics(any(), any())).thenReturn(stats);

    regionStatusResultList.clear();
    regionStatusResultList.add(RegionStatus.VALID);
  }

  @Test
  public void initializeSessionCacheSucceeds() {
    sessionCache.initialize();

    verify(emptyExecution).execute(any(BootstrappingFunction.class));
    verify(emptyExecution).execute(CreateRegionFunction.ID);
    verify(cache).createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU);
    verify(regionFactory, times(0)).setStatisticsEnabled(true);
    verify(regionFactory, times(0)).setCustomEntryIdleTimeout(any(SessionCustomExpiry.class));
    verify(regionFactory, times(0)).addCacheListener(any(SessionExpirationCacheListener.class));
    verify(regionFactory).create(sessionRegionName);
  }

  @Test
  public void bootstrappingFunctionThrowsException() {
    FunctionException exception = new FunctionException();

    ResultCollector exceptionCollector = mock(ResultCollector.class);

    when(emptyExecution.execute(new BootstrappingFunction())).thenReturn(exceptionCollector);
    when(exceptionCollector.getResult()).thenThrow(exception);

    sessionCache.initialize();

    verify(logger).warn("Caught unexpected exception:", exception);
  }


  @Test
  public void createOrRetrieveRegionThrowsException() {
    RuntimeException exception = new RuntimeException();
    doThrow(exception).when((ClientServerSessionCache) sessionCache).createLocalSessionRegion();

    assertThatThrownBy(() -> sessionCache.initialize()).hasCause(exception)
        .isInstanceOf(IllegalStateException.class);

    verify(logger).fatal("Unable to create or retrieve region", exception);

  }

  @Test
  public void createRegionFunctionFailsOnServer() {
    ArgumentCaptor<String> stringCaptor = ArgumentCaptor.forClass(String.class);

    regionStatusResultList.clear();
    regionStatusResultList.add(RegionStatus.INVALID);

    assertThatThrownBy(() -> sessionCache.initialize()).isInstanceOf(IllegalStateException.class)
        .hasCauseInstanceOf(IllegalStateException.class).hasMessageContaining(
            "An exception occurred on the server while attempting to create or validate region named "
                + sessionRegionName
                + ". See the server log for additional details.");

    verify(logger).fatal(stringCaptor.capture(), any(Exception.class));
    assertThat(stringCaptor.getValue()).isEqualTo("Unable to create or retrieve region");
  }

  @Test
  public void nonDefaultMaxTimeoutIntervalSetsExpirationDetails() {
    // Setting the mocked return value of getMaxInactiveInterval to something distinctly not equal
    // to the default
    when(sessionManager.getMaxInactiveInterval())
        .thenReturn(RegionConfiguration.DEFAULT_MAX_INACTIVE_INTERVAL + 1);

    sessionCache.initialize();

    verify(regionFactory).setStatisticsEnabled(true);
    verify(regionFactory).setCustomEntryIdleTimeout(any(SessionCustomExpiry.class));
    verify(regionFactory).addCacheListener(any(SessionExpirationCacheListener.class));
  }

  @Test
  public void createLocalSessionRegionWithoutEnableLocalCache() {
    when(sessionManager.getEnableLocalCache()).thenReturn(false);
    doReturn(regionFactory).when(cache).createClientRegionFactory(ClientRegionShortcut.PROXY);
    when(regionFactory.create(sessionRegionName)).thenReturn(sessionRegion);

    sessionCache.initialize();

    verify(regionFactory).addCacheListener(any(SessionExpirationCacheListener.class));
    verify(sessionRegion).registerInterest("ALL_KEYS", InterestResultPolicy.KEYS);
  }

  @Test
  public void createOrRetrieveRegionWithNonNullSessionRegionDoesNotCreateRegion() {
    @SuppressWarnings("unchecked")
    CacheListener<String, HttpSession>[] cacheListeners =
        new CacheListener[] {new SessionExpirationCacheListener()};
    doReturn(sessionRegion).when(cache).getRegion(sessionRegionName);
    doReturn(attributes).when(sessionRegion).getAttributes();
    doReturn(cacheListeners).when(attributes).getCacheListeners();

    sessionCache.initialize();

    verify((ClientServerSessionCache) sessionCache, times(0)).createSessionRegionOnServers();
    verify((ClientServerSessionCache) sessionCache, times(0)).createLocalSessionRegion();
  }

  @Test
  public void createOrRetrieveRegionWithNonNullSessionRegionAndNoSessionExpirationCacheListenerCreatesListener() {
    @SuppressWarnings("unchecked")
    CacheListener<String, HttpSession>[] cacheListeners =
        new CacheListener[] {new DebugCacheListener()};
    @SuppressWarnings("unchecked")
    AttributesMutator<String, HttpSession> attributesMutator = mock(AttributesMutator.class);
    doReturn(sessionRegion).when(cache).getRegion(sessionRegionName);
    doReturn(attributes).when(sessionRegion).getAttributes();
    doReturn(cacheListeners).when(attributes).getCacheListeners();
    doReturn(attributesMutator).when(sessionRegion).getAttributesMutator();

    sessionCache.initialize();

    verify(attributesMutator).addCacheListener(any(SessionExpirationCacheListener.class));
  }

  @Test
  public void createOrRetrieveRegionWithNonNullSessionProxyRegionRegistersInterestForAllKeys() {
    @SuppressWarnings("unchecked")
    CacheListener<String, HttpSession>[] cacheListeners =
        new CacheListener[] {new SessionExpirationCacheListener()};
    doReturn(sessionRegion).when(cache).getRegion(sessionRegionName);
    doReturn(attributes).when(sessionRegion).getAttributes();
    doReturn(cacheListeners).when(attributes).getCacheListeners();
    when(attributes.getDataPolicy()).thenReturn(DataPolicy.EMPTY);

    sessionCache.initialize();

    verify(sessionRegion).registerInterest("ALL_KEYS", InterestResultPolicy.KEYS);
  }

  @Test
  public void touchSessionsInvokesPRFunctionForPRAndDoesNotThrowExceptionWhenFunctionDoesNotThrowException() {
    Set<String> sessionIds = new HashSet<>();

    when(sessionManager.getRegionAttributesId()).thenReturn(RegionShortcut.PARTITION.toString());

    sessionCache.touchSessions(sessionIds);

    verify(emptyExecution).execute(TouchPartitionedRegionEntriesFunction.ID);
  }

  @Test
  public void touchSessionsInvokesPRFunctionForPRAndThrowsExceptionWhenFunctionThrowsException() {
    Set<String> sessionIds = new HashSet<>();
    FunctionException exception = new FunctionException();
    ResultCollector exceptionCollector = mock(ResultCollector.class);

    when(sessionManager.getRegionAttributesId()).thenReturn(RegionShortcut.PARTITION.toString());
    when(emptyExecution.execute(TouchPartitionedRegionEntriesFunction.ID))
        .thenReturn(exceptionCollector);
    when(exceptionCollector.getResult()).thenThrow(exception);

    sessionCache.touchSessions(sessionIds);
    verify(logger).warn("Caught unexpected exception:", exception);
  }

  @Test
  public void touchSessionsInvokesRRFunctionForRRAndDoesNotThrowExceptionWhenFunctionDoesNotThrowException() {
    // Need to invoke this to set the session region
    when(regionFactory.create(sessionRegionName)).thenReturn(sessionRegion);
    sessionCache.initialize();

    Set<String> sessionIds = new HashSet<>();

    when(sessionRegion.getFullPath()).thenReturn("/" + sessionRegionName);
    when(sessionManager.getRegionAttributesId()).thenReturn(RegionShortcut.REPLICATE.toString());

    sessionCache.touchSessions(sessionIds);
    verify(emptyExecution).execute(TouchReplicatedRegionEntriesFunction.ID);
  }

  @Test
  public void touchSessionsInvokesRRFunctionForRRAndThrowsExceptionWhenFunctionThrowsException() {
    // Need to invoke this to set the session region
    when(regionFactory.create(sessionRegionName)).thenReturn(sessionRegion);
    sessionCache.initialize();

    Set<String> sessionIds = new HashSet<>();
    FunctionException exception = new FunctionException();
    ResultCollector exceptionCollector = mock(ResultCollector.class);

    when(sessionRegion.getFullPath()).thenReturn("/" + sessionRegionName);
    when(sessionManager.getRegionAttributesId()).thenReturn(RegionShortcut.REPLICATE.toString());
    when(emptyExecution.execute(TouchReplicatedRegionEntriesFunction.ID))
        .thenReturn(exceptionCollector);
    when(exceptionCollector.getResult()).thenThrow(exception);

    sessionCache.touchSessions(sessionIds);
    verify(logger).warn("Caught unexpected exception:", exception);
  }

  @Test
  public void isBackingCacheEnabledReturnsTrueWhenCommitValveFailfastDisabled() {
    assertThat(sessionCache.isBackingCacheAvailable()).isTrue();
  }

  @Test
  public void isBackingCacheEnabledReturnsValueWhenCommitValveFailfastEnabled() {
    boolean backingCacheEnabled = false;
    PoolImpl pool = mock(PoolImpl.class);

    when(sessionManager.isCommitValveFailfastEnabled()).thenReturn(true);
    doReturn(pool).when((ClientServerSessionCache) sessionCache).findPoolInPoolManager();
    when(pool.isPrimaryUpdaterAlive()).thenReturn(backingCacheEnabled);

    assertThat(sessionCache.isBackingCacheAvailable()).isEqualTo(backingCacheEnabled);
  }
}
