/*
 * 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,
 *  delete is called on the object.
 *
 *  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 {

class RefCnt {
public:
    RefCnt() : m_refcnt(1) {}

    virtual ~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 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); }

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