/*
 * Copyright 2024 Rive
 */

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

#ifdef RIVE_TOOLS_NO_GL
using GLuint = uint32_t;
#else
#include "rive/renderer/gl/render_context_gl_impl.hpp"
#include "rive/renderer/gl/render_target_gl.hpp"
#endif

#include "assets/nomoon.png.hpp"

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

// Most gms render directly to the framebuffer. This GM checks that texture
// targets work in GL.
class OffscreenRenderTarget : public GM
{
public:
  OffscreenRenderTarget(
      BlendMode blendMode,
      bool riveRenderable,
      ColorInt clearColor = 0xffff00ff)
      : GM(256, 256)
      , m_blendMode(blendMode)
      , m_riveRenderable(riveRenderable)
      , m_clearColor(clearColor)
  {}

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

  void onDraw(rive::Renderer* originalRenderer) override
  {
    if (rcp<rive_tests::OffscreenRenderTarget>
            renderImageTarget = TestingWindow::Get()->makeOffscreenRenderTarget(
                256,
                256,
                m_riveRenderable))
    {
      // Intercept the current frameDescriptor and end the PLS frame.
      auto renderContext = TestingWindow::Get()->renderContext();
      auto originalFrameDescriptor = renderContext->frameDescriptor();
      TestingWindow::Get()->flushPLSContext();

      // Draw to the offscreen texture. Declare the frame dimensions
      // explicitly so Rive sizes its PLS buffers for the 256x256
      // offscreen render target we are about to flush into — otherwise,
      // on backends where the testing window's main frame descriptor is
      // larger than the logical GM size (e.g. wagyu where the surface
      // exceeds 256x256), the later flushPLSContext(renderImageTarget)
      // call trips the flushResources.renderTarget->width() ==
      // m_frameDescriptor.renderTargetWidth assertion in
      // RenderContext::flush.
      auto textureFrameDescriptor = originalFrameDescriptor;
      textureFrameDescriptor.renderTargetWidth = 256;
      textureFrameDescriptor.renderTargetHeight = 256;
      textureFrameDescriptor.clearColor = m_clearColor;
      renderContext->beginFrame(std::move(textureFrameDescriptor));
      RiveRenderer renderer(renderContext);
      drawInternal(&renderer, renderImageTarget->asRenderTarget());
      TestingWindow::Get()->flushPLSContext(
          renderImageTarget->asRenderTarget());

      // Copy the offscreen texture back to the destination framebuffer.
      RenderImage* renderImage = renderImageTarget->asRenderImage();
      auto copyFrameDescriptor = originalFrameDescriptor;
      copyFrameDescriptor.loadAction = gpu::LoadAction::preserveRenderTarget;
      copyFrameDescriptor.clearColor = 0xffff0000;
      renderContext->beginFrame(std::move(copyFrameDescriptor));
      renderer.save();
      if (renderContext->platformFeatures().framebufferBottomUp)
      {
        renderer.translate(0, 256);
        renderer.scale(1, -1);
      }
      renderer.drawImage(
          renderImage,
          {.filter = ImageFilter::nearest},
          BlendMode::srcOver,
          1);
      renderer.restore();
    }
    else
    {
      drawInternal(originalRenderer, nullptr);
    }
  }

  virtual void drawInternal(Renderer* renderer, RenderTarget*)
  {
    Paint paint5(0x8000ffff);
    paint5->blendMode(m_blendMode);
    drawStar5(renderer, paint5);

    Paint paint13(0x80ffff00);
    paint13->blendMode(m_blendMode);
    drawStar13(renderer, paint13);
  }

  void drawStar5(
      Renderer* renderer,
      RenderPaint* paint,
      FillRule fillRule = FillRule::nonZero)
  {
    PathBuilder builder;
    float theta = -math::PI / 7;
    builder.moveTo(cosf(theta), sinf(theta));
    for (int i = 0; i <= 7; ++i)
    {
      theta += 2 * math::PI * 2 / 7;
      builder.lineTo(cosf(theta), sinf(theta));
    }
    builder.fillRule(fillRule);
    renderer->save();
    renderer->translate(100, 100);
    renderer->scale(80, 80);
    renderer->drawPath(builder.detach(), paint);
    renderer->restore();
  }

