/*
 * 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_MAPENTRY_H_
#define GEODE_MAPENTRY_H_

#include <atomic>
#include <memory>
#include <utility>

#include <geode/CacheableKey.hpp>
#include <geode/ExceptionTypes.hpp>
#include <geode/Serializable.hpp>
#include <geode/internal/geode_globals.hpp>

#include "CacheImpl.hpp"
#include "CacheableToken.hpp"
#include "ExpiryTaskManager.hpp"
#include "RegionInternal.hpp"
#include "VersionStamp.hpp"

namespace apache {
namespace geode {
namespace client {

class MapEntry;
class MapEntryImpl;
class LRUEntryProperties;
class CacheImpl;

/**
 * @brief This class encapsulates expiration specific properties for
 *   a MapEntry.
 */
class APACHE_GEODE_EXPORT ExpEntryProperties {
 public:
  typedef std::chrono::system_clock::time_point time_point;

  inline explicit ExpEntryProperties(ExpiryTaskManager* expiryTaskManager)
      : m_lastAccessTime(0),
        m_lastModifiedTime(0),
        m_expiryTaskId(-1),
        m_expiryTaskManager(expiryTaskManager) {
    // The reactor always gives +ve id while scheduling.
    // -1 will indicate that an expiry task has not been scheduled
    // for this entry. // TODO confirm
  }

  inline time_point getLastAccessTime() const {
    return time_point(std::chrono::system_clock::duration(m_lastAccessTime));
  }

  inline time_point getLastModifiedTime() const {
    return time_point(std::chrono::system_clock::duration(m_lastModifiedTime));
  }

  //  moved time initialization outside of constructor to avoid
  // the costly gettimeofday call in MapSegment spinlock
  inline void initStartTime() {
    time_point currentTime = std::chrono::system_clock::now();
    m_lastAccessTime = currentTime.time_since_epoch().count();
    m_lastModifiedTime = currentTime.time_since_epoch().count();
  }

  inline void updateLastAccessTime(time_point currTime) {
    m_lastAccessTime = currTime.time_since_epoch().count();
  }

  inline void updateLastModifiedTime(time_point currTime) {
    m_lastModifiedTime = currTime.time_since_epoch().count();
  }

  inline void setExpiryTaskId(ExpiryTaskManager::id_type id) {
    m_expiryTaskId = id;
  }

  inline ExpiryTaskManager::id_type getExpiryTaskId() const {
    return m_expiryTaskId;
  }

  inline void cancelExpiryTaskId(
      const std::shared_ptr<CacheableKey>& key) const {
    LOGDEBUG("Cancelling expiration task for key [%s] with id [%z]",
             Utils::nullSafeToString(key).c_str(), m_expiryTaskId);
    m_expiryTaskManager->cancelTask(m_expiryTaskId);
  }

 protected:
  // this constructor deliberately skips initializing any fields
  inline explicit ExpEntryProperties(bool)
      : m_lastAccessTime(0), m_lastModifiedTime(0) {}

 private:
  /** last access time in secs, 32bit.. */
  std::atomic<time_point::duration::rep> m_lastAccessTime;
  /** last modified time in secs, 32bit.. */
  std::atomic<time_point::duration::rep> m_lastModifiedTime;
  /** The expiry task id for this particular entry.. **/
  ExpiryTaskManager::id_type m_expiryTaskId;
  ExpiryTaskManager* m_expiryTaskManager;
};

/**
 * @brief Interface class for region mapped entry value.
 */
class APACHE_GEODE_EXPORT MapEntry {
 public:
  virtual ~MapEntry() {}

  virtual void getKey(std::shared_ptr<CacheableKey>& result) const = 0;
  virtual void getValue(std::shared_ptr<Cacheable>& result) const = 0;
  virtual void setValue(const std::shared_ptr<Cacheable>& value) = 0;
  virtual std::shared_ptr<MapEntryImpl> getImplPtr() = 0;

  virtual LRUEntryProperties& getLRUProperties() = 0;
  virtual ExpEntryProperties& getExpProperties() = 0;
  virtual VersionStamp& getVersionStamp() = 0;

  /**
   * Adds a tracker to this MapEntry for any updates.
   * Returns the current update sequence number of this entry.
   * Returns by reference any updated MapEntry to be rebound while an
   * unchanged return value implies this MapEntry should be continued with.
   * Note that the contract says that the return value should not be
   * touched if this MapEntry is to be continued with.
   *
   * The design of tracking is thus:
   * Each entry will have two fields, one indicating the current number of
   * operations tracking this entry, and second indicating the sequence
   * number for number of updates since tracking was started. The idea is
   * to start tracking an entry before going for a long remote operation
   * and check whether the update sequence has remained unchanged upon
   * return. If the entry has been updated in the interim period then
   * the current update is not applied. When the number of operations
   * tracking an entry goes down to zero, then the update sequence number
   * is also reset to zero.
   */
  virtual int addTracker(std::shared_ptr<MapEntry>& newEntry) = 0;

