/*
 * 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.
 */

#pragma once

#ifndef GEODE_CACHEIMPL_H_
#define GEODE_CACHEIMPL_H_

#include <atomic>
#include <memory>
#include <mutex>
#include <string>

#include <geode/Cache.hpp>
#include <geode/PoolManager.hpp>
#include <geode/TypeRegistry.hpp>
#include <geode/internal/geode_globals.hpp>

#include "CachePerfStats.hpp"
#include "ClientProxyMembershipIDFactory.hpp"
#include "DistributedSystem.hpp"
#include "MemberListForVersionStamp.hpp"
#include "PdxTypeRegistry.hpp"
#include "RemoteQueryService.hpp"
#include "TcrEndpoint.hpp"
#include "ThreadPool.hpp"
#include "util/synchronized_map.hpp"

#define DEFAULT_LRU_MAXIMUM_ENTRIES 100000
/** @todo period '.' consistency */
/** @todo fix returns to param documentation of result ptr... */

/**
 * @file
 */

namespace apache {
namespace geode {
namespace client {

class CacheFactory;
class CacheStatistics;
class ExpiryTaskManager;
class PdxTypeRegistry;
class Pool;
class RegionAttributes;
class SerializationRegistry;
class ThreadPool;
class EvictionController;
class TcrConnectionManager;

/**
 * @class Cache Cache.hpp
 * Geode's implementation of a distributed C++ Cache.
 *
 * Caches are obtained from methods on the {@link CacheFactory} class.
 * <p>
 * When a cache is created a {@link DistributedSystem} must be specified.
 * This system tells the cache where to find other caches on the network
 * and how to communicate with them.
 * <p>
 * When a cache will no longer be used, it should be {@link #close closed}.
 * Once it {@link Cache::isClosed is closed} any attempt to use it

 * will cause a <code>CacheClosedException</code> to be thrown.
 *
 * <p>A cache can have multiple root regions, each with a different name.
 *
 */

class APACHE_GEODE_EXPORT CacheImpl {
 public:
  CacheImpl(const CacheImpl&) = delete;
  CacheImpl& operator=(const CacheImpl&) = delete;
  // added netDown and revive for tests to simulate client crash and network
  // drop
  void netDown();
  void revive();
  void setClientCrashTEST();

  // For PrSingleHop C++unit testing.
  void setNetworkHopFlag(bool networkhopflag) { m_networkhop = networkhopflag; }

  bool getAndResetNetworkHopFlag() { return m_networkhop.exchange(false); }

  int8_t getAndResetServerGroupFlag() { return m_serverGroupFlag.exchange(0); }

  void setServerGroupFlag(int8_t serverGroupFlag) {
    m_serverGroupFlag = serverGroupFlag;
  }

  std::shared_ptr<MemberListForVersionStamp> getMemberListForVersionStamp();

  /** Returns the name of this cache.
   * @return the string name of this cache
   */
  const std::string& getName() const;

  /**
   * Indicates if this cache has been closed.
   * After a new cache object is created, this method returns false;
   * After the close is called on this cache object, this method
   * returns true.
   *
   * @return true, if this cache is closed; false, otherwise
   */
  bool isClosed() const;

  /**
   * Returns the distributed system that this cache was
   * {@link CacheFactory::create created} with.
   */
  DistributedSystem& getDistributedSystem();

  /**
   * Returns the type registry that this cache was
   * {@link CacheFactory::create created} with.
   */
  TypeRegistry& getTypeRegistry();

  /**
   * Terminates this object cache and releases all the local resources.
   * After this cache is closed, any further
   * method call on this cache or any region object will throw
   * <code>CacheClosedException</code>, unless otherwise noted.
   * @param keepalive whether to keep a durable client's queue alive.
   * @throws CacheClosedException,  if the cache is already closed.
   */
  void close(bool keepalive = false);

