/**
 * 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.
 **/

#ifndef QUICKSTEP_STORAGE_COUNTED_REFERENCE_HPP_
#define QUICKSTEP_STORAGE_COUNTED_REFERENCE_HPP_

#include <type_traits>

#include "storage/EvictionPolicy.hpp"
#include "storage/StorageBlockBase.hpp"
#include "utility/Macros.hpp"

namespace quickstep {

/** \addtogroup Storage
 *  @{
 */

/**
 * @brief A managed pointer to a StorageBlockBase. StorageBlockBase::ref() and
 *        StorageBlockBase::unref(), as well as EvictionPolicy::blockReferenced()
 *        and EvictionPolicy::blockUnreferenced(), are called when
 *        appropriate. This class is a template to allow different type
 *        modifiers to be applied; however, a static assertion prevents it
 *        from being used for anything other than a StorageBlockBase.
 *
 **/
template<class T>
class CountedReference {
  static_assert(std::is_base_of<StorageBlockBase, typename std::remove_cv<T>::type>::value,
                "CountedReference is for use only with StorageBlockBase and its subclasses");

 public:
  /**
   * @brief Default constructor. Initializes the object without a StorageBlockBase
   *     to manage.
   **/
  CountedReference()
      : block_(nullptr),
        eviction_policy_(nullptr) {}

  /**
   * @brief Construct a new CountedReference to manage a reference to an
   *     underlying StorageBlockBase. Calls StorageBlockBase::ref() and
   *     EvictionPolicy::blockReferenced().
   *
   * @param block The StorageBlockBase to manage.
   * @param eviction_policy The EvictionPolicy inform when this
   *     CountedReference is constructor or destroyed.
   **/
  CountedReference(T *block, EvictionPolicy *eviction_policy)
      : block_(block), eviction_policy_(eviction_policy) {
    eviction_policy_->blockReferenced(block_->getID());
#ifdef QUICKSTEP_DEBUG
    block_->ref();
#endif
  }

  /**
   * @brief Move constructor. Transfers management of a block reference away
   *     from another block. The other reference will not longer be valid.
   * @param other The other block.
   **/
  /* implicit */
  CountedReference(CountedReference<T> &&other)
      : block_(other.block_), eviction_policy_(other.eviction_policy_) {
    other.block_ = nullptr;
    other.eviction_policy_ = nullptr;
  }

  /**
   * @brief This is a move constructor that lets you move from a
   *        MutableBlockReference to a BlockReference. The weird template stuff is to
   *        ensure that this code is only generated when T = const StorageBlockBase or const
   *        StorageBlob. See
   *        http://stackoverflow.com/questions/17842478/select-class-constructor-using-
   *        enable-if.
   * @param other The other block.
   **/
  /* implicit */
  template<typename U = T>
  CountedReference(CountedReference<typename std::remove_cv<T>::type> &&other,
                   typename std::enable_if<std::is_same<U, const T>::value>::type* = nullptr)
      : block_(other.block_), eviction_policy_(other.eviction_policy_) {
    other.block_ = nullptr;
    other.eviction_policy_ = nullptr;
  }

  /**
   * @brief Unrefs the StorageBlockBase before destruction and called
   *     EvictionPolicy::blockUnreferenced().
   **/
  ~CountedReference() {
      if (block_ != nullptr) {
#ifdef QUICKSTEP_DEBUG
        block_->unref();
#endif
        eviction_policy_->blockUnreferenced(block_->getID());
      }
  }

  /**
   * @brief Check whether this CountedReference is valid.
   *
   * @return true if this object is managing a StorageBlockBase reference false
   *     otherwise.
   **/
  inline bool valid() { return block_ != nullptr; }

  /**
   * @brief Provide pointer access to underlying StorageBlockBase.
   *
   * @return Pointer to managed StorageBlockBase.
   **/
  inline T *operator->() const { return block_; }

  /**
   * @brief Provide reference access to underlying StorageBlockBase.
   *
   * @return Reference to managed StorageBlockBase.
   **/
  inline T &operator*() const { return *block_; }

  /**
   * @brief Move assignment operator for CountedReference. Releases the
   *     managed StorageBlockBase from other and takes over its management.
   *     After calling this, other.valid() will return false.
   **/
  inline CountedReference &operator=(CountedReference &&other) {
    if (this == &other) {
      return *this;
    }
    this->~CountedReference();
    block_ = other.block_;
    eviction_policy_ = other.eviction_policy_;
    other.block_ = nullptr;
    other.eviction_policy_ = nullptr;
    return *this;
  }

  /**
   * @brief Releases management of the underlying StorageBlockBase.
   **/
  inline void release() {
    this->~CountedReference();
    block_ = nullptr;
    eviction_policy_ = nullptr;
  }

 private:
  friend CountedReference<const T>;  // Needed to move from mutable to non-mutable CountedReference objects.

  T *block_;
  EvictionPolicy *eviction_policy_;
  DISALLOW_COPY_AND_ASSIGN(CountedReference<T>);
};

}  // namespace quickstep

/** @} */

#endif  // QUICKSTEP_STORAGE_COUNTED_REFERENCE_HPP_
