/*
 * Copyright 2025 Rive
 */

#include "gm.hpp"
#include "gmutils.hpp"
#include "common/testing_window.hpp"
#include "rive/renderer/render_canvas.hpp"
#include "rive/renderer/render_context.hpp"
#include "rive/renderer/rive_renderer.hpp"

using namespace rivegm;
using namespace rive;
using namespace rive::gpu;

// Renders Rive 2D content into a RenderCanvas and composites the result into
// the main framebuffer. Verifies the basic render-to-texture lifecycle:
// makeRenderCanvas() -> renderTarget() -> beginFrame/flush -> renderImage() ->
// drawImage.
class RenderCanvasBasic : public GM
{
public:
  RenderCanvasBasic() : GM(256, 256) {}

  ColorInt clearColor() const override { return 0xffff0000; } // red

  void onDraw(rive::Renderer* originalRenderer) override
  {
    auto renderContext = TestingWindow::Get()->renderContext();
    if (!renderContext)
      return;

    auto canvas = renderContext->makeRenderCanvas(256, 256);
    if (!canvas)
      return;

    // Intercept the current frame and flush.
    auto originalFrameDescriptor = renderContext->frameDescriptor();
    TestingWindow::Get()->flushPLSContext();

    // Begin a new frame targeting the canvas. Declare the frame
    // dimensions explicitly so Rive sizes its PLS buffers for the
    // canvas render target we are about to flush into. Without this,
    // backends whose main frame descriptor is larger than the canvas
    // (e.g. wagyu where the surface exceeds the GM size) trip the
    // flushResources.renderTarget->width() ==
    // m_frameDescriptor.renderTargetWidth assertion in
    // RenderContext::flush.
    auto canvasFrameDescriptor = originalFrameDescriptor;
    canvasFrameDescriptor.renderTargetWidth = canvas->width();
    canvasFrameDescriptor.renderTargetHeight = canvas->height();
    canvasFrameDescriptor.clearColor = 0xff0000ff; // blue
    renderContext->beginFrame(std::move(canvasFrameDescriptor));

    // Draw a green circle into the canvas.
    RiveRenderer renderer(renderContext);
    Paint green(0xff00ff00);
    PathBuilder builder;
    int nsegs = 40;
    float r = 80;
    float cx = 128, cy = 128;
    for (int i = 0; i <= nsegs; ++i)
    {
      float theta = 2 * math::PI * i / nsegs;
      float x = cx + r * cosf(theta);
      float y = cy + r * sinf(theta);
      if (i == 0)
        builder.moveTo(x, y);
      else
        builder.lineTo(x, y);
    }
    renderer.drawPath(builder.detach(), green);

    // Flush to the canvas's render target.
    TestingWindow::Get()->flushPLSContext(canvas->renderTarget());

    // Resume the main frame and composite the canvas.
    auto mainFrameDescriptor = originalFrameDescriptor;
    mainFrameDescriptor.loadAction = gpu::LoadAction::preserveRenderTarget;
    renderContext->beginFrame(std::move(mainFrameDescriptor));
    renderer.drawImage(
        canvas->renderImage(),
        {.filter = ImageFilter::nearest},
        BlendMode::srcOver,
        1);
  }
};
GMREGISTER(render_canvas_basic, return new RenderCanvasBasic())

// Composites a RenderCanvas through drawImageMesh, whose UVs come straight
// from the mesh buffers instead of an image matrix. The circle sits high so a
// vertically mirrored composite is visible.
class RenderCanvasMesh : public GM
{
public:
  RenderCanvasMesh() : GM(256, 256) {}

  ColorInt clearColor() const override { return 0xffff0000; } // red

