/*
 * 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_THINCLIENTPOOLDM_H_
#define GEODE_THINCLIENTPOOLDM_H_

#include <string>
#include <memory>
#include <set>
#include <vector>

#include <ace/Semaphore.h>

#include <geode/Pool.hpp>
#include <geode/ResultCollector.hpp>

#include "ThinClientBaseDM.hpp"
#include "PoolAttributes.hpp"
#include "ThinClientLocatorHelper.hpp"
#include "RemoteQueryService.hpp"
#include "Task.hpp"
#include "PoolStatistics.hpp"
#include "FairQueue.hpp"
#include "TcrPoolEndPoint.hpp"
#include "ThinClientRegion.hpp"
#include "ExecutionImpl.hpp"
#include "ClientMetadataService.hpp"
#include "ThreadPool.hpp"
#include "ThinClientStickyManager.hpp"
#include "TXState.hpp"
#include "UserAttributes.hpp"
#include "NonCopyable.hpp"

namespace apache {
namespace geode {

namespace statistics {

class PoolStatsSampler;

}  // namespace statistics

namespace client {


class CacheImpl;
class FunctionExecution;

/* adongre
 * CID 28731: Other violation (MISSING_COPY)
 * Class "apache::geode::client::ThinClientPoolDM" owns resources that are
 managed in its
 * constructor and destructor but has no user-written copy constructor.
 * FIX : Make the class no Copyablez

 * CID 28717: Other violation (MISSING_ASSIGN)
 * Class "apache::geode::client::ThinClientPoolDM" owns resources that are
 * managed in its constructor and destructor but has no user-written assignment
 operator.
 * Fix : Make the class Non Assinable
 */