  /**
   * Creates a region  using the specified
   * RegionAttributes.
   *
   * @param name the name of the region to create
   * @param aRegionAttributes the attributes of the root region
   * @todo change return to param for regionPtr...
   * @param regionPtr the pointer object pointing to the returned region object
   * when the function returns
   * @throws InvalidArgumentException if the attributePtr is nullptr.
   * @throws RegionExistsException if a region is already in
   * this cache
   * @throws CacheClosedException if the cache is closed
   * @throws OutOfMemoryException if the memory allocation failed
   * @throws NotConnectedException if the cache is not connected
   * @throws UnknownException otherwise
   */
  void createRegion(std::string name, const RegionAttributes& aRegionAttributes,
                    std::shared_ptr<Region>& regionPtr);

  /**
   * Return the existing region (or subregion) with the specified
   * path that already exists or is already mapped into the cache.
   * Whether or not the path starts with a forward slash it is interpreted as a
   * full path starting at a root.
   *
   * @param path the path to the region
   * @return the Region or null if not found
   * @throws IllegalArgumentException if path is null, the empty string, or "/"
   */
  std::shared_ptr<Region> getRegion(const std::string& path);

  /**
   * Returns a set of root regions in the cache. Does not cause any
   * shared regions to be mapped into the cache. This set is a snapshot and
   * is not backed by the Cache. The regions passed in are cleared.
   */
  std::vector<std::shared_ptr<Region>> rootRegions();

  RegionFactory createRegionFactory(RegionShortcut preDefinedRegion);

  void initializeDeclarativeCache(const std::string& cacheXml);

  std::shared_ptr<CacheTransactionManager> getCacheTransactionManager();

  ~CacheImpl();

  CacheImpl(Cache* c, const std::shared_ptr<Properties>& dsProps,
            bool ignorePdxUnreadFields, bool readPdxSerialized,
            const std::shared_ptr<AuthInitialize>& authInitialize);

  void initServices();
  EvictionController* getEvictionController();

  ExpiryTaskManager& getExpiryTaskManager() { return *m_expiryTaskManager; }

  ClientProxyMembershipIDFactory& getClientProxyMembershipIDFactory() {
    return m_clientProxyMembershipIDFactory;
  }

  Cache* getCache() const { return m_cache; }

  TcrConnectionManager& tcrConnectionManager() {
    return *m_tcrConnectionManager;
  }

  void removeRegion(const std::string& name);

  std::shared_ptr<QueryService> getQueryService(bool noInit = false);

  std::shared_ptr<QueryService> getQueryService(const char* poolName);

  std::shared_ptr<RegionInternal> createRegion_internal(
      const std::string& name,
      const std::shared_ptr<RegionInternal>& rootRegion,
      const RegionAttributes& attrs,
      const std::shared_ptr<CacheStatistics>& csptr, bool shared);

  /**
   * Send the "client ready" message to the server.
   */
  void readyForEvents();

  bool isPoolInMultiuserMode(const Region& region) const;

  //  TESTING: Durable clients. Not thread safe.
  bool getEndpointStatus(const std::string& endpoint);

  // TESTING: Endpoint disconnections
  int getNumberOfTimeEndpointDisconnected(const std::string& endpoint,
                                          const std::string& poolName);

  void processMarker();

  // Pool helpers for unit tests
  int getPoolSize(const std::string& poolName);

  bool getPdxIgnoreUnreadFields() {
    this->throwIfClosed();

    return m_ignorePdxUnreadFields;
  }

  void setPdxIgnoreUnreadFields(bool ignore) {
    m_ignorePdxUnreadFields = ignore;
  }

  void setPdxReadSerialized(bool val) { m_readPdxSerialized = val; }

  bool getPdxReadSerialized() {
    this->throwIfClosed();
    return m_readPdxSerialized;
  }

  static std::map<std::string, RegionAttributes> getRegionShortcut();

  std::shared_ptr<PdxTypeRegistry> getPdxTypeRegistry() const;

  std::shared_ptr<SerializationRegistry> getSerializationRegistry() const;
  inline CachePerfStats& getCachePerfStats() { return *m_cacheStats; }

  PoolManager& getPoolManager() const {
    this->throwIfClosed();
    return *m_poolManager;
  }

