/*
 * Copyright 2023 Rive
 */

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

using namespace rivegm;
using namespace rive;

// Ensures the PLS render target does not get cleared when using
// LoadAction::preserveRenderTarget.
class PreserveRenderTargetBase : public GM
{
protected:
  PreserveRenderTargetBase(bool empty, BlendMode blendMode)
      : GM(64, 64)
      , m_empty(empty)
      , m_blendMode(blendMode)
  {}

  void run(const char* name, std::vector<uint8_t>* pixels) override
  {
    Paint yellow;
    yellow->color(0xffffff00);

    // Set the render target to a cyan background with a yellow circle.
    auto renderer = TestingWindow::Get()->beginFrame(
        {.clearColor = 0xff008080});
    renderer->drawPath(PathBuilder::Circle(32, 32, 20), yellow);

    // Don't clear to red!
    if (auto* renderContext = TestingWindow::Get()->renderContext())
    {
      rive::gpu::RenderContext::FrameDescriptor
          frameDescriptor = renderContext->frameDescriptor();
      frameDescriptor.loadAction = rive::gpu::LoadAction::preserveRenderTarget;
      frameDescriptor.clearColor = 0xffff0000;

      TestingWindow::Get()->flushPLSContext();
      renderContext->beginFrame(std::move(frameDescriptor));
    }
    else
    {
      TestingWindow::Get()->endFrame();
      renderer = TestingWindow::Get()->beginFrame({
          .clearColor = 0xffff0000,
          .doClear = false,
      });
    }

    if (!m_empty)
    {
      // Add a black circle on top of the preserved yellow one.
      Paint black;
      black->color(0xff000000);
      black->blendMode(m_blendMode);
      renderer->drawPath(PathBuilder::Circle(32, 32, 8), black);
    }

    TestingWindow::Get()->endFrame(pixels);
  }

  void onDraw(rive::Renderer*) override { RIVE_UNREACHABLE(); }

  const bool m_empty;
  const BlendMode m_blendMode;
};

class PreserveRenderTargetGM : public PreserveRenderTargetBase
{
public:
  PreserveRenderTargetGM() : PreserveRenderTargetBase(false, BlendMode::srcOver)
  {}
};
GMREGISTER(preserverendertarget, return new PreserveRenderTargetGM)

class PreserveRenderTargetBlendModeGM : public PreserveRenderTargetBase
{
public:
  PreserveRenderTargetBlendModeGM()
      : PreserveRenderTargetBase(false, BlendMode::darken)
  {}
};
GMREGISTER(
    preserverendertarget_blendmode,
    return new PreserveRenderTargetBlendModeGM)

class PreserveRenderTargetEmptyGM : public PreserveRenderTargetBase
{
public:
  PreserveRenderTargetEmptyGM()
      : PreserveRenderTargetBase(true, BlendMode::srcOver)
  {}
};
GMREGISTER(preserverendertarget_empty, return new PreserveRenderTargetEmptyGM)