class ThinClientPoolDM
    : public ThinClientBaseDM,
      public Pool,
      public FairQueue<TcrConnection, ACE_Recursive_Thread_Mutex>,
      private NonCopyable,
      private NonAssignable {
 public:
  ThinClientPoolDM(const char* name, std::shared_ptr<PoolAttributes> poolAttrs,
                   TcrConnectionManager& connManager);

  virtual void init();

  const std::string& getName() const { return m_poolName; }

  virtual GfErrType sendSyncRequest(TcrMessage& request, TcrMessageReply& reply,
                                    bool attemptFailover = true,
                                    bool isBGThread = false);
  GfErrType sendSyncRequest(
      TcrMessage& request, TcrMessageReply& reply, bool attemptFailover,
      bool isBGThread,
      const std::shared_ptr<BucketServerLocation>& serverLocation);

  // Pool Specific Fns.
  virtual const std::shared_ptr<CacheableStringArray> getLocators() const;
  virtual const std::shared_ptr<CacheableStringArray> getServers();
  virtual void destroy(bool keepalive = false);
  virtual bool isDestroyed() const;
  virtual std::shared_ptr<QueryService> getQueryService();
  virtual std::shared_ptr<QueryService> getQueryServiceWithoutCheck();
  virtual bool isEndpointAttached(TcrEndpoint* ep);
  GfErrType sendRequestToAllServers(
      const char* func, uint8_t getResult, std::chrono::milliseconds timeout,
      std::shared_ptr<Cacheable> args, std::shared_ptr<ResultCollector>& rs,
      std::shared_ptr<CacheableString>& exceptionPtr);

  GfErrType sendRequestToEP(const TcrMessage& request, TcrMessageReply& reply,
                            TcrEndpoint* currentEndpoint);
  void addConnection(TcrConnection* conn);

  TcrEndpoint* addEP(ServerLocation& serverLoc);

  TcrEndpoint* addEP(const char* endpointName);
  virtual int pingServer(volatile bool& isRunning);
  virtual int updateLocatorList(volatile bool& isRunning);
  virtual int cliCallback(volatile bool& isRunning);
  virtual void pingServerLocal();

  virtual ~ThinClientPoolDM() {
    destroy();
    _GEODE_SAFE_DELETE(m_locHelper);
    _GEODE_SAFE_DELETE(m_stats);
    _GEODE_SAFE_DELETE(m_clientMetadataService);
    _GEODE_SAFE_DELETE(m_manager);
  }
  // void updateQueue(const char* regionPath) ;
  ClientProxyMembershipID* getMembershipId() { return m_memId.get(); }
  virtual void processMarker(){};
  virtual bool checkDupAndAdd(std::shared_ptr<EventId> eventid) {
    return m_connManager.checkDupAndAdd(eventid);
  }
  ACE_Recursive_Thread_Mutex& getPoolLock() { return getQueueLock(); }
  void reducePoolSize(int num);
  void removeEPConnections(int numConn, bool triggerManagerConn = true);
  void removeEPConnections(TcrEndpoint* ep);
  GfErrType createPoolConnection(TcrConnection*& conn,
                                 std::set<ServerLocation>& excludeServers,
                                 bool& maxConnLimit,
                                 const TcrConnection* currentServer = nullptr);
  ThinClientLocatorHelper* getLocatorHelper() {
    return m_locHelper;
  }
  virtual void releaseThreadLocalConnection();
  virtual void setThreadLocalConnection(TcrConnection* conn);
  bool excludeConnection(TcrConnection*, std::set<ServerLocation>&);
  void incRegionCount();
  void decRegionCount();

  virtual void setStickyNull(bool isBGThread) {
    if (!isBGThread) m_manager->setStickyConnection(nullptr, false);
  };

  virtual bool canItBeDeletedNoImpl(TcrConnection* conn);

  void updateNotificationStats(bool isDeltaSuccess, long timeInNanoSecond);

  virtual bool isSecurityOn() { return m_isSecurityOn || m_isMultiUserMode; }

  virtual bool isMultiUserMode() { return m_isMultiUserMode; }

  virtual void sendUserCacheCloseMessage(bool keepAlive);

  virtual inline PoolStats& getStats() { return *m_stats; }

  size_t getNumberOfEndPoints() const { return m_endpoints.current_size(); }

  int32_t GetPDXIdForType(std::shared_ptr<Serializable> pdxType);

  std::shared_ptr<Serializable> GetPDXTypeById(int32_t typeId);

  void AddPdxType(std::shared_ptr<Serializable> pdxType, int32_t pdxTypeId);

  int32_t GetEnumValue(std::shared_ptr<Serializable> enumInfo);
  std::shared_ptr<Serializable> GetEnum(int32_t val);
  void AddEnum(std::shared_ptr<Serializable> enumInfo, int enumVal);

  // Tries to get connection to a endpoint. If no connection is available, it
  // tries
  // to create one. If it fails to create one,  it returns a connection to any
  // other
  // server after failing over the transaction to that server
  GfErrType getConnectionToAnEndPoint(std::string epNameStr,
                                      TcrConnection*& conn);

  virtual inline bool isSticky() { return m_sticky; }
  virtual TcrEndpoint* getEndPoint(
      const std::shared_ptr<BucketServerLocation>& serverLocation,
      int8_t& version, std::set<ServerLocation>& excludeServers);

  ClientMetadataService* getClientMetaDataService() {
    return m_clientMetadataService;
  }
  void setPrimaryServerQueueSize(int queueSize) {
    m_primaryServerQueueSize = queueSize;
  }
  int getPrimaryServerQueueSize() const { return m_primaryServerQueueSize; }

 protected:
  ThinClientStickyManager* m_manager;
  std::vector<std::string> m_canonicalHosts;
  ACE_Map_Manager<std::string, TcrEndpoint*, ACE_Recursive_Thread_Mutex>
      m_endpoints;
  ACE_Recursive_Thread_Mutex m_endpointsLock;
  ACE_Recursive_Thread_Mutex m_endpointSelectionLock;
  std::string m_poolName;
  PoolStats* m_stats;
  bool m_sticky;
  // PoolStats * m_stats;
  // PoolStatType* m_poolStatType;
  void netDown();
  ACE_Semaphore m_updateLocatorListSema;
  ACE_Semaphore m_pingSema;
  ACE_Semaphore m_cliCallbackSema;
  volatile bool m_isDestroyed;
  volatile bool m_destroyPending;
  volatile bool m_destroyPendingHADM;
  void checkRegions();
  std::shared_ptr<RemoteQueryService> m_remoteQueryServicePtr;
  virtual void startBackgroundThreads();
  virtual void stopPingThread();
  virtual void stopUpdateLocatorListThread();
  virtual void stopCliCallbackThread();
  virtual void cleanStickyConnections(volatile bool& isRunning);
  virtual TcrConnection* getConnectionFromQueue(bool timeout, GfErrType* error,
                                                std::set<ServerLocation>&,
                                                bool& maxConnLimit);

  virtual void putInQueue(TcrConnection* conn, bool isBGThread,
                          bool isTransaction = false);

  GfErrType doFailover(TcrConnection* conn);

  virtual bool canItBeDeleted(TcrConnection* conn);

  virtual TcrConnection* getConnectionFromQueueW(
      GfErrType* error, std::set<ServerLocation>& excludeServers,
      bool isBGThread, TcrMessage& request, int8_t& version, bool& match,
      bool& connFound,
      const std::shared_ptr<BucketServerLocation>& serverLocation = nullptr);

  TcrConnection* getFromEP(TcrEndpoint* theEP);
  virtual TcrEndpoint* getSingleHopServer(
      TcrMessage& request, int8_t& version,
      std::shared_ptr<BucketServerLocation>& serverLocation,
      std::set<ServerLocation>& excludeServers);
  // Create pool connection to a specified endpoint.
  GfErrType createPoolConnectionToAEndPoint(TcrConnection*& conn,
                                            TcrEndpoint* theEP,
                                            bool& maxConnLimit,
                                            bool appThreadrequest = false);

 private:
  bool hasExpired(TcrConnection* conn);

  std::shared_ptr<Properties> getCredentials(TcrEndpoint* ep);
  GfErrType sendUserCredentials(std::shared_ptr<Properties> credentials,
                                TcrConnection*& conn, bool isBGThread,
                                bool& isServerException);
  TcrConnection* getConnectionInMultiuserMode(
      std::shared_ptr<UserAttributes> userAttribute);

  // get endpoint using the endpoint string
  TcrEndpoint* getEndPoint(std::string epNameStr);

  bool m_isSecurityOn;
  bool m_isMultiUserMode;

  TcrConnection* getUntil(std::chrono::microseconds& sec, GfErrType* error,
                          std::set<ServerLocation>& excludeServers,
                          bool& maxConnLimit) {
    bool isClosed;
    TcrConnection* mp =
        getNoGetLock(isClosed, error, excludeServers, maxConnLimit);

    if (mp == nullptr && !isClosed) {
      mp = getUntilWithToken(sec, isClosed, &excludeServers);
    }

    return mp;
  }

  TcrConnection* getNoGetLock(bool& isClosed, GfErrType* error,
                              std::set<ServerLocation>& excludeServers,
                              bool& maxConnLimit);
  bool exclude(TcrConnection* conn, std::set<ServerLocation>& excludeServers);
  void deleteAction() { removeEPConnections(1); }

  std::string selectEndpoint(std::set<ServerLocation>&,
                             const TcrConnection* currentServer = nullptr);
  // TODO global - m_memId was volatile
  std::unique_ptr<ClientProxyMembershipID> m_memId;
  virtual TcrEndpoint* createEP(const char* endpointName) {
    return new TcrPoolEndPoint(endpointName, m_connManager.getCacheImpl(),
                               m_connManager.m_failoverSema,
                               m_connManager.m_cleanupSema,
                               m_connManager.m_redundancySema, this);
  }
  virtual void removeCallbackConnection(TcrEndpoint*) {}

  bool excludeServer(std::string, std::set<ServerLocation>&);

  ThinClientLocatorHelper* m_locHelper;

  std::atomic<int32_t> m_poolSize;  // Actual Size of Pool
  int m_numRegions;

  // for selectEndpoint
  unsigned m_server;

  // Manage Connection thread
  ACE_Semaphore m_connSema;
  Task<ThinClientPoolDM>* m_connManageTask;
  Task<ThinClientPoolDM>* m_pingTask;
  Task<ThinClientPoolDM>* m_updateLocatorListTask;
  Task<ThinClientPoolDM>* m_cliCallbackTask;
  long m_pingTaskId;
  ExpiryTaskManager::id_type m_updateLocatorListTaskId;
  long m_connManageTaskId;
  int manageConnections(volatile bool& isRunning);
  int doPing(const ACE_Time_Value&, const void*);
  int doUpdateLocatorList(const ACE_Time_Value&, const void*);
  int doManageConnections(const ACE_Time_Value&, const void*);
  int manageConnectionsInternal(volatile bool& isRunning);
  void cleanStaleConnections(volatile bool& isRunning);
  void restoreMinConnections(volatile bool& isRunning);
  std::atomic<int32_t> m_clientOps;  // Actual Size of Pool
  statistics::PoolStatsSampler* m_PoolStatsSampler;
  ClientMetadataService* m_clientMetadataService;
  friend class CacheImpl;
  friend class ThinClientStickyManager;
  friend class FunctionExecution;
  static const char* NC_Ping_Thread;
  static const char* NC_MC_Thread;
  int m_primaryServerQueueSize;
};