  const std::shared_ptr<Pool>& getDefaultPool() {
    return m_poolManager->getDefaultPool();
  }

  SystemProperties& getSystemProperties() const {
    this->throwIfClosed();

    return m_distributedSystem.getSystemProperties();
  }

  ThreadPool& getThreadPool();

  inline const std::shared_ptr<AuthInitialize>& getAuthInitialize() {
    return m_authInitialize;
  }

  statistics::StatisticsManager& getStatisticsManager() const {
    return *(m_statisticsManager.get());
  }

  DataOutput createDataOutput() const;

  DataOutput createDataOutput(Pool* pool) const;

  DataInput createDataInput(const uint8_t* buffer, size_t len) const;

  DataInput createDataInput(const uint8_t* buffer, size_t len,
                            Pool* pool) const;

  PdxInstanceFactory createPdxInstanceFactory(const std::string& className,
                                              bool expectDomainClass) const;

  AuthenticatedView createAuthenticatedView(
      std::shared_ptr<Properties> userSecurityProperties,
      const std::string& poolName);

  bool doIfDestroyNotPending(std::function<void()>);

  bool isKeepAlive();

 private:
  std::atomic<bool> m_networkhop;
  std::atomic<int8_t> m_serverGroupFlag;
  bool m_ignorePdxUnreadFields;
  bool m_readPdxSerialized;
  std::unique_ptr<ExpiryTaskManager> m_expiryTaskManager;

  // CachePerfStats
  CachePerfStats* m_cacheStats;

  std::unique_ptr<PoolManager> m_poolManager;

  std::unique_ptr<statistics::StatisticsManager> m_statisticsManager;

  enum RegionKind {
    CPP_REGION,
    THINCLIENT_REGION,
    THINCLIENT_HA_REGION,
    THINCLIENT_POOL_REGION
  };

  RegionKind getRegionKind(RegionAttributes rattrs) const;

  void sendNotificationCloseMsgs();

  void validateRegionAttributes(const std::string& name,
                                const RegionAttributes& attrs) const;

  inline void getSubRegions(
      std::unordered_map<std::string, std::shared_ptr<Region>>& srm) {
    auto&& lock = m_regions.make_lock<std::lock_guard>();
    if (m_regions.empty()) return;
    srm.insert(m_regions.begin(), m_regions.end());
  }

  std::shared_ptr<Region> findRegion(const std::string& name);

  void setCache(Cache* cache);

  bool m_closed;
  bool m_initialized;

  DistributedSystem m_distributedSystem;
  ClientProxyMembershipIDFactory m_clientProxyMembershipIDFactory;
  synchronized_map<std::unordered_map<std::string, std::shared_ptr<Region>>,
                   std::recursive_mutex>
      m_regions;
  Cache* m_cache;
  std::unique_ptr<EvictionController> m_evictionController;
  TcrConnectionManager* m_tcrConnectionManager;
  std::shared_ptr<RemoteQueryService> m_remoteQueryServicePtr;
  std::recursive_mutex m_destroyCacheMutex;
  volatile bool m_destroyPending;
  volatile bool m_initDone;
  std::mutex m_initDoneLock;
  std::shared_ptr<AdminRegion> m_adminRegion;
  std::shared_ptr<CacheTransactionManager> m_cacheTXManager;

  MemberListForVersionStamp& m_memberListForVersionStamp;
  std::shared_ptr<SerializationRegistry> m_serializationRegistry;
  std::shared_ptr<PdxTypeRegistry> m_pdxTypeRegistry;
  ThreadPool m_threadPool;
  const std::shared_ptr<AuthInitialize> m_authInitialize;
  std::unique_ptr<TypeRegistry> m_typeRegistry;
  bool m_keepAlive;

  inline void throwIfClosed() const {
    if (m_closed) {
      throw CacheClosedException("Cache is closed.");
    }
  }

  friend class CacheFactory;
  friend class Cache;
  friend class DistributedSystemImpl;
  friend class PdxInstanceFactory;
};
}  // namespace client
}  // namespace geode
}  // namespace apache

#endif  // GEODE_CACHEIMPL_H_
