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