/*
 * 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) {}

    ~RefCnt() { assert(this->debugging_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))
        {
#ifndef NDEBUG
            // we restore the "1" in debug builds just to make our destructor happy
            (void)m_refcnt.fetch_add(+1, std::memory_order_relaxed);
#endif
            delete static_cast<const T*>(this);
        }
    }

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

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;
    }

    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

#endif