  /**
   * Removes a tracker for this MapEntry and returns a pair:
   *  1) the first element of the pair is a boolean that indicates whether
   *     or not the entry should be replaced with the underlying MapEntryImpl
   *     object in the map
   *  2) the second element is the updated number of trackers for this entry
   */
  virtual std::pair<bool, int> removeTracker() = 0;

  /**
   * Increment the number of updates to this entry.
   * Returns the current update sequence number of this entry.
   * Returns by reference any updated MapEntry to be rebound while an
   * unchanged return value implies this MapEntry should be continued with.
   * Note that the contract says that the return value should not be
   * touched if this MapEntry is to be continued with.
   */
  virtual int incrementUpdateCount(std::shared_ptr<MapEntry>& newEntry) = 0;

  /**
   * Get the current tracking number of this entry. A return value of zero
   * indicates that the entry is not being tracked.
   */
  virtual int getTrackingNumber() const = 0;

  /**
   * Get the current number of updates since tracking was started for
   * this entry.
   */
  virtual int getUpdateCount() const = 0;

  /**
   * Any cleanup required (e.g. removing from LRUList) for the entry.
   */
  virtual void cleanup(const CacheEventFlags eventFlags) = 0;

 protected:
  inline MapEntry() {}

  inline explicit MapEntry(bool) {}
};

/**
 * @brief Hold region mapped entry value. subclass will hold lru flags.
 * Another holds expiration timestamps.
 */
class MapEntryImpl : public MapEntry,
                     public std::enable_shared_from_this<MapEntryImpl> {
 public:
  ~MapEntryImpl() override = default;
  MapEntryImpl(const MapEntryImpl&) = delete;
  MapEntryImpl& operator=(const MapEntryImpl&) = delete;

  inline void getKeyI(std::shared_ptr<CacheableKey>& result) const {
    result = m_key;
  }

  inline void getValueI(std::shared_ptr<Cacheable>& result) const {
    // If value is destroyed, then this returns nullptr
    if (CacheableToken::isDestroyed(m_value)) {
      result = nullptr;
    } else {
      result = m_value;
    }
  }

  inline void setValueI(const std::shared_ptr<Cacheable>& value) {
    m_value = value;
  }

  void getKey(std::shared_ptr<CacheableKey>& result) const override {
    getKeyI(result);
  }

  void getValue(std::shared_ptr<Cacheable>& result) const override {
    getValueI(result);
  }

  void setValue(const std::shared_ptr<Cacheable>& value) override {
    setValueI(value);
  }

  std::shared_ptr<MapEntryImpl> getImplPtr() override {
    return shared_from_this();
  }

  LRUEntryProperties& getLRUProperties() override {
    throw FatalInternalException(
        "MapEntry::getLRUProperties called for "
        "non-LRU MapEntry");
  }

  ExpEntryProperties& getExpProperties() override {
    throw FatalInternalException(
        "MapEntry::getExpProperties called for "
        "non-expiration MapEntry");
  }

  VersionStamp& getVersionStamp() override {
    throw FatalInternalException(
        "MapEntry::getVersionStamp called for "
        "non-versioned MapEntry");
  }

  void cleanup(const CacheEventFlags) override{};

 protected:
  inline explicit MapEntryImpl(bool) : MapEntry(true) {}

  inline explicit MapEntryImpl(const std::shared_ptr<CacheableKey>& key)
      : MapEntry(), m_key(key) {}

  std::shared_ptr<Cacheable> m_value;
  std::shared_ptr<CacheableKey> m_key;
};

class APACHE_GEODE_EXPORT VersionedMapEntryImpl : public MapEntryImpl,
                                                  public VersionStamp {
 public:
  virtual ~VersionedMapEntryImpl() {}

  virtual VersionStamp& getVersionStamp() { return *this; }

 protected:
  inline explicit VersionedMapEntryImpl(bool) : MapEntryImpl(true) {}

  inline explicit VersionedMapEntryImpl(
      const std::shared_ptr<CacheableKey>& key)
      : MapEntryImpl(key) {}

 private:
  // disabled
  VersionedMapEntryImpl(const VersionedMapEntryImpl&);
  VersionedMapEntryImpl& operator=(const VersionedMapEntryImpl&);
};

class APACHE_GEODE_EXPORT EntryFactory {
 public:
  explicit EntryFactory(const bool concurrencyChecksEnabled)
      : m_concurrencyChecksEnabled(concurrencyChecksEnabled) {}

  virtual ~EntryFactory() {}

  virtual void newMapEntry(ExpiryTaskManager* expiryTaskManager,
                           const std::shared_ptr<CacheableKey>& key,
                           std::shared_ptr<MapEntryImpl>& result) const;

 protected:
  bool m_concurrencyChecksEnabled;
};
}  // namespace client
}  // namespace geode
}  // namespace apache

#endif  // GEODE_MAPENTRY_H_
