/*
 * 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_MAPENTRYT_H_
#define GEODE_MAPENTRYT_H_

#include <geode/internal/geode_globals.hpp>
#include "MapEntry.hpp"
#include "TrackedMapEntry.hpp"

#define GF_TRACK_MAX 4
#define GF_UPDATE_MAX 8

namespace apache {
namespace geode {
namespace client {
// this class encapsulates the common functionality of the MapEntryT<>
// generic template class and its specializations
template <typename TBase, int NUM_TRACKERS, int UPDATE_COUNT>
class MapEntryST {
 public:
  static int addTracker(TBase* loc);
  static int removeTracker(TBase* loc);
  static int incUpdateCount(TBase* loc);

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

// specialization of MapEntryST for NUM_TRACKERS==0 to terminate
// removeTracker
template <typename TBase, int UPDATE_COUNT>
class MapEntryST<TBase, 0, UPDATE_COUNT> {
 public:
  static int addTracker(TBase* loc);
  static int removeTracker(TBase* loc);
  static int incUpdateCount(TBase* loc);

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

/**
 * We use the tracking of entries to deal with updates coming in while
 * another region operation is in progress. Specifically the issue to be
 * tackled is to ensure that updates that come in while remote server part
 * of an operation is in progress should not be overwritten, particularly
 * the notifications. The approach being used is to set a tracking number
 * on the entry before starting the remote operation which will lead to any
 * updates incrementing an "update counter" of the entry. When the operation
 * tries to perform the local cache update part, then it checks the
 * "update counter" and goes ahead only if that has not changed.
 *
 * This template class encapsulates the tracking number and update counter.
 * It completely avoids storing member variables for the above two by
 * having a series of classes each returning a fixed value for these two
 * and using placement new to convert "this" into another type which will
 * return a new tracking number and update counter. This recursive template
 * definition is terminated using specializations so that beyond
 * "GF_TRACK_MAX" and "GF_UPDATE_MAX" we make use of a wrapper
 * <code>TrackedMapEntry</code> class that will store the tracking number
 * and update counter as separate fields in addition to the actual MapEntry.
 * The assumption is that "GF_TRACK_MAX" or "GF_UPDATE_MAX" will be violated
 * very rarely.
 *
 *
 */
template <typename TBase, int NUM_TRACKERS, int UPDATE_COUNT>
class MapEntryT final : public TBase {
 public:
  inline explicit MapEntryT(bool) : TBase(true) {}

  ~MapEntryT() final = default;

  MapEntryT(const MapEntryT&) = delete;
  MapEntryT& operator=(const MapEntryT&) = delete;

  int addTracker(std::shared_ptr<MapEntry>&) final {
    return MapEntryST<TBase, NUM_TRACKERS, UPDATE_COUNT>::addTracker(this);
  }

  std::pair<bool, int> removeTracker() final {
    return std::make_pair(
        false,
        MapEntryST<TBase, NUM_TRACKERS, UPDATE_COUNT>::removeTracker(this));
  }

  int incrementUpdateCount(std::shared_ptr<MapEntry>&) final {
    return MapEntryST<TBase, NUM_TRACKERS, UPDATE_COUNT>::incUpdateCount(this);
  }

  int getTrackingNumber() const final { return NUM_TRACKERS; }

  int getUpdateCount() const final { return UPDATE_COUNT; }

  inline static std::shared_ptr<MapEntryT> create(
      const std::shared_ptr<CacheableKey>& key) {
    return std::make_shared<MapEntryT>(key);
  }

  inline static std::shared_ptr<MapEntryT> create(
      ExpiryTaskManager* expiryTaskManager,
      const std::shared_ptr<CacheableKey>& key) {
    return std::make_shared<MapEntryT>(expiryTaskManager, key);
  }

 protected:
  inline MapEntryT(const std::shared_ptr<CacheableKey>& key) : TBase(key) {}
  inline MapEntryT(ExpiryTaskManager* expiryTaskManager,
                   const std::shared_ptr<CacheableKey>& key)
      : TBase(expiryTaskManager, key) {}

  _GEODE_FRIEND_STD_SHARED_PTR(MapEntryT)
};

// specialization of MapEntryT to terminate the recursive template definition
// for update counter == GF_UPDATE_MAX
template <typename TBase, int NUM_TRACKERS>
class MapEntryT<TBase, NUM_TRACKERS, GF_UPDATE_MAX> final : public TBase {
 public:
  inline explicit MapEntryT(bool) : TBase(true) {}

  ~MapEntryT() final = default;

  MapEntryT(const MapEntryT&) = delete;
  MapEntryT& operator=(const MapEntryT&) = delete;

  int addTracker(std::shared_ptr<MapEntry>&) final {
    return MapEntryST<TBase, NUM_TRACKERS, GF_UPDATE_MAX>::addTracker(this);
  }

  std::pair<bool, int> removeTracker() final {
    return std::make_pair(
        false,
        MapEntryST<TBase, NUM_TRACKERS, GF_UPDATE_MAX>::removeTracker(this));
  }

  int incrementUpdateCount(std::shared_ptr<MapEntry>& newEntry) final {
    // fallback to TrackedMapEntry
    newEntry = std::make_shared<TrackedMapEntry>(
        this->shared_from_this(), NUM_TRACKERS, GF_UPDATE_MAX + 1);
    return (GF_UPDATE_MAX + 1);
  }

  int getTrackingNumber() const final { return NUM_TRACKERS; }

  int getUpdateCount() const final { return GF_UPDATE_MAX; }
};

