/*
 * Copyright 2025 Rive
 */

// GM test for the Ore graphics abstraction layer. Renders a colored triangle
// using the Ore API into a RenderCanvas, then composites the result into the
// main framebuffer via drawImage(). Verifies: makeBuffer, makeShaderModule,
// makePipeline, beginRenderPass, setVertexBuffer, draw, finish,
// wrapCanvasTexture, and the full Ore→Rive composite path.

#include "gm.hpp"
#include "gmutils.hpp"
#include "ore_gm_helper.hpp"
#if defined(ORE_BACKEND_METAL) || defined(ORE_BACKEND_D3D11) ||                \
    defined(ORE_BACKEND_D3D12) || defined(ORE_BACKEND_GL) ||                   \
    defined(ORE_BACKEND_WGPU) || defined(ORE_BACKEND_VK) ||                    \
    defined(ORE_BACKEND_RHI)
#include "rive/renderer/render_canvas.hpp"
#include "rive/renderer/ore/ore_buffer.hpp"
#include "rive/renderer/ore/ore_texture.hpp"
#include "rive/renderer/ore/ore_sampler.hpp"
#include "rive/renderer/ore/ore_shader_module.hpp"
#include "rive/renderer/ore/ore_pipeline.hpp"
#include "rive/renderer/ore/ore_render_pass.hpp"
#endif

using namespace rivegm;
using namespace rive;
using namespace rive::gpu;
#if defined(ORE_BACKEND_METAL) || defined(ORE_BACKEND_D3D11) ||                \
    defined(ORE_BACKEND_D3D12) || defined(ORE_BACKEND_GL) ||                   \
    defined(ORE_BACKEND_WGPU) || defined(ORE_BACKEND_VK) ||                    \
    defined(ORE_BACKEND_RHI)
using namespace rive::ore;
#endif

#if defined(ORE_BACKEND_METAL) || defined(ORE_BACKEND_D3D11) ||                \
    defined(ORE_BACKEND_D3D12) || defined(ORE_BACKEND_GL) ||                   \
    defined(ORE_BACKEND_WGPU) || defined(ORE_BACKEND_VK) ||                    \
    defined(ORE_BACKEND_RHI)

// Interleaved position (float2) + color (float4) per vertex.
struct Vertex
{
  float x, y;
  float r, g, b, a;
};

static const Vertex kTriangleVertices[] = {
    //  x      y       r     g     b     a
    {0.0f, 0.5f, 1.0f, 0.0f, 0.0f, 1.0f},   // top — red
    {-0.5f, -0.5f, 0.0f, 1.0f, 0.0f, 1.0f}, // bottom-left — green
    {0.5f, -0.5f, 0.0f, 0.0f, 1.0f, 1.0f},  // bottom-right — blue
};

#endif // ORE_BACKEND_METAL || ... || ORE_BACKEND_VK

class OreTriangleGM : public GM
{
public:
  OreTriangleGM() : GM(256, 256) {}

  ColorInt clearColor() const override { return 0xff000000; } // black

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

#if defined(ORE_BACKEND_METAL) || defined(ORE_BACKEND_D3D11) ||                \
    defined(ORE_BACKEND_D3D12) || defined(ORE_BACKEND_GL) ||                   \
    defined(ORE_BACKEND_WGPU) || defined(ORE_BACKEND_VK) ||                    \
    defined(ORE_BACKEND_RHI)
    auto& ctx = *renderContext->getOreContext();
    // Create a RenderCanvas to render into.
    auto canvas = renderContext->makeRenderCanvas(256, 256);
    if (!canvas)
      return;

    // Wrap the canvas texture for Ore.
    auto colorTarget = ctx.wrapCanvasTexture(canvas.get());
    if (!colorTarget)
      return;

    // Create vertex buffer.
    BufferDesc bufDesc{};
    bufDesc.usage = BufferUsage::vertex;
    bufDesc.size = sizeof(kTriangleVertices);
    bufDesc.data = kTriangleVertices;
    // Immutable, so the goldens check each backend still uploads its data.
    bufDesc.immutable = true;
    bufDesc.label = "ore_triangle_vbo";
    auto vbo = ctx.makeBuffer(bufDesc);

    // Load shader from the pre-compiled RSTB.
    auto shader = ore_gm::loadShader(ctx, ore_gm::kTriangle);
    if (!shader.vsModule)
      return;

    // Vertex layout: float2 position + float4 color, interleaved.
    ore::VertexAttribute attrs[] = {
        {offsetof(Vertex, x), 0, VertexFormat::float2}, // position
        {offsetof(Vertex, r), 1, VertexFormat::float4}, // color
    };
    VertexBufferLayout vertexLayout{};
    vertexLayout.stride = sizeof(Vertex);
    vertexLayout.stepMode = VertexStepMode::vertex;
    vertexLayout.attributes = attrs;
    vertexLayout.attributeCount = 2;

    // Pipeline.
    PipelineDesc pipeDesc{};
    pipeDesc.vertexModule = shader.vsModule.get();
    pipeDesc.fragmentModule = shader.psModule.get();
    pipeDesc.vertexEntryPoint = shader.vsEntryPoint;
    pipeDesc.fragmentEntryPoint = shader.fsEntryPoint;
    pipeDesc.vertexBuffers = &vertexLayout;
    pipeDesc.vertexBufferCount = 1;
    pipeDesc.topology = PrimitiveTopology::triangleList;
    pipeDesc.colorTargets[0].format = TextureFormat::rgba8unorm;
    pipeDesc.colorCount = 1;
    // No depth/stencil for this simple test.
    pipeDesc.depthStencil.depthCompare = CompareFunction::always;
    pipeDesc.depthStencil.depthWriteEnabled = false;
    pipeDesc.label = "ore_triangle_pipeline";
    auto pipeline = ctx.makePipeline(pipeDesc);

    // Render the triangle via Ore.
    m_ore.beginFrame(renderContext);

    ColorAttachment ca{};
    ca.view = colorTarget.get();
    ca.loadOp = LoadOp::clear;
    ca.storeOp = StoreOp::store;
    ca.clearColor = {0.1f, 0.1f, 0.1f, 1.0f}; // dark grey

    RenderPassDesc rpDesc{};
    rpDesc.colorAttachments[0] = ca;
    rpDesc.colorCount = 1;
    rpDesc.label = "ore_triangle_pass";

    auto pass = ctx.beginRenderPass(rpDesc);
    pass->setPipeline(pipeline.get());
    pass->setVertexBuffer(0, vbo.get());
    pass->setViewport(0, 0, 256, 256);
    pass->draw(3);
    pass->finish();

    m_ore.endFrame(renderContext);
    ore_gm::invalidateGLStateAfterOre(renderContext);

    // Composite the canvas into the main framebuffer via the original
    // renderer. No frame break needed — Ore rendered to a separate canvas
    // texture, not the main render target.
    originalRenderer->save();
    originalRenderer->drawImage(
        canvas->renderImage(),
        {.filter = ImageFilter::nearest},
        BlendMode::srcOver,
        1);
    originalRenderer->restore();
#endif
  }

private:
  ore_gm::OreGMContext m_ore;
};

GMREGISTER(ore_triangle, return new OreTriangleGM())
