/*
 * Copyright 2021 Rive
 */

#ifndef _RIVE_REFCNT_HPP_
#define _RIVE_REFCNT_HPP_

#include "rive/rive_types.hpp"

#include <atomic>
#include <cstddef>
#include <type_traits>
#include <utility>

/*
 *  RefCnt : Threadsafe shared pointer baseclass.
 *
 *  The reference count is set to one in the constructor, and goes up on every
 * call to ref(), and down on every call to unref(). When a call to unref()
 * brings the counter to 0, the object is casted to class "const T*" and
 * deleted. Usage:
 *
 *    class MyClass : public RefCnt<MyClass>
 *
 *  rcp : template wrapper for subclasses of RefCnt, to manage assignment and
 * parameter passing to safely keep track of shared ownership.
 *
 *  Both of these inspired by Skia's SkRefCnt and sk_sp
 */

namespace rive
{

template <typename T> class RefCnt
{
public:
  RefCnt() : m_refcnt(1) {}

  void ref() const { (void)m_refcnt.fetch_add(+1, std::memory_order_relaxed); }

  void unref() const
  {
    if (1 == m_refcnt.fetch_add(-1, std::memory_order_acq_rel))
    {
      static_cast<const T*>(this)->onRefCntReachedZero();
    }
  }

  // not reliable in actual threaded scenarios, but useful (perhaps) for
  // debugging
  int32_t debugging_refcnt() const
  {
    return m_refcnt.load(std::memory_order_relaxed);
  }

protected:
  // Can be overloaded in the subclass if specialized delete behavior is
  // required.
  void onRefCntReachedZero() const { delete static_cast<const T*>(this); }

private:
  // mutable, so can be changed even on a const object
  mutable std::atomic<int32_t> m_refcnt;

  RefCnt(RefCnt&&) = delete;
  RefCnt(const RefCnt&) = delete;
  RefCnt& operator=(RefCnt&&) = delete;
  RefCnt& operator=(const RefCnt&) = delete;
};

template <typename T> static inline T* safe_ref(T* obj)
{
  if (obj)
  {
    obj->ref();
  }
  return obj;
}

template <typename T> static inline void safe_unref(T* obj)
{
  if (obj)
  {
    obj->unref();
  }
}

// rcp : smart point template for holding subclasses of RefCnt

template <typename T> class rcp
{
public:
  constexpr rcp() : m_ptr(nullptr) {}
  constexpr rcp(std::nullptr_t) : m_ptr(nullptr) {}
  explicit rcp(T* ptr) : m_ptr(ptr) {}

  rcp(const rcp<T>& other) : m_ptr(safe_ref(other.get())) {}
  rcp(rcp<T>&& other) : m_ptr(other.release()) {}

  template <
      typename U,
      typename =
          typename std::enable_if<std::is_convertible<U*, T*>::value>::type>
  rcp(const rcp<U>& other) : m_ptr(safe_ref(other.get()))
  {}

  template <
      typename U,
      typename =
          typename std::enable_if<std::is_convertible<U*, T*>::value>::type>
  rcp(rcp<U>&& other) : m_ptr(other.release())
  {}

  /**
   *  Calls unref() on the underlying object pointer.
   */
  ~rcp() { safe_unref(m_ptr); }

  rcp<T>& operator=(std::nullptr_t)
  {
    this->reset();
    return *this;
  }

  rcp<T>& operator=(const rcp<T>& other)
  {
    if (this != &other)
    {
      this->reset(safe_ref(other.get()));
    }
    return *this;
  }

  // move assignment operator
  rcp<T>& operator=(rcp<T>&& other)
  {
    this->reset(other.release());
    return *this;
  }

  T& operator*() const
  {
    assert(this->get() != nullptr);
    return *this->get();
  }

  explicit operator bool() const { return this->get() != nullptr; }

  T* get() const { return m_ptr; }
  T* operator->() const { return m_ptr; }

  // Unrefs the current pointer, and accepts the new pointer, but
  // DOES NOT increment ownership of the new pointer.
  void reset(T* ptr = nullptr)
  {
    // Calling m_ptr->unref() may call this->~() or this->reset(T*).
    // http://wg21.cmeerw.net/lwg/issue998
    // http://wg21.cmeerw.net/lwg/issue2262
    T* oldPtr = m_ptr;
    m_ptr = ptr;
    safe_unref(oldPtr);
  }

  // This returns the bare point WITHOUT CHANGING ITS REFCNT, but removes it
  // from this object, so the caller must manually manage its count.
  T* release()
  {
    T* ptr = m_ptr;
    m_ptr = nullptr;
    return ptr;
  }

  void swap(rcp<T>& other) { std::swap(m_ptr, other.m_ptr); }

private:
  T* m_ptr;
};

template <typename T> inline void swap(rcp<T>& a, rcp<T>& b) { a.swap(b); }

template <typename T, typename... Args> rcp<T> inline make_rcp(Args&&... args)
{
  return rcp<T>(new T(std::forward<Args>(args)...));
}

template <typename T> rcp<T> inline ref_rcp(T* ptr)
{
  return rcp<T>(safe_ref(ptr));
}

template <
    typename U,
    typename T,
    typename =
        typename std::enable_if<std::is_convertible<U*, T*>::value>::type>
rcp<U> static_rcp_cast(rcp<T> ptr)
{
  return rcp<U>(static_cast<U*>(ptr.release()));
}

// == variants

template <typename T> inline bool operator==(const rcp<T>& a, std::nullptr_t)
{
  return !a;
}
template <typename T> inline bool operator==(std::nullptr_t, const rcp<T>& b)
{
  return !b;
}
template <typename T, typename U>
inline bool operator==(const rcp<T>& a, const rcp<U>& b)
{
  return a.get() == b.get();
}

// != variants

template <typename T> inline bool operator!=(const rcp<T>& a, std::nullptr_t)
{
  return static_cast<bool>(a);
}
template <typename T> inline bool operator!=(std::nullptr_t, const rcp<T>& b)
{
  return static_cast<bool>(b);
}
template <typename T, typename U>
inline bool operator!=(const rcp<T>& a, const rcp<U>& b)
{
  return a.get() != b.get();
}

} // namespace rive

namespace std
{
template <typename T> struct hash<rive::rcp<T>>
{
  using result_type = std::size_t;
  using argument_type = rive::rcp<T>;

  std::size_t operator()(const rive::rcp<T>& up) const
  {
    return hash<T*>()(up.get());
  }
};

} // namespace std
#endif
