/*
 * 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 java.util.Arrays;
import java.util.List;
import java.util.Set;

import javax.servlet.http.HttpSession;

import org.apache.geode.cache.DataPolicy;
import org.apache.geode.cache.GemFireCache;
import org.apache.geode.cache.InterestResultPolicy;
import org.apache.geode.cache.Region;
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.PoolManager;
import org.apache.geode.cache.client.internal.PoolImpl;
import org.apache.geode.cache.execute.Execution;
import org.apache.geode.cache.execute.FunctionService;
import org.apache.geode.cache.execute.ResultCollector;
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.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 ClientServerSessionCache extends AbstractSessionCache {

  private ClientCache cache;

  protected static final String DEFAULT_REGION_ATTRIBUTES_ID =
      RegionShortcut.PARTITION_REDUNDANT.toString();

  protected static final boolean DEFAULT_ENABLE_LOCAL_CACHE = true;

  public ClientServerSessionCache(SessionManager sessionManager, ClientCache cache) {
    super(sessionManager);
    this.cache = cache;
  }

  @Override
  public void initialize() {
    // Bootstrap the servers
    bootstrapServers();

    // Create or retrieve the region
    try {
      createOrRetrieveRegion();
    } catch (Exception ex) {
      sessionManager.getLogger().fatal("Unable to create or retrieve region", ex);
      throw new IllegalStateException(ex);
    }

    // Set the session region directly as the operating region since there is no difference
    // between the local cache region and the session region.
    this.operatingRegion = this.sessionRegion;

    // Create or retrieve the statistics
    createStatistics();
  }

  @Override
  public String getDefaultRegionAttributesId() {
    return DEFAULT_REGION_ATTRIBUTES_ID;
  }

  @Override
  public boolean getDefaultEnableLocalCache() {
    return DEFAULT_ENABLE_LOCAL_CACHE;
  }

  @Override
  public void touchSessions(Set<String> sessionIds) {
    // Get the region attributes id to determine the region type. This is
    // problematic since the region attributes id doesn't really define the
    // region type. Currently there is no way to know the type of region created
    // on the server. Maybe the CreateRegionFunction should return it.
    String regionAttributesID = getSessionManager().getRegionAttributesId().toLowerCase();

    // Invoke the appropriate function depending on the type of region
    if (regionAttributesID.startsWith("partition")) {
      // Execute the partitioned touch function on the primary server(s)
      Execution execution = getExecutionForFunctionOnRegionWithFilter(sessionIds);
      try {
        ResultCollector collector = execution.execute(TouchPartitionedRegionEntriesFunction.ID);
        collector.getResult();
      } catch (Exception e) {
        // If an exception occurs in the function, log it.
        getSessionManager().getLogger().warn("Caught unexpected exception:", e);
      }
    } else {
      // Execute the member touch function on all the server(s)
      Object[] arguments = new Object[] {this.sessionRegion.getFullPath(), sessionIds};
      Execution execution = getExecutionForFunctionOnServersWithArguments(arguments);
      try {
        ResultCollector collector = execution.execute(TouchReplicatedRegionEntriesFunction.ID);
        collector.getResult();
      } catch (Exception e) {
        // If an exception occurs in the function, log it.
        getSessionManager().getLogger().warn("Caught unexpected exception:", e);
      }
    }
  }

  @Override
  public boolean isPeerToPeer() {
    return false;
  }

  @Override
  public boolean isClientServer() {
    return true;
  }

  @Override
  public Set<String> keySet() {
    return getSessionRegion().keySetOnServer();
  }

  @Override
  public int size() {
    return getSessionRegion().sizeOnServer();
  }

  @Override
  public boolean isBackingCacheAvailable() {
    if (getSessionManager().isCommitValveFailfastEnabled()) {
      PoolImpl pool = findPoolInPoolManager();
      return pool.isPrimaryUpdaterAlive();
    }
    return true;
  }

  @Override
  public GemFireCache getCache() {
    return this.cache;
  }

  private void bootstrapServers() {
    Execution execution = getExecutionForFunctionOnServers();
    ResultCollector collector = execution.execute(new BootstrappingFunction());
    // Get the result. Nothing is being done with it.
    try {
      collector.getResult();
    } catch (Exception e) {
      // If an exception occurs in the function, log it.
      getSessionManager().getLogger().warn("Caught unexpected exception:", e);
    }
  }

  protected void createOrRetrieveRegion() {
    // Retrieve the local session region
    this.sessionRegion = this.cache.getRegion(getSessionManager().getRegionName());

    // If necessary, create the regions on the server and client
    if (this.sessionRegion == null) {
      // Create the PR on the servers
      createSessionRegionOnServers();

      // Create the region on the client
      this.sessionRegion = createLocalSessionRegion();
      if (getSessionManager().getLogger().isDebugEnabled()) {
        getSessionManager().getLogger().debug("Created session region: " + this.sessionRegion);
      }
    } else {
      if (getSessionManager().getLogger().isDebugEnabled()) {
        getSessionManager().getLogger().debug("Retrieved session region: " + this.sessionRegion);
      }

      // Check that we have our expiration listener attached
      if (!regionHasExpirationListenerAttached(sessionRegion)) {
        sessionRegion.getAttributesMutator().addCacheListener(new SessionExpirationCacheListener());
      }

      // This is true for PROXY regions
      if (sessionRegion.getAttributes().getDataPolicy() == DataPolicy.EMPTY) {
        sessionRegion.registerInterest("ALL_KEYS", InterestResultPolicy.KEYS);
      }
    }
  }

  private boolean regionHasExpirationListenerAttached(Region<?, ?> region) {
    return Arrays.stream(region.getAttributes().getCacheListeners())
        .anyMatch(x -> x instanceof SessionExpirationCacheListener);
  }

  void createSessionRegionOnServers() {
    // Create the RegionConfiguration
    RegionConfiguration configuration = createRegionConfiguration();

    // Send it to the server tier
    Execution execution = getExecutionForFunctionOnServerWithRegionConfiguration(configuration);
    ResultCollector collector = execution.execute(CreateRegionFunction.ID);

    // Verify the region was successfully created on the servers
    List<RegionStatus> results = (List<RegionStatus>) collector.getResult();
    for (RegionStatus status : results) {
      if (status == RegionStatus.INVALID) {
        StringBuilder builder = new StringBuilder();
        builder
            .append(
                "An exception occurred on the server while attempting to create or validate region named ")
            .append(getSessionManager().getRegionName())
            .append(". See the server log for additional details.");
        throw new IllegalStateException(builder.toString());
      }
    }
  }

  Region<String, HttpSession> createLocalSessionRegion() {
    ClientRegionFactory<String, HttpSession> factory = null;
    if (getSessionManager().getEnableLocalCache()) {
      // Create the region factory with caching and heap LRU enabled
      factory = this.cache.createClientRegionFactory(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU);

      // Set the expiration time, action and listener if necessary
      int maxInactiveInterval = getSessionManager().getMaxInactiveInterval();
      if (maxInactiveInterval != RegionConfiguration.DEFAULT_MAX_INACTIVE_INTERVAL) {
        factory.setStatisticsEnabled(true);
        factory.setCustomEntryIdleTimeout(new SessionCustomExpiry());
        factory.addCacheListener(new SessionExpirationCacheListener());
      }
    } else {
      // Create the region factory without caching enabled
      factory = this.cache.createClientRegionFactory(ClientRegionShortcut.PROXY);
      factory.addCacheListener(new SessionExpirationCacheListener());
    }

    // Create the region
    Region region = factory.create(getSessionManager().getRegionName());

    /*
     * If we're using an empty client region, we register interest so that expired sessions are
     * destroyed correctly.
     */
    if (!getSessionManager().getEnableLocalCache()) {
      region.registerInterest("ALL_KEYS", InterestResultPolicy.KEYS);
    }

    return region;
  }

  // Helper methods added to improve unit testing of class
  Execution getExecutionForFunctionOnServers() {
    return getExecutionForFunctionOnServersWithArguments(null);
  }

  Execution getExecutionForFunctionOnServersWithArguments(Object[] arguments) {
    if (arguments != null && arguments.length > 0) {
      return FunctionService.onServers(getCache()).setArguments(arguments);
    } else {
      return FunctionService.onServers(getCache());
    }
  }

  Execution getExecutionForFunctionOnServerWithRegionConfiguration(RegionConfiguration arguments) {
    if (arguments != null) {
      return FunctionService.onServer(getCache()).setArguments(arguments);
    } else {
      return FunctionService.onServer(getCache());
    }
  }

  Execution getExecutionForFunctionOnRegionWithFilter(Set<?> filter) {
    if (filter != null && filter.size() > 0) {
      return FunctionService.onRegion(getSessionRegion()).withFilter(filter);
    } else {
      return FunctionService.onRegion(getSessionRegion());
    }
  }

  PoolImpl findPoolInPoolManager() {
    return (PoolImpl) PoolManager.find(getOperatingRegionName());
  }
}