class FunctionExecution : public PooledWork<GfErrType> {
  ThinClientPoolDM* m_poolDM;
  TcrEndpoint* m_ep;
  const char* m_func;
  uint8_t m_getResult;
  std::chrono::milliseconds m_timeout;
  std::shared_ptr<Cacheable> m_args;
  GfErrType m_error;
  std::shared_ptr<ResultCollector>* m_rc;
  std::shared_ptr<ACE_Recursive_Thread_Mutex> m_resultCollectorLock;
  std::shared_ptr<CacheableString> exceptionPtr;
  std::shared_ptr<UserAttributes> m_userAttr;

 public:
  FunctionExecution() {
    m_poolDM = nullptr;
    m_ep = nullptr;
    m_func = nullptr;
    m_getResult = 0;
    m_error = GF_NOERR;
    m_rc = nullptr;
    m_resultCollectorLock = nullptr;
    m_userAttr = nullptr;
  }

  ~FunctionExecution() {}

  std::shared_ptr<CacheableString> getException() { return exceptionPtr; }

  void setParameters(const char* func, uint8_t getResult,
                     std::chrono::milliseconds timeout,
                     std::shared_ptr<Cacheable> args, TcrEndpoint* ep,
                     ThinClientPoolDM* poolDM,
                     const std::shared_ptr<ACE_Recursive_Thread_Mutex>& rCL,
                     std::shared_ptr<ResultCollector>* rs,
                     std::shared_ptr<UserAttributes> userAttr) {
    exceptionPtr = nullptr;
    m_resultCollectorLock = rCL;
    m_rc = rs;
    m_error = GF_NOTCON;
    m_func = func;
    m_getResult = getResult;
    m_timeout = timeout;
    m_args = args;
    m_ep = ep;
    m_poolDM = poolDM;
    m_userAttr = userAttr;

    // m_functionExecutionTask = new Task<FunctionExecution>(this,
    //&FunctionExecution::execute);
  }