  void onDraw(rive::Renderer* originalRenderer) override
  {
    auto renderContext = TestingWindow::Get()->renderContext();
    if (!renderContext)
      return;

    auto canvas = renderContext->makeRenderCanvas(256, 256);
    if (!canvas)
      return;

    auto originalFrameDescriptor = renderContext->frameDescriptor();
    TestingWindow::Get()->flushPLSContext();

    auto canvasFrameDescriptor = originalFrameDescriptor;
    canvasFrameDescriptor.renderTargetWidth = canvas->width();
    canvasFrameDescriptor.renderTargetHeight = canvas->height();
    canvasFrameDescriptor.clearColor = 0xff0000ff; // blue
    renderContext->beginFrame(std::move(canvasFrameDescriptor));

    RiveRenderer renderer(renderContext);
    Paint green(0xff00ff00);
    PathBuilder builder;
    int nsegs = 40;
    float r = 60;
    float cx = 128, cy = 80;
    for (int i = 0; i <= nsegs; ++i)
    {
      float theta = 2 * math::PI * i / nsegs;
      float x = cx + r * cosf(theta);
      float y = cy + r * sinf(theta);
      if (i == 0)
        builder.moveTo(x, y);
      else
        builder.lineTo(x, y);
    }
    renderer.drawPath(builder.detach(), green);
    TestingWindow::Get()->flushPLSContext(canvas->renderTarget());

    auto mainFrameDescriptor = originalFrameDescriptor;
    mainFrameDescriptor.loadAction = gpu::LoadAction::preserveRenderTarget;
    renderContext->beginFrame(std::move(mainFrameDescriptor));

    Factory* factory = TestingWindow::Get()->factory();
    auto pts = factory->makeRenderBuffer(
        RenderBufferType::vertex,
        RenderBufferFlags::mappedOnceAtInitialization,
        4 * sizeof(Vec2D));
    memcpy(
        pts->map(),
        std::array<Vec2D, 4>{
            Vec2D{0, 0},
            Vec2D{256, 0},
            Vec2D{0, 256},
            Vec2D{256, 256}}
            .data(),
        pts->sizeInBytes());
    pts->unmap();
    auto uvs = factory->makeRenderBuffer(
        RenderBufferType::vertex,
        RenderBufferFlags::mappedOnceAtInitialization,
        4 * sizeof(Vec2D));
    memcpy(
        uvs->map(),
        std::array<Vec2D, 4>{Vec2D{0, 0}, Vec2D{1, 0}, Vec2D{0, 1}, Vec2D{1, 1}}
            .data(),
        uvs->sizeInBytes());
    uvs->unmap();
    auto indices = factory->makeRenderBuffer(
        RenderBufferType::index,
        RenderBufferFlags::mappedOnceAtInitialization,
        6 * sizeof(uint16_t));
    memcpy(
        indices->map(),
        std::array<uint16_t, 6>{0, 1, 2, 1, 2, 3}.data(),
        indices->sizeInBytes());
    indices->unmap();
    renderer.drawImageMesh(
        canvas->renderImage(),
        {.filter = ImageFilter::nearest},
        pts,
        uvs,
        indices,
        4,
        6,
        BlendMode::srcOver,
        1);
  }
};
GMREGISTER(render_canvas_mesh, return new RenderCanvasMesh())

// Winding sensitive content inside a canvas: a clockwise fill rule keeps the
// clockwise square and drops the counter clockwise one, under a circular clip.
// A target whose rows run the other way from the window inverts winding, so
// the squares swap if the front face is not set per target.
class RenderCanvasWinding : public GM
{
public:
  RenderCanvasWinding() : GM(256, 256) {}

  ColorInt clearColor() const override { return 0xffff0000; } // red

