/*
 * 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.cache.client.internal;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import org.apache.logging.log4j.Logger;

import org.apache.geode.InternalGemFireError;
import org.apache.geode.cache.InterestResultPolicy;
import org.apache.geode.cache.query.CqQuery;
import org.apache.geode.cache.query.internal.cq.InternalCqQuery;
import org.apache.geode.internal.cache.LocalRegion;
import org.apache.geode.internal.cache.tier.InterestType;
import org.apache.geode.internal.cache.tier.sockets.UnregisterAllInterest;
import org.apache.geode.internal.logging.LogService;

/**
 * Used to keep track of what interest a client has registered. This code was extracted from the old
 * ConnectionProxyImpl.
 *
 * @since GemFire 5.7
 */
public class RegisterInterestTracker {
  private static final Logger logger = LogService.getLogger();

  public static final int interestListIndex = 0;
  public static final int durableInterestListIndex = 1;
  private static final int interestListIndexForUpdatesAsInvalidates = 2;
  private static final int durableInterestListIndexForUpdatesAsInvalidates = 3;

  private final FailoverInterestList[] fils = new FailoverInterestList[4];

  /** Manages CQs */
  private final ConcurrentMap<CqQuery, Boolean> cqs = new ConcurrentHashMap<>();

  public RegisterInterestTracker() {
    this.fils[interestListIndex] = new FailoverInterestList();
    this.fils[interestListIndexForUpdatesAsInvalidates] = new FailoverInterestList();
    this.fils[durableInterestListIndex] = new FailoverInterestList();
    this.fils[durableInterestListIndexForUpdatesAsInvalidates] = new FailoverInterestList();
  }

  public static int getInterestLookupIndex(boolean isDurable, boolean receiveUpdatesAsInvalidates) {
    if (isDurable) {
      if (receiveUpdatesAsInvalidates) {
        return durableInterestListIndexForUpdatesAsInvalidates;
      } else {
        return durableInterestListIndex;
      }
    } else {
      if (receiveUpdatesAsInvalidates) {
        return interestListIndexForUpdatesAsInvalidates;
      } else {
        return interestListIndex;
      }
    }
  }

  public List<Object> getInterestList(String regionName, int interestType) {
    RegionInterestEntry rie1 = readRegionInterests(regionName, interestType, false, false);
    RegionInterestEntry rie2 = readRegionInterests(regionName, interestType, false, true);
    RegionInterestEntry rie3 = readRegionInterests(regionName, interestType, true, false);
    RegionInterestEntry rie4 = readRegionInterests(regionName, interestType, true, true);

    ArrayList<Object> result = new ArrayList<>();

    if (rie1 != null) {
      result.addAll(rie1.getInterests().keySet());
    }

    if (rie2 != null) {
      result.addAll(rie2.getInterests().keySet());
    }

    if (rie3 != null) {
      result.addAll(rie3.getInterests().keySet());
    }

    if (rie4 != null) {
      result.addAll(rie4.getInterests().keySet());
    }

    return result;
  }

  void addSingleInterest(LocalRegion r, Object key, int interestType,
      InterestResultPolicy pol, boolean isDurable,
      boolean receiveUpdatesAsInvalidates) {
    RegionInterestEntry rie =
        getRegionInterests(r, interestType, false, isDurable, receiveUpdatesAsInvalidates);
    rie.getInterests().put(key, pol);
  }

  boolean removeSingleInterest(LocalRegion r, Object key, int interestType,
      boolean isDurable, boolean receiveUpdatesAsInvalidates) {
    RegionInterestEntry rie =
        getRegionInterests(r, interestType, true, isDurable, receiveUpdatesAsInvalidates);
    if (rie == null) {
      return false;
    }
    if (logger.isDebugEnabled()) {
      logger.debug("removeSingleInterest region={} key={}", r.getFullPath(), key);
    }
    Object interest = rie.getInterests().remove(key);
    if (interest == null) {
      logger.warn("removeSingleInterest: key {} not registered in the client",
          key);
      return false;
    } else {
      return true;
    }
  }

  void addInterestList(LocalRegion r, List keys, InterestResultPolicy pol, boolean isDurable,
      boolean receiveUpdatesAsInvalidates) {
    RegionInterestEntry rie =
        getRegionInterests(r, InterestType.KEY, false, isDurable, receiveUpdatesAsInvalidates);
    for (Object key : keys) {
      rie.getInterests().put(key, pol);
    }
  }