  GfErrType execute(void) {
    // TSSUserAttributesWrapper::s_geodeTSSUserAttributes->setUserAttributes(m_userAttr);
    GuardUserAttributes gua;

    if (m_userAttr != nullptr)
      gua.setAuthenticatedView(m_userAttr->getAuthenticatedView());

    std::string funcName(m_func);
    TcrMessageExecuteFunction request(
        new DataOutput(m_poolDM->getConnectionManager()
                           .getCacheImpl()
                           ->createDataOutput()),
        funcName, m_args, m_getResult, m_poolDM, m_timeout);
    TcrMessageReply reply(true, m_poolDM);
    ChunkedFunctionExecutionResponse* resultProcessor(
        new ChunkedFunctionExecutionResponse(reply, (m_getResult & 2) == 2,
                                             *m_rc, m_resultCollectorLock));
    reply.setChunkedResultHandler(resultProcessor);
    reply.setTimeout(m_timeout);
    reply.setDM(m_poolDM);

    LOGDEBUG(
        "ThinClientPoolDM::sendRequestToAllServer sendRequest on endpoint[%s]!",
        m_ep->name().c_str());

    m_error = m_poolDM->sendRequestToEP(request, reply, m_ep);
    m_error = m_poolDM->handleEPError(m_ep, reply, m_error);
    if (m_error != GF_NOERR) {
      if (m_error == GF_NOTCON || m_error == GF_IOERR) {
        delete resultProcessor;
        resultProcessor = nullptr;
        return GF_NOERR;  // if server is unavailable its not an error for
                          // functionexec OnServers() case
      }
      LOGDEBUG(
          "FunctionExecution::execute failed on endpoint[%s]!. Error = %d ",
          m_ep->name().c_str(), m_error);
      if (reply.getMessageType() == TcrMessage::EXCEPTION) {
        exceptionPtr = CacheableString::create(reply.getException());
      }

      delete resultProcessor;
      resultProcessor = nullptr;
      return m_error;
    } else if (reply.getMessageType() == TcrMessage::EXCEPTION ||
               reply.getMessageType() == TcrMessage::EXECUTE_FUNCTION_ERROR) {
      m_error = ThinClientRegion::handleServerException("Execute",
                                                        reply.getException());
      exceptionPtr = CacheableString::create(reply.getException());
    }
    if (resultProcessor->getResult() == true) {
    }
    delete resultProcessor;
    resultProcessor = nullptr;
    return m_error;
  }
};

