/*
 * 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_CONCURRENTENTRIESMAP_H_
#define GEODE_CONCURRENTENTRIESMAP_H_
#include <atomic>

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

#include "EntriesMap.hpp"
#include "ExpMapEntry.hpp"
#include "MapSegment.hpp"

namespace apache {
namespace geode {
namespace client {
class RegionInternal;

/**
 * @brief Concurrent entries map.
 */
class APACHE_GEODE_EXPORT ConcurrentEntriesMap : public EntriesMap {
 protected:
  ExpiryTaskManager* m_expiryTaskManager;
  uint8_t m_concurrency;
  MapSegment* m_segments;
  std::atomic<uint32_t> m_size;
  RegionInternal* m_region;
  std::atomic<int32_t> m_numDestroyTrackers;
  bool m_concurrencyChecksEnabled;
  // TODO:  hashcode() is invoked 3-4 times -- need a better
  // implementation (STLport hash_map?) that will invoke it only once
  /**
   * Return a reference to the segment for which the given key would
   * be stored.
   */
  virtual MapSegment* segmentFor(
      const std::shared_ptr<CacheableKey>& key) const {
    return &(m_segments[segmentIdx(key)]);
  }

  /**
   * Return the segment index number for the given key.
   */
  inline int segmentIdx(const std::shared_ptr<CacheableKey>& key) const {
    return segmentIdx(key->hashcode());
  }

  /**
   * Return the segment index number for the given hash.
   */
  inline int segmentIdx(uint32_t hash) const { return (hash % m_concurrency); }

 public:
  /**
   * @brief constructor, must call open before using map.
   */
  ConcurrentEntriesMap(ExpiryTaskManager* expiryTaskManager,
                       std::unique_ptr<EntryFactory> entryFactory,
                       bool concurrencyChecksEnabled, RegionInternal* region,
                       uint8_t concurrency = 16);

  /**
   * Initialize segments with proper EntryFactory.
   */
  virtual void open(uint32_t initialCapacity);

  virtual void close();

  virtual ~ConcurrentEntriesMap();

  virtual void clear();

  virtual GfErrType put(const std::shared_ptr<CacheableKey>& key,
                        const std::shared_ptr<Cacheable>& newValue,
                        std::shared_ptr<MapEntryImpl>& me,
                        std::shared_ptr<Cacheable>& oldValue, int updateCount,
                        int destroyTracker,
                        std::shared_ptr<VersionTag> versionTag,
                        bool& isUpdate = EntriesMap::boolVal,
                        DataInput* delta = nullptr);
  virtual GfErrType invalidate(const std::shared_ptr<CacheableKey>& key,
                               std::shared_ptr<MapEntryImpl>& me,
                               std::shared_ptr<Cacheable>& oldValue,
                               std::shared_ptr<VersionTag> versionTag);
  virtual GfErrType create(const std::shared_ptr<CacheableKey>& key,
                           const std::shared_ptr<Cacheable>& newValue,
                           std::shared_ptr<MapEntryImpl>& me,
                           std::shared_ptr<Cacheable>& oldValue,
                           int updateCount, int destroyTracker,
                           std::shared_ptr<VersionTag> versionTag);
  virtual bool get(const std::shared_ptr<CacheableKey>& key,
                   std::shared_ptr<Cacheable>& value,
                   std::shared_ptr<MapEntryImpl>& me);

  /**
   * @brief get MapEntry for key.
   * TODO: return GfErrType like other methods
   */
  virtual void getEntry(const std::shared_ptr<CacheableKey>& key,
                        std::shared_ptr<MapEntryImpl>& result,
                        std::shared_ptr<Cacheable>& value) const;

  /**
   * @brief remove the entry for key from the map.
   */
  virtual GfErrType remove(const std::shared_ptr<CacheableKey>& key,
                           std::shared_ptr<Cacheable>& result,
                           std::shared_ptr<MapEntryImpl>& me, int updateCount,
                           std::shared_ptr<VersionTag> versionTag,
                           bool afterRemote);

  /**
   * @brief return true if there exists an entry for the key.
   */
  virtual bool containsKey(const std::shared_ptr<CacheableKey>& key) const;

  /**
   * @brief return the all the keys in a list.
   */
  virtual void getKeys(
      std::vector<std::shared_ptr<CacheableKey>>& result) const;

  /**
   * @brief return all the entries in a list.
   */
  virtual void getEntries(
      std::vector<std::shared_ptr<RegionEntry>>& result) const;

  /**
   * @brief return all values in a list.
   */
  virtual void getValues(std::vector<std::shared_ptr<Cacheable>>& result) const;

  /**
   * @brief return the number of entries in the map.
   */
  virtual uint32_t size() const;

  virtual int addTrackerForEntry(const std::shared_ptr<CacheableKey>& key,
                                 std::shared_ptr<Cacheable>& oldValue,
                                 bool addIfAbsent, bool failIfPresent,
                                 bool incUpdateCount);

  virtual void removeTrackerForEntry(const std::shared_ptr<CacheableKey>& key);

  virtual int addTrackerForAllEntries(MapOfUpdateCounters& updateCounterMap,
                                      bool addDestroyTracking);

  virtual void removeDestroyTracking();
  virtual void reapTombstones(std::map<uint16_t, int64_t>& gcVersions);

  virtual void reapTombstones(std::shared_ptr<CacheableHashSet> removedKeys);

  /**
   * for internal testing, returns if an entry is a tombstone
   */
  virtual GfErrType isTombstone(std::shared_ptr<CacheableKey>& key,
                                std::shared_ptr<MapEntryImpl>& me,
                                bool& result);

  /**
   * for internal testing, return the number of times any segment
   * has rehashed.
   */
  uint32_t totalSegmentRehashes() const;
};  // class EntriesMap
}  // namespace client
}  // namespace geode
}  // namespace apache

#endif  // GEODE_CONCURRENTENTRIESMAP_H_
