/*
 * 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_LRUACTION_H_
#define GEODE_LRUACTION_H_

#include <geode/Cache.hpp>
#include <geode/PersistenceManager.hpp>
#include <geode/internal/geode_globals.hpp>

#include "CacheableToken.hpp"
#include "MapEntry.hpp"
#include "RegionInternal.hpp"
#include "Utils.hpp"

namespace apache {
namespace geode {
namespace client {

/**
 * @brief abstract behavior for different eviction actions.
 */
class LRUEntriesMap;
class LRUAction {
 protected:
  bool m_invalidates;
  bool m_destroys;
  bool m_distributes;
  bool m_overflows;

  LRUAction() {
    m_invalidates = false;
    m_destroys = false;
    m_distributes = false;
    m_overflows = false;
  }

 public:
  // types of action

  typedef enum {
    /** When the region or cached object expires, it is invalidated. */
    INVALIDATE = 0,
    /** When expired, invalidated locally only. */
    LOCAL_INVALIDATE,

    /** When the region or cached object expires, it is destroyed. */
    DESTROY,
    /** When expired, destroyed locally only. */
    LOCAL_DESTROY,

    /** invalid type. */
    INVALID_ACTION,

    /** over flow type */
    OVERFLOW_TO_DISK
  } Action;

 public:
  static LRUAction* newLRUAction(const LRUAction::Action& lruAction,
                                 RegionInternal* regionPtr,
                                 LRUEntriesMap* entriesMapPtr);

  virtual ~LRUAction() noexcept = default;

  virtual bool evict(const std::shared_ptr<MapEntryImpl>& mePtr) = 0;

  virtual LRUAction::Action getType() = 0;

  inline bool invalidates() { return m_invalidates; }

  inline bool destroys() { return m_destroys; }

  inline bool distributes() { return m_distributes; }

  inline bool overflows() { return m_overflows; }
};

/**
 * @brief LRUAction for destroy (distributed)
 */
class LRUDestroyAction : public virtual LRUAction {
 private:
  RegionInternal* m_regionPtr;

  explicit LRUDestroyAction(RegionInternal* regionPtr)
      : m_regionPtr(regionPtr) {
    m_destroys = true;
    m_distributes = true;
  }

 public:
  ~LRUDestroyAction() noexcept override = default;

  bool evict(const std::shared_ptr<MapEntryImpl>& mePtr) override {
    std::shared_ptr<CacheableKey> keyPtr;
    mePtr->getKeyI(keyPtr);
    std::shared_ptr<VersionTag> versionTag;
    //  we should invoke the destroyNoThrow with appropriate
    // flags to correctly invoke listeners
    LOGDEBUG("LRUDestroy: evicting entry with key [%s]",
             Utils::nullSafeToString(keyPtr).c_str());
    GfErrType err = GF_NOERR;
    if (!m_regionPtr->isDestroyed()) {
      err = m_regionPtr->destroyNoThrow(keyPtr, nullptr, -1,
                                        CacheEventFlags::EVICTION, versionTag);
    }
    return (err == GF_NOERR);
  }

  LRUAction::Action getType() override { return LRUAction::DESTROY; }

  friend class LRUAction;
};

/**
 * @brief LRUAction for invalidate.
 */
class LRULocalInvalidateAction : public virtual LRUAction {
 private:
  RegionInternal* m_regionPtr;

  explicit LRULocalInvalidateAction(RegionInternal* regionPtr)
      : m_regionPtr(regionPtr) {
    m_invalidates = true;
  }

 public:
  ~LRULocalInvalidateAction() noexcept override = default;

  bool evict(const std::shared_ptr<MapEntryImpl>& mePtr) override;

  LRUAction::Action getType() override { return LRUAction::LOCAL_INVALIDATE; }

  friend class LRUAction;
};

/**
 * @brief LRUAction for invalidate.
 */
class LRUOverFlowToDiskAction : public virtual LRUAction {
 private:
  RegionInternal* m_regionPtr;
  LRUEntriesMap* m_entriesMapPtr;

  LRUOverFlowToDiskAction(RegionInternal* regionPtr,
                          LRUEntriesMap* entriesMapPtr)
      : m_regionPtr(regionPtr), m_entriesMapPtr(entriesMapPtr) {
    m_overflows = true;
  }

 public:
  ~LRUOverFlowToDiskAction() noexcept override {}

  bool evict(const std::shared_ptr<MapEntryImpl>& mePtr) override;

  LRUAction::Action getType() override { return LRUAction::OVERFLOW_TO_DISK; }

  friend class LRUAction;
};
}  // namespace client
}  // namespace geode
}  // namespace apache

#endif  // GEODE_LRUACTION_H_