class OnRegionFunctionExecution : public PooledWork<GfErrType> {
  std::shared_ptr<BucketServerLocation> m_serverLocation;
  TcrMessage* m_request;
  TcrMessageReply* m_reply;
  bool m_isBGThread;
  ThinClientPoolDM* m_poolDM;
  std::string m_func;
  uint8_t m_getResult;
  std::chrono::milliseconds m_timeout;
  std::shared_ptr<Cacheable> m_args;
  std::shared_ptr<CacheableHashSet> m_routingObj;
  std::shared_ptr<ResultCollector> m_rc;
  TcrChunkedResult* m_resultCollector;
  std::shared_ptr<ACE_Recursive_Thread_Mutex> m_resultCollectorLock;
  std::shared_ptr<UserAttributes> m_userAttr;
  const Region* m_region;
  bool m_allBuckets;

 public:
  OnRegionFunctionExecution(
      std::string func, const Region* region, std::shared_ptr<Cacheable> args,
      std::shared_ptr<CacheableHashSet> routingObj, uint8_t getResult,
      std::chrono::milliseconds timeout, ThinClientPoolDM* poolDM,
      const std::shared_ptr<ACE_Recursive_Thread_Mutex>& rCL,
      std::shared_ptr<ResultCollector> rs,
      std::shared_ptr<UserAttributes> userAttr, bool isBGThread,
      const std::shared_ptr<BucketServerLocation>& serverLocation,
      bool allBuckets)
      : m_serverLocation(serverLocation),
        m_isBGThread(isBGThread),
        m_poolDM(poolDM),
        m_func(func),
        m_getResult(getResult),
        m_timeout(timeout),
        m_args(args),
        m_routingObj(routingObj),
        m_rc(rs),
        m_resultCollectorLock(rCL),
        m_userAttr(userAttr),
        m_region(region),
        m_allBuckets(allBuckets) {
    m_request = new TcrMessageExecuteRegionFunctionSingleHop(
        new DataOutput(m_poolDM->getConnectionManager()
                           .getCacheImpl()
                           ->createDataOutput()),
        m_func, m_region, m_args, m_routingObj, m_getResult, nullptr,
        m_allBuckets, timeout, m_poolDM);
    m_reply = new TcrMessageReply(true, m_poolDM);
    m_resultCollector = new ChunkedFunctionExecutionResponse(
        *m_reply, (m_getResult & 2) == 2, m_rc, m_resultCollectorLock);
    m_reply->setChunkedResultHandler(m_resultCollector);
    m_reply->setTimeout(m_timeout);
    m_reply->setDM(m_poolDM);
  }

  ~OnRegionFunctionExecution() {
    delete m_request;
    delete m_reply;
    delete m_resultCollector;
  }

  TcrMessage* getReply() { return m_reply; }

  std::shared_ptr<CacheableHashSet> getFailedNode() {
    return m_reply->getFailedNode();
  }

  ChunkedFunctionExecutionResponse* getResultCollector() {
    return static_cast<ChunkedFunctionExecutionResponse*>(m_resultCollector);
  }

  GfErrType execute(void) {
    GuardUserAttributes gua;

    if (m_userAttr != nullptr)
      gua.setAuthenticatedView(m_userAttr->getAuthenticatedView());

    return m_poolDM->sendSyncRequest(*m_request, *m_reply, !(m_getResult & 1),
                                     m_isBGThread, m_serverLocation);
  }
};

}  // namespace client
}  // namespace geode
}  // namespace apache

#endif  // GEODE_THINCLIENTPOOLDM_H_
