/*
 * Copyright 2026 Rive
 */

#if defined(RIVE_CANVAS) && defined(RIVE_ORE)

#include "rive/renderer/cmd/deferred_host.hpp"
#include "rive/renderer/render_canvas.hpp"
#include "rive/renderer/render_context.hpp"
#include "rive/renderer/render_context_impl.hpp"
#include <assert.h>
#include <stdio.h>

#if defined(__ANDROID__)
#include <android/log.h>
// stderr goes nowhere on Android, route diagnostics to logcat.
#define DEFERRED_WARN(...)                                                     \
    __android_log_print(ANDROID_LOG_ERROR, "Rive", __VA_ARGS__)
#else
#define DEFERRED_WARN(...) fprintf(stderr, __VA_ARGS__)
#endif

namespace rive::cmd
{

rive::Factory* HostFrameSink::factory() { return renderContext(); }

rive::ore::Context* HostFrameSink::oreContext()
{
    return m_replayOre ? renderContext()->ore() : nullptr;
}

rive::Renderer* HostFrameSink::beginScreenFrame(uint64_t target)
{
    if (target != m_target && !m_acceptAnyScreenTarget)
    {
        // Another texture's segments reached this sink, so the session frame
        // was taken while that texture was still recording. Drop them loudly
        // rather than draw them here; the replayer counts them as dropped.
        static int strays = 0;
        if (strays < 16)
        {
            strays++;
            DEFERRED_WARN("rive deferred: frame carried target %llu into the "
                          "sink for target %llu, dropping its draws\n",
                          (unsigned long long)target,
                          (unsigned long long)m_target);
        }
        // Native delivery is one host per session frame: hosts must record
        // sequentially, so a foreign target here means overlapping opens and
        // its draws would silently blank. Loud in debug; the warning above
        // is all release gets.
        assert(false && "deferred hosts must open and close their screen "
                        "target sequentially, a neighbor's frame reached "
                        "this sink");
        return nullptr;
    }
    if (m_screen == nullptr)
    {
        m_screen = beginScreen(target, m_clear, m_color);
    }
    return m_screen;
}

void HostFrameSink::beginOreFrame()
{
    if (auto* ore = oreContext())
    {
        ore->beginFrame(oreFrame());
    }
}

void HostFrameSink::endOreFrame()
{
    if (auto* ore = oreContext())
    {
        ore->endFrame();
    }
}

void HostFrameSink::afterOreFrame()
{
    renderContext()->impl()->scrubStateAfterOre();
}

rive::Renderer* HostFrameSink::beginCanvasContent(
    rive::gpu::RenderCanvas* canvas,
    uint32_t clearColor)
{
    m_activeCanvas = canvas;
    auto* rc = renderContext();
    // A deferred canvas has no texture until the replaying context gives it
    // one, and this is the first thing that renders into it.
    rc->impl()->ensureCanvasBacking(canvas);
    rive::gpu::RenderContext::FrameDescriptor d{};
    d.renderTargetWidth = canvas->width();
    d.renderTargetHeight = canvas->height();
    d.loadAction = rive::gpu::LoadAction::clear;
    d.clearColor = clearColor;
    d.disableRasterOrdering = m_disableRasterOrdering;
    rc->beginFrame(d);
    m_canvasRenderer = std::make_unique<rive::RiveRenderer>(rc);
    return m_canvasRenderer.get();
}

void HostFrameSink::endCanvasContent()
{
    if (m_activeCanvas == nullptr)
    {
        return;
    }
    auto* rc = renderContext();
    rive::gpu::RenderContext::FlushResources fr{};
    fr.renderTarget = m_activeCanvas->renderTarget();
    if (m_useExternalCommandBuffer)
    {
        void* cb = rc->impl()->makeCommandBuffer();
        fr.externalCommandBuffer = cb;
        rc->flush(fr);
        rc->impl()->commitCommandBuffer(cb);
    }
    else
    {
        rc->flush(fr);
    }
    m_canvasRenderer.reset();
    m_activeCanvas = nullptr;
}

void DeferredInlineHost::beginRecord(bool clear, uint32_t color)
{
    m_doClear = clear;
    m_color = color;
    m_session->recordOreReplayMarker();
}

bool DeferredInlineHost::replayOre() const
{
    return m_session->oreContext().stream().commandBytes().size() != 0;
}

static void warnDroppedDraws(uint32_t droppedDraws)
{
    if (droppedDraws == 0)
    {
        return;
    }
    static int drops = 0;
    if (drops < 16)
    {
        drops++;
        DEFERRED_WARN("rive deferred: %u draws DROPPED this frame (mixed "
                      "factories or replay bug)\n",
                      droppedDraws);
    }
}

bool DeferredInlineHost::replayInline(HostFrameSink& sink,
                                      const std::function<void()>& present)
{
    // Nothing recorded, keep showing the last presented frame.
    if (!m_session->recordedThisFrame())
    {
        return false;
    }

    m_replayer.replayFrame(*m_session, sink);
    m_session->resetFrame();

    if (sink.began())
    {
        present();
    }
    warnDroppedDraws(m_replayer.droppedDraws());
    return true;
}

} // namespace rive::cmd

#endif // RIVE_CANVAS && RIVE_ORE