  public void addCq(InternalCqQuery cqi, boolean isDurable) {
    this.cqs.put(cqi, isDurable);
  }

  public void removeCq(InternalCqQuery cqi) {
    this.cqs.remove(cqi);
  }

  Map getCqsMap() {
    return this.cqs;
  }

  /**
   * Unregisters everything registered on the given region name
   */
  void unregisterRegion(ServerRegionProxy srp, boolean keepalive) {
    removeAllInterests(srp, InterestType.KEY, false, keepalive, false);
    removeAllInterests(srp, InterestType.FILTER_CLASS, false, keepalive, false);
    removeAllInterests(srp, InterestType.OQL_QUERY, false, keepalive, false);
    removeAllInterests(srp, InterestType.REGULAR_EXPRESSION, false, keepalive, false);
    removeAllInterests(srp, InterestType.KEY, false, keepalive, true);
    removeAllInterests(srp, InterestType.FILTER_CLASS, false, keepalive, true);
    removeAllInterests(srp, InterestType.OQL_QUERY, false, keepalive, true);
    removeAllInterests(srp, InterestType.REGULAR_EXPRESSION, false, keepalive, true);
    // durable
    if (srp.getPool().isDurableClient()) {
      removeAllInterests(srp, InterestType.KEY, true, keepalive, true);
      removeAllInterests(srp, InterestType.FILTER_CLASS, true, keepalive, true);
      removeAllInterests(srp, InterestType.OQL_QUERY, true, keepalive, true);
      removeAllInterests(srp, InterestType.REGULAR_EXPRESSION, true, keepalive, true);
      removeAllInterests(srp, InterestType.KEY, true, keepalive, false);
      removeAllInterests(srp, InterestType.FILTER_CLASS, true, keepalive, false);
      removeAllInterests(srp, InterestType.OQL_QUERY, true, keepalive, false);
      removeAllInterests(srp, InterestType.REGULAR_EXPRESSION, true, keepalive, false);
    }
  }

  /**
   * Remove all interests of a given type on the given proxy's region.
   *
   * @param interestType the interest type
   * @param durable a boolean stating whether to remove durable or non-durable registrations
   */
  private void removeAllInterests(ServerRegionProxy srp, int interestType, boolean durable,
      boolean keepAlive, boolean receiveUpdatesAsInvalidates) {
    String regName = srp.getRegionName();
    ConcurrentMap allInterests =
        getRegionToInterestsMap(interestType, durable, receiveUpdatesAsInvalidates);
    if (allInterests.remove(regName) != null) {
      if (logger.isDebugEnabled()) {
        logger.debug("removeAllInterests region={} type={}", regName,
            InterestType.getString(interestType));
      }
      try {
        // fix bug 35680 by using a UnregisterAllInterest token
        Object key = UnregisterAllInterest.singleton();
        // we have already cleaned up the tracker so send the op directly
        UnregisterInterestOp.execute(srp.getPool(), regName, key, interestType, true/* isClosing */,
            keepAlive);
      } catch (Exception e) {
        if (!srp.getPool().getCancelCriterion().isCancelInProgress()) {
          logger.warn("Problem removing all interest on region={} interestType={} :{}",
              new Object[] {regName, InterestType.getString(interestType),
                  e.getLocalizedMessage()});
        }
      }
    }
  }

  boolean removeInterestList(LocalRegion r, List keys, boolean isDurable,
      boolean receiveUpdatesAsInvalidates) {
    RegionInterestEntry rie =
        getRegionInterests(r, InterestType.KEY, true, isDurable, receiveUpdatesAsInvalidates);
    if (rie == null) {
      return false;
    }
    if (logger.isDebugEnabled()) {
      logger.debug("removeInterestList region={} keys={}", r.getFullPath(), keys);
    }
    int removeCount = 0;
    for (Object key : keys) {
      Object interest = rie.getInterests().remove(key);
      if (interest != null) {
        removeCount++;
      } else {
        logger.warn("removeInterestList: key {} not registered in the client",
            key);
      }
    }
    return removeCount != 0;
  }

  /**
   * Return keys of interest for a given region. The keys in this Map are the full names of the
   * regions. The values are instances of RegionInterestEntry.
   *
   * @param interestType the type to return
   * @return the map
   */
  ConcurrentMap<String, RegionInterestEntry> getRegionToInterestsMap(int interestType,
      boolean isDurable,
      boolean receiveUpdatesAsInvalidates) {
    FailoverInterestList fil =
        this.fils[getInterestLookupIndex(isDurable, receiveUpdatesAsInvalidates)];

    switch (interestType) {
      case InterestType.KEY:
        return fil.keysOfInterest;
      case InterestType.REGULAR_EXPRESSION:
        return fil.regexOfInterest;
      case InterestType.FILTER_CLASS:
        return fil.filtersOfInterest;
      case InterestType.CQ:
        return fil.cqsOfInterest;
      case InterestType.OQL_QUERY:
        return fil.queriesOfInterest;
      default:
        throw new InternalGemFireError("Unknown interestType");
    }
  }