  void drawStar13(
      Renderer* renderer,
      RenderPaint* paint,
      FillRule fillRule = FillRule::evenOdd)
  {
    PathBuilder builder;
    float theta = 0;
    for (int i = 0; i <= 13; ++i)
    {
      theta += 2 * math::PI * 3 / 13;
      builder.lineTo(cosf(theta), sinf(theta));
    }
    builder.fillRule(fillRule);
    renderer->save();
    renderer->translate(256 - 100, 256 - 100);
    renderer->scale(80, 80);
    renderer->drawPath(builder.detach(), paint);
    renderer->restore();
  }

protected:
  const BlendMode m_blendMode;
  const bool m_riveRenderable;
  const ColorInt m_clearColor;
};

GMREGISTER(
    offscreen_render_target,
    return new OffscreenRenderTarget(BlendMode::srcOver, true))
GMREGISTER(
    offscreen_render_target_nonrenderable,
    return new OffscreenRenderTarget(BlendMode::srcOver, false))
GMREGISTER(
    offscreen_render_target_lum,
    return new OffscreenRenderTarget(BlendMode::luminosity, true))
GMREGISTER(
    offscreen_render_target_lum_nonrenderable,
    return new OffscreenRenderTarget(BlendMode::luminosity, false))

GMREGISTER(
    offscreen_render_target_transparent_clear,
    return new OffscreenRenderTarget(BlendMode::srcOver, true, 0x7fff00ff))
GMREGISTER(
    offscreen_render_target_nonrenderable_transparent_clear,
    return new OffscreenRenderTarget(BlendMode::srcOver, false, 0x7fff00ff))
GMREGISTER(
    offscreen_render_target_lum_transparent_clear,
    return new OffscreenRenderTarget(BlendMode::luminosity, true, 0x7fff00ff))
GMREGISTER(
    offscreen_render_target_lum_nonrenderable_transparent_clear,
    return new OffscreenRenderTarget(BlendMode::luminosity, false, 0x7fff00ff))

// This GM checks that texture targets (including MSAA targets) work with
// LoadAction::preserveRenderTarget.
class OffscreenRenderTargetPreserve : public OffscreenRenderTarget
{
public:
  OffscreenRenderTargetPreserve(BlendMode blendMode, bool riveRenderable)
      : OffscreenRenderTarget(blendMode, riveRenderable)
  {}
  OffscreenRenderTargetPreserve(bool riveRenderable)
      : OffscreenRenderTargetPreserve(BlendMode::srcOver, riveRenderable)
  {}

