/*
 * 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;
        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())
