/*
 * Copyright 2020 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef GrRefCnt_DEFINED
#define GrRefCnt_DEFINED

#include "include/core/SkRefCnt.h"
#include "src/gpu/ganesh/GrGpuResource.h"
#include "src/gpu/ganesh/GrManagedResource.h"

// We have to use auto for the function pointers here because if the actual functions live on the
// base class of T we need the function here to be a pointer to a function of the base class and not
// a function on T. Thus we can't have something like void(T::*Ref)() since we may need T or we may
// need some base class of T.
template <typename T, auto Ref, auto Unref> class gr_sp {
private:
    static inline T* SafeRef(T* obj) {
        if (obj) {
            (obj->*Ref)();
        }
        return obj;
    }

    static inline void SafeUnref(T* obj) {
        if (obj) {
            (obj->*Unref)();
        }
    }

public:
    using element_type = T;

    constexpr gr_sp() : fPtr(nullptr) {}
    constexpr gr_sp(std::nullptr_t) : fPtr(nullptr) {}

    /**
     * Shares the underlying object by calling Ref(), so that both the argument and the newly
     * created gr_sp both have a reference to it.
     */
    gr_sp(const gr_sp<T, Ref, Unref>& that) : fPtr(SafeRef(that.get())) {}
    template <typename U,
              typename = typename std::enable_if<std::is_convertible<U*, T*>::value>::type>
    gr_sp(const gr_sp<U, Ref, Unref>& that) : fPtr(SafeRef(that.get())) {}

    gr_sp(const sk_sp<T>& that) : fPtr(SafeRef(that.get())) {}


    /**
     * Move the underlying object from the argument to the newly created gr_sp. Afterwards only the
     * new gr_sp will have a reference to the object, and the argument will point to null.
     * No call to Ref() or Unref() will be made.
     */
    gr_sp(gr_sp<T, Ref, Unref>&& that) : fPtr(that.release()) {}

    /**
     * Copies the underlying object pointer from the argument to the gr_sp. It will then call
     * Ref() on the new object.
     */
    gr_sp(sk_sp<T>&& that) : fPtr(SafeRef(that.get())) {}

    /**
     *  Adopt the bare pointer into the newly created gr_sp.
     *  No call to Ref() or Unref() will be made.
     */
    explicit gr_sp(T* obj) : fPtr(obj) {}

    /**
     * Calls Unref() on the underlying object pointer.
     */
    ~gr_sp() {
        SafeUnref(fPtr);
        SkDEBUGCODE(fPtr = nullptr);
    }

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

    /**
     * Shares the underlying object referenced by the argument by calling Ref() on it. If this gr_sp
     * previously had a reference to an object (i.e. not null) it will call Unref() on that object.
     */
    gr_sp& operator=(const gr_sp<T, Ref, Unref>& that) {
        if (this != &that) {
            this->reset(SafeRef(that.get()));
        }
        return *this;
    }

    /**
     * Copies the underlying object pointer from the argument to the gr_sp. If the gr_sp previously
     * held a reference to another object, Unref() will be called on that object. It will then call
     * Ref() on the new object.
     */
    gr_sp& operator=(const sk_sp<T>& that) {
        this->reset(SafeRef(that.get()));
        return *this;
    }

    /**
     * Move the underlying object from the argument to the gr_sp. If the gr_sp previously held
     * a reference to another object, Unref() will be called on that object. No call to Ref() will
     * be made.
     */
    gr_sp& operator=(gr_sp<T, Ref, Unref>&& that) {
        this->reset(that.release());
        return *this;
    }

    /**
     * Copies the underlying object pointer from the argument to the gr_sp. If the gr_sp previously
     * held a reference to another object, Unref() will be called on that object. It will then call
     * Ref() on the new object.
     */
    gr_sp& operator=(sk_sp<T>&& that) {
        this->reset(SafeRef(that.get()));
        return *this;
    }

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

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

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

    /**
     * Adopt the new bare pointer, and call Unref() on any previously held object (if not null).
     * No call to Ref() will be made.
     */
    void reset(T* ptr = nullptr) {
        T* oldPtr = fPtr;
        fPtr = ptr;
        SafeUnref(oldPtr);
    }

private:
    /**
     * Return the bare pointer, and set the internal object pointer to nullptr.
     * The caller must assume ownership of the object, and manage its reference count directly.
     * No call to Unref() will be made.
     */
    T* SK_WARN_UNUSED_RESULT release() {
        T* ptr = fPtr;
        fPtr = nullptr;
        return ptr;
    }

    T* fPtr;
};

////////////////////////////////////////////////////////////////////////////////////////////////////

/**
 * Shared pointer class to wrap classes that support a addCommandBufferUsage() and
 * removeCommandBufferUsage() interface.
 *
 * This class supports copying, moving, and assigning an sk_sp into it. In general these commands do
 * not modify the sk_sp at all but just call addCommandBufferUsage() on the underlying object.
 *
 * This class is designed to be used by GrGpuResources that need to track when they are in use on
 * gpu (usually via a command buffer) separately from tracking if there are any current logical
 * usages in Ganesh. This allows for a scratch GrGpuResource to be reused for new draw calls even
 * if it is in use on the GPU.
 */
template <typename T>
using gr_cb = gr_sp<T, &T::addCommandBufferUsage, &T::removeCommandBufferUsage>;

////////////////////////////////////////////////////////////////////////////////////////////////////

/**
 * This class mimics sk_sp but instead of calling unref it calls recycle instead.
 */
template <typename T> using gr_rp = gr_sp<T, &T::ref, &T::recycle>;

/**
 *  Returns a gr_rp wrapping the provided ptr AND calls ref on it (if not null).
 *
 *  This is different than the semantics of the constructor for gr_rp, which just wraps the ptr,
 *  effectively "adopting" it.
 */
template <typename T> gr_rp<T> gr_ref_rp(T* obj) { return gr_rp<T>(SkSafeRef(obj)); }

template <typename T> gr_rp<T> gr_ref_rp(const T* obj) {
    return gr_rp<T>(const_cast<T*>(SkSafeRef(obj)));
}
#endif