  virtual void drawInternal(Renderer* renderer, RenderTarget* renderTarget)
  {
    ColorInt colors[2];
    float stops[2];
    colors[0] = 0xff000000;
    stops[0] = 0;
    colors[1] = 0xffff00ff;
    stops[1] = 1;
    Paint paint;
    paint->shader(TestingWindow::Get()
                      ->factory()
                      ->makeLinearGradient(0, 0, 250, 0, colors, stops, 2));
    renderer->drawPath(PathBuilder::Rect({0, 0, 256, 256}), paint);

    colors[0] = 0x80000000;
    stops[0] = 0;
    colors[1] = 0x8000ffff;
    stops[1] = 1;
    Paint paint2;
    paint2->shader(TestingWindow::Get()
                       ->factory()
                       ->makeLinearGradient(0, 0, 0, 250, colors, stops, 2));
    renderer->drawPath(PathBuilder::Rect({0, 0, 256, 256}), paint2);

    if (auto renderContext = TestingWindow::Get()->renderContext())
    {
      auto frameDescriptor = renderContext->frameDescriptor();
#ifndef RIVE_TOOLS_NO_GL
      if (auto plsImplGL = TestingWindow::Get()->renderContextGLImpl())
      {
        assert(renderTarget);
        TestingWindow::Get()->flushPLSContext(renderTarget);
        if (int sampleCount = frameDescriptor.msaaSampleCount)
        {
          // If the MSAA framebuffer target is not the target texture,
          // wipe it to red behind the scenes in order to make sure
          // our preservation codepath works. (It shouldn't appear red
          // in the end -- this should get preserved instead.)
          if (!plsImplGL->capabilities().EXT_multisampled_render_to_texture)
          {
            auto renderTextureTargetGL = static_cast<RenderTargetGL*>(
                renderTarget);
            renderTextureTargetGL->bindFramebufferForDepthStencilMode(
                plsImplGL,
                sampleCount,
                nullptr,
                nullptr);
            glClearColor(1, 0, 0, 1);
            glClear(GL_COLOR_BUFFER_BIT);
          }
        }
      }
      else
#endif
      {
        TestingWindow::Get()->flushPLSContext(renderTarget);
      }
      frameDescriptor.loadAction = gpu::LoadAction::preserveRenderTarget;
      renderContext->beginFrame(std::move(frameDescriptor));
    }
    Paint paint5(0x8000ffff);
    paint5->blendMode(m_blendMode);
    drawStar5(renderer, paint5);

    if (auto renderContext = TestingWindow::Get()->renderContext())
    {
      auto frameDescriptor = renderContext->frameDescriptor();
#ifndef RIVE_TOOLS_NO_GL
      if (auto plsImplGL = TestingWindow::Get()->renderContextGLImpl())
      {
        assert(renderTarget);
        TestingWindow::Get()->flushPLSContext(renderTarget);
        if (int sampleCount = frameDescriptor.msaaSampleCount)
        {
          // If the MSAA framebuffer target is not the target texture,
          // wipe it to red behind the scenes in order to make sure
          // our preservation codepath works. (It shouldn't appear red
          // in the end -- this should get preserved instead.)
          if (!plsImplGL->capabilities().EXT_multisampled_render_to_texture)
          {
            auto renderTextureTargetGL = static_cast<RenderTargetGL*>(
                renderTarget);
            renderTextureTargetGL->bindFramebufferForDepthStencilMode(
                plsImplGL,
                sampleCount,
                nullptr,
                nullptr);
            glClearColor(1, 0, 0, 1);
            glClear(GL_COLOR_BUFFER_BIT);
          }
        }
      }
      else
#endif
      {
        TestingWindow::Get()->flushPLSContext(renderTarget);
      }
      frameDescriptor.loadAction = gpu::LoadAction::preserveRenderTarget;
      renderContext->beginFrame(std::move(frameDescriptor));
    }
    Paint paint13(0x80ffff00);
    paint13->blendMode(m_blendMode);
    drawStar13(renderer, paint13);
  }
};
GMREGISTER(
    offscreen_render_target_preserve,
    return new OffscreenRenderTargetPreserve(true))
GMREGISTER(
    offscreen_render_target_preserve_nonrenderable,
    return new OffscreenRenderTargetPreserve(false))

// ...And verify that blend modes work on a texture target.
class OffscreenRenderTargetPreserveLum : public OffscreenRenderTargetPreserve
{
public:
  OffscreenRenderTargetPreserveLum(bool riveRenderable)
      : OffscreenRenderTargetPreserve(BlendMode::luminosity, riveRenderable)
  {}
};
GMREGISTER(
    offscreen_render_target_preserve_lum,
    return new OffscreenRenderTargetPreserveLum(true))
GMREGISTER(
    offscreen_render_target_preserve_lum_nonrenderable,
    return new OffscreenRenderTargetPreserveLum(false))

// This GM checks that virtual tiles work with various types of render targets.
class OffscreenVirtualTiles : public OffscreenRenderTarget
{
public:
  OffscreenVirtualTiles(gpu::LoadAction loadAction, BlendMode blendMode)
      : OffscreenRenderTarget(blendMode, /*riveRenderable=*/false)
      , m_loadAction(loadAction)
  {}

