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

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

// == 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
