/*
 * Copyright 2022 Rive
 */

#pragma once

#include "rive/pls/pls.hpp"

namespace rive::pls
{
// API-agnostic implementation of an abstract buffer ring. We use rings to ensure the GPU can render
// one frame in parallel while the CPU prepares the next frame.
//
// Calling mapBuffer() maps the next buffer in the ring.
//
// Calling unmapAndSubmitBuffer() submits the currently-mapped buffer for GPU rendering, in whatever
// way that is meaningful for the PLSRenderContext implementation.
//
// This class is meant to only be used through BufferRing<>.
class BufferRing
{
public:
    BufferRing(size_t capacityInBytes) : m_capacityInBytes(capacityInBytes) {}
    virtual ~BufferRing() {}

    size_t capacityInBytes() const { return m_capacityInBytes; }
    bool isMapped() const { return m_mapSizeInBytes != 0; }

    // Maps the next buffer in the ring.
    void* mapBuffer(size_t mapSizeInBytes)
    {
        assert(!isMapped());
        assert(mapSizeInBytes > 0);
        assert(mapSizeInBytes <= m_capacityInBytes);
        m_submittedBufferIdx = (m_submittedBufferIdx + 1) % kBufferRingSize;
        m_mapSizeInBytes = mapSizeInBytes;
        return onMapBuffer(m_submittedBufferIdx, m_mapSizeInBytes);
    }

    // Submits the currently-mapped buffer for GPU rendering, in whatever way that is meaningful for
    // the PLSRenderContext implementation.
    void unmapAndSubmitBuffer()
    {
        assert(isMapped());
        onUnmapAndSubmitBuffer(m_submittedBufferIdx, m_mapSizeInBytes);
        m_mapSizeInBytes = 0;
    }

protected:
    int submittedBufferIdx() const
    {
        assert(!isMapped());
        return m_submittedBufferIdx;
    }

    virtual void* onMapBuffer(int bufferIdx, size_t mapSizeInBytes) = 0;
    virtual void onUnmapAndSubmitBuffer(int bufferIdx, size_t mapSizeInBytes) = 0;

    uint8_t* shadowBuffer() const
    {
        if (m_shadowBuffer == nullptr && m_capacityInBytes > 0)
        {
            m_shadowBuffer.reset(new uint8_t[m_capacityInBytes]);
        }
        return m_shadowBuffer.get();
    }

private:
    size_t m_capacityInBytes;
    size_t m_mapSizeInBytes = 0;
    int m_submittedBufferIdx = 0;

    // Lazy-allocated CPU buffer for when buffer mapping isn't supported by the API.
    mutable std::unique_ptr<uint8_t[]> m_shadowBuffer;
};

// BufferRing that resides solely in CPU memory, and therefore doesn't require a ring.
class HeapBufferRing : public BufferRing
{
public:
    HeapBufferRing(size_t capacityInBytes) : BufferRing(capacityInBytes) {}

    uint8_t* contents() const { return shadowBuffer(); }

protected:
    void* onMapBuffer(int bufferIdx, size_t mapSizeInBytes) override { return shadowBuffer(); }
    void onUnmapAndSubmitBuffer(int bufferIdx, size_t mapSizeInBytes) override {}
};
} // namespace rive::pls