  virtual void drawInternal(Renderer* renderer, RenderTarget* renderTarget)
  {
    ColorInt colors[2];
    float stops[2];
    colors[0] = 0xff000000;
    stops[0] = 0;
    colors[1] = 0xffff00ff;
    stops[1] = 1;
    Paint paint;
    paint->shader(TestingWindow::Get()
                      ->factory()
                      ->makeLinearGradient(0, 0, 250, 0, colors, stops, 2));
    renderer->drawPath(PathBuilder::Rect({0, 0, 256, 256}), paint);

    colors[0] = 0x80000000;
    stops[0] = 0;
    colors[1] = 0x8000ffff;
    stops[1] = 1;
    Paint paint2;
    paint2->shader(TestingWindow::Get()
                       ->factory()
                       ->makeLinearGradient(0, 0, 0, 250, colors, stops, 2));
    renderer->drawPath(PathBuilder::Rect({0, 0, 256, 256}), paint2);

    if (auto renderContext = TestingWindow::Get()->renderContext())
    {
      auto frameDescriptor = renderContext->frameDescriptor();
      TestingWindow::Get()->flushPLSContext(renderTarget);
      frameDescriptor.loadAction = m_loadAction;
      frameDescriptor.virtualTileWidth = 37;
      frameDescriptor.virtualTileHeight = 23;
      renderContext->beginFrame(std::move(frameDescriptor));
    }

    Path largePathThatUsesInteriorTriangles;
    Paint transWhite;
    transWhite->color(0x80ffffff);
    transWhite->blendMode(m_blendMode);
    largePathThatUsesInteriorTriangles->addRect(0, 0, 1000, 1000);
    renderer->drawPath(
        largePathThatUsesInteriorTriangles.get(),
        transWhite.get());

    Paint paint5(0x8000ffff);
    paint5->blendMode(m_blendMode);
    drawStar5(renderer, paint5, FillRule::clockwise);

    auto img = LoadImage(assets::nomoon_png());

    {
      AutoRestore ar(renderer, true);
      renderer->translate(100, 30);
      renderer->scale(.4f, .4f);
      renderer
          ->drawImage(img.get(), ImageSampler::LinearClamp(), m_blendMode, .5f);
    }

    {
      Factory* factory = TestingWindow::Get()->factory();
      auto pts = factory->makeRenderBuffer(
          RenderBufferType::vertex,
          RenderBufferFlags::mappedOnceAtInitialization,
          4 * sizeof(Vec2D));
      memcpy(
          pts->map(),
          std::array<Vec2D, 4>{
              Vec2D{110, 110},
              Vec2D{200, 110},
              Vec2D{10, 200},
              Vec2D{270, 270}}
              .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(
          img.get(),
          ImageSampler::LinearClamp(),
          pts,
          uvs,
          indices,
          4,
          6,
          m_blendMode,
          .7f);
    }

    Paint paint13(0x80ffff00);
    paint13->blendMode(m_blendMode);
    paint13->feather(1);
    drawStar13(renderer, paint13, FillRule::clockwise);

    Paint white(0xffffffff);
    paint13->blendMode(m_blendMode);
    uint64_t lcg = 12789;
    for (size_t i = 0; i < 2000; ++i)
    {
      AutoRestore ar(renderer, true);
      renderer->translate(lcg & 0xff, (lcg >> 8) & 0xff);
      renderer->scale(.01f, .01f);
      drawStar5(renderer, white, FillRule::clockwise);
      lcg = lcg * 6364136223846793005ULL + 1;
    }
  }

private:
  const gpu::LoadAction m_loadAction;
};
GMREGISTER(
    offscreen_virtual_tiles_nonrenderable,
    return new OffscreenVirtualTiles(
        gpu::LoadAction::clear,
        BlendMode::srcOver))
GMREGISTER(
    offscreen_virtual_tiles_preserve_nonrenderable,
    return new OffscreenVirtualTiles(
        gpu::LoadAction::preserveRenderTarget,
        BlendMode::srcOver))
GMREGISTER(
    offscreen_virtual_tiles_lum_nonrenderable,
    return new OffscreenVirtualTiles(
        gpu::LoadAction::clear,
        BlendMode::luminosity))
GMREGISTER(
    offscreen_virtual_tiles_preserve_lum_nonrenderable,
    return new OffscreenVirtualTiles(
        gpu::LoadAction::preserveRenderTarget,
        BlendMode::luminosity))