// specialization of MapEntryT to terminate the recursive template definition
// for tracking number == GF_TRACK_MAX
template <typename TBase, int UPDATE_COUNT>
class MapEntryT<TBase, GF_TRACK_MAX, UPDATE_COUNT> final : public TBase {
 public:
  inline explicit MapEntryT(bool) : TBase(true) {}

  ~MapEntryT() final = default;

  MapEntryT(const MapEntryT&) = delete;
  MapEntryT& operator=(const MapEntryT&) = delete;

  int addTracker(std::shared_ptr<MapEntry>& newEntry) final {
    // fallback to TrackedMapEntry
    newEntry = std::make_shared<TrackedMapEntry>(
        this->shared_from_this(), GF_TRACK_MAX + 1, UPDATE_COUNT);
    return UPDATE_COUNT;
  }

  std::pair<bool, int> removeTracker() final {
    return std::make_pair(
        false,
        MapEntryST<TBase, GF_TRACK_MAX, UPDATE_COUNT>::removeTracker(this));
  }

  int incrementUpdateCount(std::shared_ptr<MapEntry>&) final {
    return MapEntryST<TBase, GF_TRACK_MAX, UPDATE_COUNT>::incUpdateCount(this);
  }

  int getTrackingNumber() const final { return GF_TRACK_MAX; }

  int getUpdateCount() const final { return UPDATE_COUNT; }
};

// specialization of MapEntryT to terminate the recursive template definition
// for tracking number == GF_TRACK_MAX and update counter == GF_UPDATE_MAX
template <typename TBase>
class MapEntryT<TBase, GF_TRACK_MAX, GF_UPDATE_MAX> final : public TBase {
 public:
  inline explicit MapEntryT(bool) : TBase(true) {}

  ~MapEntryT() final = default;

  MapEntryT(const MapEntryT&) = delete;
  MapEntryT& operator=(const MapEntryT&) = delete;

  int addTracker(std::shared_ptr<MapEntry>& newEntry) final {
    // fallback to TrackedMapEntry
    newEntry = std::make_shared<TrackedMapEntry>(
        this->shared_from_this(), GF_TRACK_MAX + 1, GF_UPDATE_MAX);
    return GF_UPDATE_MAX;
  }

  std::pair<bool, int> removeTracker() final {
    return std::make_pair(
        false,
        MapEntryST<TBase, GF_TRACK_MAX, GF_UPDATE_MAX>::removeTracker(this));
  }

  int incrementUpdateCount(std::shared_ptr<MapEntry>& newEntry) final {
    // fallback to TrackedMapEntry
    newEntry = std::make_shared<TrackedMapEntry>(
        this->shared_from_this(), GF_TRACK_MAX, GF_UPDATE_MAX + 1);
    return (GF_UPDATE_MAX + 1);
  }

  int getTrackingNumber() const final { return GF_TRACK_MAX; }

  int getUpdateCount() const final { return GF_UPDATE_MAX; }
};

template <typename TBase, int NUM_TRACKERS, int UPDATE_COUNT>
inline int MapEntryST<TBase, NUM_TRACKERS, UPDATE_COUNT>::addTracker(
    TBase* loc) {
  // use placement new to make vptr point to class that shall have
  // tracking number incremented by one
  // invoke the constructor that will avoid initializing *any* data
  (void)new (loc) MapEntryT<TBase, NUM_TRACKERS + 1, UPDATE_COUNT>(true);
  return UPDATE_COUNT;
}

template <typename TBase, int NUM_TRACKERS, int UPDATE_COUNT>
inline int MapEntryST<TBase, NUM_TRACKERS, UPDATE_COUNT>::removeTracker(
    TBase* loc) {
  // use placement new to make vptr point to class that shall have
  // tracking number decremented by one
  // invoke the constructor that will avoid initializing *any* data
  if (NUM_TRACKERS == 1) {
    // if all trackers have gone away then the update counter is no
    // longer required, so reset it to zero
    (void)new (loc) MapEntryT<TBase, 0, 0>(true);
  } else {
    (void)new (loc) MapEntryT<TBase, NUM_TRACKERS - 1, UPDATE_COUNT>(true);
  }
  return (NUM_TRACKERS - 1);
}

template <typename TBase, int NUM_TRACKERS, int UPDATE_COUNT>
inline int MapEntryST<TBase, NUM_TRACKERS, UPDATE_COUNT>::incUpdateCount(
    TBase* loc) {
  // use placement new to make vptr point to class that shall have
  // update number incremented by one
  // invoke the constructor that will avoid initializing *any* data
  (void)new (loc) MapEntryT<TBase, NUM_TRACKERS, UPDATE_COUNT + 1>(true);
  return (UPDATE_COUNT + 1);
}

template <typename TBase, int UPDATE_COUNT>
inline int MapEntryST<TBase, 0, UPDATE_COUNT>::addTracker(TBase* loc) {
  // use placement new to make vptr point to class that shall have
  // tracking number incremented by one
  // invoke the constructor that will avoid initializing *any* data
  (void)new (loc) MapEntryT<TBase, 1, UPDATE_COUNT>(true);
  return UPDATE_COUNT;
}

template <typename TBase, int UPDATE_COUNT>
inline int MapEntryST<TBase, 0, UPDATE_COUNT>::removeTracker(TBase*) {
  return 0;
}

template <typename TBase, int UPDATE_COUNT>
inline int MapEntryST<TBase, 0, UPDATE_COUNT>::incUpdateCount(TBase*) {
  return UPDATE_COUNT;
}
}  // namespace client
}  // namespace geode
}  // namespace apache

#endif  // GEODE_MAPENTRYT_H_
