/*
 * 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_targetPreserved, 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;
  const FrameMode mode = canvasMode(canvas);
  d.msaaSampleCount = mode.msaaSampleCount;
  d.disableRasterOrdering = mode.disableRasterOrdering;
  d.clockwiseFillOverride = mode.clockwiseFillOverride;
  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 = canvasFlushResources();
  fr.renderTarget = m_activeCanvas->renderTarget();
  if (fr.externalCommandBuffer == nullptr && 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,
    const ore::Context::TargetDesc& target)
{
  m_doClear = clear;
  m_color = color;
  m_session->oreContext().setTarget(target);
  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