  void onDraw(rive::Renderer* originalRenderer) override
  {
    auto renderContext = TestingWindow::Get()->renderContext();
    if (!renderContext)
      return;

    auto canvas = renderContext->makeRenderCanvas(256, 256);
    if (!canvas)
      return;

    auto originalFrameDescriptor = renderContext->frameDescriptor();
    TestingWindow::Get()->flushPLSContext();

    auto canvasFrameDescriptor = originalFrameDescriptor;
    canvasFrameDescriptor.renderTargetWidth = canvas->width();
    canvasFrameDescriptor.renderTargetHeight = canvas->height();
    canvasFrameDescriptor.clearColor = 0xff0000ff; // blue
    renderContext->beginFrame(std::move(canvasFrameDescriptor));

    RiveRenderer renderer(renderContext);
    // The clip stack outlives the flush, so keep it out of the composite.
    renderer.save();
    Path clip = PathBuilder::Circle(128, 128, 110);
    renderer.clipPath(clip.get());
    Paint green(0xff00ff00);
    renderer.drawPath(
        PathBuilder(FillRule::clockwise)
            .moveTo(24, 24)
            .lineTo(120, 24)
            .lineTo(120, 120)
            .lineTo(24, 120)
            .close()
            .detach(),
        green);
    Paint yellow(0xffffff00);
    renderer.drawPath(
        PathBuilder(FillRule::clockwise)
            .moveTo(136, 136)
            .lineTo(136, 232)
            .lineTo(232, 232)
            .lineTo(232, 136)
            .close()
            .detach(),
        yellow);
    renderer.restore();
    TestingWindow::Get()->flushPLSContext(canvas->renderTarget());

    auto mainFrameDescriptor = originalFrameDescriptor;
    mainFrameDescriptor.loadAction = gpu::LoadAction::preserveRenderTarget;
    renderContext->beginFrame(std::move(mainFrameDescriptor));
    renderer.drawImage(
        canvas->renderImage(),
        {.filter = ImageFilter::nearest},
        BlendMode::srcOver,
        1);
  }
};
GMREGISTER(render_canvas_winding, return new RenderCanvasWinding())

// Verifies that RenderCanvas content persists across frames. Renders a green
// circle into the canvas on the first frame, then on the second frame only
// composites the canvas (without re-rendering into it).
class RenderCanvasPersistence : public GM
{
public:
  RenderCanvasPersistence() : GM(256, 256) {}

  ColorInt clearColor() const override { return 0xffff0000; } // red

  void onDraw(rive::Renderer* originalRenderer) override
  {
    auto renderContext = TestingWindow::Get()->renderContext();
    if (!renderContext)
      return;

    if (!m_canvas)
    {
      m_canvas = renderContext->makeRenderCanvas(256, 256);
      if (!m_canvas)
        return;

      // Render green circle into the canvas on first call.
      auto originalFrameDescriptor = renderContext->frameDescriptor();
      TestingWindow::Get()->flushPLSContext();

      auto canvasFD = originalFrameDescriptor;
      canvasFD.renderTargetWidth = m_canvas->width();
      canvasFD.renderTargetHeight = m_canvas->height();
      canvasFD.clearColor = 0xff0000ff; // blue
      renderContext->beginFrame(std::move(canvasFD));
      RiveRenderer renderer(renderContext);
      Paint green(0xff00ff00);
      PathBuilder builder;
      int nsegs = 40;
      float r = 80;
      float cx = 128, cy = 128;
      for (int i = 0; i <= nsegs; ++i)
      {
        float theta = 2 * math::PI * i / nsegs;
        float x = cx + r * cosf(theta);
        float y = cy + r * sinf(theta);
        if (i == 0)
          builder.moveTo(x, y);
        else
          builder.lineTo(x, y);
      }
      renderer.drawPath(builder.detach(), green);
      TestingWindow::Get()->flushPLSContext(m_canvas->renderTarget());

      // Resume main frame.
      auto mainFD = originalFrameDescriptor;
      mainFD.loadAction = gpu::LoadAction::preserveRenderTarget;
      renderContext->beginFrame(std::move(mainFD));
    }

    // Composite the canvas (rendered on first frame, persisted on later
    // frames).
    RiveRenderer renderer(renderContext);
    renderer.drawImage(
        m_canvas->renderImage(),
        {.filter = ImageFilter::nearest},
        BlendMode::srcOver,
        1);
  }

private:
  rcp<RenderCanvas> m_canvas;
};
GMREGISTER(render_canvas_persistence, return new RenderCanvasPersistence())