  /**
   * Return the RegionInterestEntry for the given region. Create one if none exists and forRemoval
   * is false.
   *
   * @param r specified region
   * @param interestType desired interest type
   * @param forRemoval true if calls wants one for removal
   * @return the entry or null if none exists and forRemoval is true.
   */
  private RegionInterestEntry getRegionInterests(LocalRegion r, int interestType,
      boolean forRemoval, boolean isDurable, boolean receiveUpdatesAsInvalidates) {
    final String regionName = r.getFullPath();
    ConcurrentMap<String, RegionInterestEntry> mapOfInterest =
        getRegionToInterestsMap(interestType, isDurable, receiveUpdatesAsInvalidates);
    RegionInterestEntry result = mapOfInterest.get(regionName);
    if (result == null && !forRemoval) {
      RegionInterestEntry rie = new RegionInterestEntry(r);
      result = mapOfInterest.putIfAbsent(regionName, rie);
      if (result == null) {
        result = rie;
      }
    }
    return result;
  }

  private RegionInterestEntry readRegionInterests(String regionName, int interestType,
      boolean isDurable, boolean receiveUpdatesAsInvalidates) {
    ConcurrentMap mapOfInterest =
        getRegionToInterestsMap(interestType, isDurable, receiveUpdatesAsInvalidates);
    return (RegionInterestEntry) mapOfInterest.get(regionName);
  }

  /**
   * A Holder object for client's register interest, this is required when a client fails over to
   * another server and does register interest based on this Data structure
   *
   * @since GemFire 5.5
   *
   */
  protected static class FailoverInterestList {
    /**
     * Record of enumerated keys of interest.
     *
     * This list is maintained here in case an endpoint (server) bounces. In that case, a message
     * will be sent to the endpoint as soon as it has restarted.
     *
     * The keys in this Map are the full names of the regions. The values are instances of
     * {@link RegionInterestEntry}.
     */
    final ConcurrentMap<String, RegionInterestEntry> keysOfInterest = new ConcurrentHashMap<>();

    /**
     * Record of regular expression keys of interest.
     *
     * This list is maintained here in case an endpoint (server) bounces. In that case, a message
     * will be sent to the endpoint as soon as it has restarted.
     *
     * The keys in this Map are the full names of the regions. The values are instances of
     * {@link RegionInterestEntry}.
     */
    final ConcurrentMap<String, RegionInterestEntry> regexOfInterest = new ConcurrentHashMap<>();

    /**
     * Record of filtered keys of interest.
     *
     * This list is maintained here in case an endpoint (server) bounces. In that case, a message
     * will be sent to the endpoint as soon as it has restarted.
     *
     * The keys in this Map are the full names of the regions. The values are instances of
     * {@link RegionInterestEntry}.
     */
    final ConcurrentMap<String, RegionInterestEntry> filtersOfInterest = new ConcurrentHashMap<>();

    /**
     * Record of QOL keys of interest.
     *
     * This list is maintained here in case an endpoint (server) bounces. In that case, a message
     * will be sent to the endpoint as soon as it has restarted.
     *
     * The keys in this Map are the full names of the regions. The values are instances of
     * {@link RegionInterestEntry}.
     */
    final ConcurrentMap<String, RegionInterestEntry> queriesOfInterest = new ConcurrentHashMap<>();

    /**
     * Record of registered CQs
     *
     */
    final ConcurrentMap<String, RegionInterestEntry> cqsOfInterest = new ConcurrentHashMap<>();
  }

  /**
   * Description of the interests of a particular region.
   *
   *
   */
  public static class RegionInterestEntry {
    private final LocalRegion region;

    private final ConcurrentMap<Object, InterestResultPolicy> interests;

    RegionInterestEntry(LocalRegion r) {
      this.region = r;
      this.interests = new ConcurrentHashMap<>();
    }

    public LocalRegion getRegion() {
      return this.region;
    }

    public ConcurrentMap<Object, InterestResultPolicy> getInterests() {
      return this.interests;
    }
  }
}
