/*
 * 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_REMOTEQUERYSERVICE_H_
#define GEODE_REMOTEQUERYSERVICE_H_

#include <memory>
#include <string>

#include <ace/RW_Thread_Mutex.h>

#include <geode/QueryService.hpp>
#include <geode/internal/geode_globals.hpp>

#include "CqService.hpp"
#include "ThinClientCacheDistributionManager.hpp"
#include "statistics/StatisticsManager.hpp"

namespace apache {
namespace geode {
namespace client {

class CacheImpl;
class ThinClientPoolDM;
typedef std::map<std::string, bool> CqPoolsConnected;
class APACHE_GEODE_EXPORT RemoteQueryService
    : public QueryService,
      public std::enable_shared_from_this<RemoteQueryService> {
 public:
  explicit RemoteQueryService(CacheImpl* cptr,
                              ThinClientPoolDM* poolDM = nullptr);
  virtual ~RemoteQueryService() = default;

  void init();

  inline ACE_RW_Thread_Mutex& getLock() { return m_rwLock; }

  inline const volatile bool& invalid() { return m_invalid; }

  void close();

  std::shared_ptr<Query> newQuery(std::string querystring) override;

  virtual std::shared_ptr<CqQuery> newCq(
      std::string querystr, const std::shared_ptr<CqAttributes>& cqAttr,
      bool isDurable = false) override;

  virtual std::shared_ptr<CqQuery> newCq(
      std::string name, std::string querystr,
      const std::shared_ptr<CqAttributes>& cqAttr,
      bool isDurable = false) override;

  virtual void closeCqs() override;

  virtual QueryService::query_container_type getCqs() const override;

  virtual std::shared_ptr<CqQuery> getCq(
      const std::string& name) const override;

  virtual void executeCqs() override;

  virtual void stopCqs() override;

  virtual std::shared_ptr<CqServiceStatistics> getCqServiceStatistics()
      const override;

  void executeAllCqs(bool failover);

  virtual std::shared_ptr<CacheableArrayList> getAllDurableCqsFromServer()
      const override;

  /**
   * execute all cqs on the endpoint after failover
   */
  GfErrType executeAllCqs(TcrEndpoint* endpoint);
  void receiveNotification(TcrMessage* msg);
  void invokeCqConnectedListeners(ThinClientPoolDM* pool, bool connected);
  // For Lazy Cq Start-no use, no start
  inline void initCqService() {
    if (m_cqService == nullptr) {
      LOGFINE("RemoteQueryService: starting cq service");
      m_cqService = std::make_shared<CqService>(m_tccdm, m_statisticsFactory);
      LOGFINE("RemoteQueryService: started cq service");
    }
  }

 private:
  volatile bool m_invalid;
  mutable ACE_RW_Thread_Mutex m_rwLock;

  ThinClientBaseDM* m_tccdm;
  std::shared_ptr<CqService> m_cqService;
  CqPoolsConnected m_CqPoolsConnected;
  statistics::StatisticsFactory* m_statisticsFactory;
};

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

#endif  // GEODE_REMOTEQUERYSERVICE_H_
