/*
 * Copyright 2025 Rive
 */

#include "testing_window.hpp"

#if !defined(RIVE_WEBGPU) || (RIVE_WEBGPU < 2)

TestingWindow* TestingWindow::MakeWGPU(const BackendParams&) { return nullptr; }

#else

#include "common/offscreen_render_target.hpp"
#include "rive/renderer/rive_renderer.hpp"
#include "rive/renderer/rive_render_image.hpp"
#include "rive/renderer/webgpu/render_context_webgpu_impl.hpp"

#ifdef RIVE_WAGYU
#include <webgpu/webgpu_wagyu.h>
#endif

#ifdef __EMSCRIPTEN__
#include <emscripten/emscripten.h>
#include <emscripten/html5.h>
#endif

namespace rive::gpu
{
static const char* wgpu_backend_name(wgpu::BackendType backendType)
{
    switch (backendType)
    {
        case wgpu::BackendType::Undefined:
            return "<unknown backend>";
        case wgpu::BackendType::Null:
            return "<null backend>";
        case wgpu::BackendType::WebGPU:
            return "WebGPU";
        case wgpu::BackendType::D3D11:
            return "D3D11";
        case wgpu::BackendType::D3D12:
            return "D3D12";
        case wgpu::BackendType::Metal:
            return "Metal";
        case wgpu::BackendType::Vulkan:
            return "Vulkan";
        case wgpu::BackendType::OpenGL:
            return "OpenGL";
        case wgpu::BackendType::OpenGLES:
            return "OpenGLES";
    }
    RIVE_UNREACHABLE();
}

static const char* pls_impl_name(
    const RenderContextWebGPUImpl::Capabilities& capabilities)
{
#ifdef RIVE_WAGYU
    switch (capabilities.plsType)
    {
        case RenderContextWebGPUImpl::PixelLocalStorageType::
            GL_EXT_shader_pixel_local_storage:
            return "GL_EXT_shader_pixel_local_storage";
        case RenderContextWebGPUImpl::PixelLocalStorageType::
            VK_EXT_rasterization_order_attachment_access:
            return "VK_EXT_rasterization_order_attachment_access";
        case RenderContextWebGPUImpl::PixelLocalStorageType::none:
            break;
    }
#endif
    return "<no pixel local storage>";
}

class TestingWindowWGPU : public TestingWindow
{
public:
    TestingWindowWGPU(const BackendParams& backendParams) :
        m_backendParams(backendParams)
    {
        m_instance = wgpu::CreateInstance(nullptr);
        assert(m_instance);

        m_instance.RequestAdapter(
            {},
            wgpu::CallbackMode::AllowSpontaneous,
            [](wgpu::RequestAdapterStatus status,
               wgpu::Adapter adapter,
               wgpu::StringView message,
               TestingWindowWGPU* this_) {
                assert(status == wgpu::RequestAdapterStatus::Success);
                this_->m_adapter = adapter;
            },
            this);
        while (!m_adapter)
        {
            emscripten_sleep(1);
        }

        m_adapter.RequestDevice(
            {},
            wgpu::CallbackMode::AllowSpontaneous,
            [](wgpu::RequestDeviceStatus status,
               wgpu::Device device,
               wgpu::StringView message,
               TestingWindowWGPU* this_) {
                assert(status == wgpu::RequestDeviceStatus::Success);
                this_->m_device = device;
            },
            this);
        while (!m_device)
        {
            emscripten_sleep(1);
        }

        m_queue = m_device.GetQueue();
        assert(m_queue);

        {
            wgpu::EmscriptenSurfaceSourceCanvasHTMLSelector htmlSelector;
            htmlSelector.selector = "#canvas";

            wgpu::SurfaceDescriptor surfaceDesc = {
                .nextInChain = &htmlSelector,
            };

            m_surface = m_instance.CreateSurface(&surfaceDesc);
            assert(m_surface);

            int w, h;
            emscripten_get_canvas_element_size("#canvas", &w, &h);
            m_width = w;
            m_height = h;
        }

        {
            wgpu::SurfaceCapabilities capabilities;
            m_surface.GetCapabilities(m_adapter, &capabilities);
            assert(capabilities.formatCount > 0);
            m_format = capabilities.formats[0];
            assert(m_format != wgpu::TextureFormat::Undefined);
            if (m_format != wgpu::TextureFormat::RGBA8Unorm &&
                m_format != wgpu::TextureFormat::BGRA8Unorm)
            {
                m_format = wgpu::TextureFormat::RGBA8Unorm;
            }
        }

        {
            wgpu::SurfaceConfiguration conf = {
                .device = m_device,
                .format = m_format,
            };
            m_surface.Configure(&conf);
        }

        RenderContextWebGPUImpl::ContextOptions contextOptions;
        m_renderContext = RenderContextWebGPUImpl::MakeContext(m_adapter,
                                                               m_device,
                                                               m_queue,
                                                               contextOptions);

        wgpu::AdapterInfo adapterInfo;
        m_adapter.GetInfo(&adapterInfo);
        printf("==== WGPU device: %s %s %s (%s, %s) ====\n",
               adapterInfo.vendor.data,
               adapterInfo.device.data,
               adapterInfo.description.data,
               wgpu_backend_name(impl()->capabilities().backendType),
               pls_impl_name(impl()->capabilities()));
    }

    rive::Factory* factory() override { return m_renderContext.get(); }

    rive::gpu::RenderContext* renderContext() const override
    {
        return m_renderContext.get();
    }

    rcp<rive_tests::OffscreenRenderTarget> makeOffscreenRenderTarget(
        uint32_t width,
        uint32_t height,
        bool riveRenderable) const override
    {
        return rive_tests::OffscreenRenderTarget::MakeWebGPU(impl(),
                                                             width,
                                                             height);
    }

    void resize(int width, int height) override
    {
        if (m_width != width || m_height != height)
        {
            m_overflowTexture = {};
            m_overflowTextureView = {};
            m_pixelReadBuff = {};
            TestingWindow::resize(width, height);
        }
    }

    std::unique_ptr<rive::Renderer> beginFrame(
        const FrameOptions& options) override
    {
        assert(m_currentCanvasTexture == nullptr);

        wgpu::SurfaceTexture surfaceTexture;
        m_surface.GetCurrentTexture(&surfaceTexture);

        m_currentCanvasTexture = surfaceTexture.texture;
        uint32_t surfaceWidth = m_currentCanvasTexture.GetWidth();
        uint32_t surfaceHeight = m_currentCanvasTexture.GetHeight();

        wgpu::TextureViewDescriptor textureViewDesc = {
            .format = m_format,
            .dimension = wgpu::TextureViewDimension::e2D,
        };

        m_currentCanvasTextureView =
            m_currentCanvasTexture.CreateView(&textureViewDesc);

        if (surfaceWidth < m_width || surfaceHeight < m_height)
        {
            if (!m_overflowTexture)
            {
                wgpu::TextureDescriptor overflowTextureDesc = {
                    .usage = wgpu::TextureUsage::RenderAttachment |
                             wgpu::TextureUsage::CopySrc,
                    .dimension = wgpu::TextureDimension::e2D,
                    .size = {m_width, m_height},
                    .format = m_format,
                };

                m_overflowTexture =
                    m_device.CreateTexture(&overflowTextureDesc);
                m_overflowTextureView = m_overflowTexture.CreateView();
            }
            assert(m_overflowTexture.GetWidth() == m_width);
            assert(m_overflowTexture.GetHeight() == m_height);

            m_renderTarget =
                m_renderContext->static_impl_cast<RenderContextWebGPUImpl>()
                    ->makeRenderTarget(m_format, m_width, m_height);
            m_renderTarget->setTargetTextureView(m_overflowTextureView,
                                                 m_overflowTexture);
        }
        else
        {
            m_renderTarget =
                m_renderContext->static_impl_cast<RenderContextWebGPUImpl>()
                    ->makeRenderTarget(m_format, surfaceWidth, surfaceHeight);
            m_renderTarget->setTargetTextureView(m_currentCanvasTextureView,
                                                 m_currentCanvasTexture);
        }

        rive::gpu::RenderContext::FrameDescriptor frameDescriptor = {
            .renderTargetWidth = m_renderTarget->width(),
            .renderTargetHeight = m_renderTarget->height(),
            .loadAction = options.doClear
                              ? rive::gpu::LoadAction::clear
                              : rive::gpu::LoadAction::preserveRenderTarget,
            .clearColor = options.clearColor,
            .msaaSampleCount = m_backendParams.msaa ? 4u : 0u,
            .disableRasterOrdering = options.disableRasterOrdering,
            .wireframe = options.wireframe,
            .fillsDisabled = options.fillsDisabled,
            .strokesDisabled = options.strokesDisabled,
            .clockwiseFillOverride =
                m_backendParams.clockwise || options.clockwiseFillOverride,
            .synthesizedFailureType = options.synthesizedFailureType,
        };
        m_renderContext->beginFrame(frameDescriptor);
        return std::make_unique<RiveRenderer>(m_renderContext.get());
    }

    void flushPLSContext(RenderTarget* offscreenRenderTarget) final
    {
        wgpu::CommandEncoder encoder = m_device.CreateCommandEncoder();
        m_renderContext->flush({
            .renderTarget = m_renderTarget.get(),
            .externalCommandBuffer = encoder.Get(),
        });
        wgpu::CommandBuffer commands = encoder.Finish();
        m_queue.Submit(1, &commands);
    }

    void endFrame(std::vector<uint8_t>* pixelData) override
    {
        flushPLSContext(nullptr);
        assert(m_currentCanvasTexture != nullptr);

        if (m_overflowTexture)
        {
            // Blit the overflow texture back to the canvas.
            wgpu::CommandEncoder encoder = m_device.CreateCommandEncoder();

            wgpu::TexelCopyTextureInfo src = {
                .texture = m_overflowTexture,
                .origin = {0, 0, 0},
            };

            wgpu::TexelCopyTextureInfo dst = {
                .texture = m_currentCanvasTexture,
                .origin = {0, 0, 0},
            };

            wgpu::Extent3D copySize{
                std::min(m_width, m_currentCanvasTexture.GetWidth()),
                std::min(m_height, m_currentCanvasTexture.GetHeight()),
            };

            encoder.CopyTextureToTexture(&src, &dst, &copySize);

            wgpu::CommandBuffer commands = encoder.Finish();
            m_queue.Submit(1, &commands);
        }

        if (pixelData != nullptr)
        {
            assert(m_format == wgpu::TextureFormat::RGBA8Unorm ||
                   m_format == wgpu::TextureFormat::BGRA8Unorm);
            bool invertY = false;
#ifdef RIVE_WAGYU
            invertY =
                impl()->capabilities().backendType ==
                    wgpu::BackendType::OpenGLES &&
                wgpuWagyuTextureIsSwapchain(m_currentCanvasTexture.Get()) &&
                m_overflowTexture == nullptr;
#endif
            const uint32_t rowBytesInReadBuff =
                math::round_up_to_multiple_of<256>(m_width * 4);

            // Create a buffer to receive the pixels.
            if (!m_pixelReadBuff)
            {
                wgpu::BufferDescriptor buffDesc{
                    .usage =
                        wgpu::BufferUsage::MapRead | wgpu::BufferUsage::CopyDst,
                    .size = m_height * rowBytesInReadBuff,
                };
                m_pixelReadBuff = m_device.CreateBuffer(&buffDesc);
            }
            assert(m_pixelReadBuff.GetSize() == m_height * rowBytesInReadBuff);

            // Blit the framebuffer into m_pixelReadBuff.
            wgpu::CommandEncoder readEncoder = m_device.CreateCommandEncoder();
            wgpu::TexelCopyTextureInfo srcTexture = {
                .texture = m_overflowTexture != nullptr
                               ? m_overflowTexture
                               : m_currentCanvasTexture,
                .origin = {0,
                           invertY ? m_renderTarget->height() - m_height : 0,
                           0},
            };
            wgpu::TexelCopyBufferInfo dstBuffer = {
                .layout =
                    {
                        .offset = 0,
                        .bytesPerRow = rowBytesInReadBuff,
                    },
                .buffer = m_pixelReadBuff,
            };
            wgpu::Extent3D copySize = {
                .width = m_width,
                .height = m_height,
            };
            readEncoder.CopyTextureToBuffer(&srcTexture, &dstBuffer, &copySize);

            wgpu::CommandBuffer commands = readEncoder.Finish(NULL);
            m_queue.Submit(1, &commands);

            {
                // Map m_pixelReadBuff.
                bool mappingFinished = false;
                m_pixelReadBuff.MapAsync(
                    wgpu::MapMode::Read,
                    0,
                    m_height * rowBytesInReadBuff,
                    wgpu::CallbackMode::AllowSpontaneous,
                    [](wgpu::MapAsyncStatus status,
                       wgpu::StringView message,
                       bool* mappingFinished) {
                        if (status != wgpu::MapAsyncStatus::Success)
                        {
                            fprintf(stderr,
                                    "failed to map m_pixelReadBuff: %s\n",
                                    message.data);
                            abort();
                        }
                        *mappingFinished = true;
                    },
                    &mappingFinished);
                while (!mappingFinished)
                {
                    emscripten_sleep(1);
                }
            }

            // Copy the image data from m_pixelReadBuff to pixelData.
            const size_t rowBytesInDst = m_width * 4;
            pixelData->resize(m_height * rowBytesInDst);
            const uint8_t* pixelReadBuffData = reinterpret_cast<const uint8_t*>(
                m_pixelReadBuff.GetConstMappedRange());
            for (size_t y = 0; y < m_height; ++y)
            {
                const uint8_t* src;
                if (invertY)
                {
                    src = &pixelReadBuffData[y * rowBytesInReadBuff];
                }
                else
                {
                    src = &pixelReadBuffData[(m_height - y - 1) *
                                             rowBytesInReadBuff];
                }
                uint8_t* dst = &(*pixelData)[y * rowBytesInDst];
                if (m_format == wgpu::TextureFormat::RGBA8Unorm)
                {
                    memcpy(dst, src, rowBytesInDst);
                }
                else
                {
                    assert(m_format == wgpu::TextureFormat::BGRA8Unorm);
                    for (size_t x = 0; x < rowBytesInDst; x += 4)
                    {
                        // BGBRA -> RGBA.
                        dst[x + 0] = src[x + 2];
                        dst[x + 1] = src[x + 1];
                        dst[x + 2] = src[x + 0];
                        dst[x + 3] = src[x + 3];
                    }
                }
            }
            m_pixelReadBuff.Unmap();
        }

        m_currentCanvasTextureView = {};
        m_currentCanvasTexture = {};
    }

private:
    RenderContextWebGPUImpl* impl() const
    {
        return m_renderContext->static_impl_cast<RenderContextWebGPUImpl>();
    }

    const BackendParams m_backendParams;

    wgpu::Instance m_instance = nullptr;
    wgpu::Adapter m_adapter;
    wgpu::Device m_device;
    wgpu::Surface m_surface;
    wgpu::TextureFormat m_format = wgpu::TextureFormat::Undefined;
    wgpu::Queue m_queue;
    wgpu::Texture m_currentCanvasTexture;
    wgpu::TextureView m_currentCanvasTextureView;
    wgpu::Texture m_overflowTexture;
    wgpu::TextureView m_overflowTextureView;
    wgpu::Buffer m_pixelReadBuff;

    std::unique_ptr<RenderContext> m_renderContext;
    rcp<RenderTargetWebGPU> m_renderTarget;
};
}; // namespace rive::gpu

TestingWindow* TestingWindow::MakeWGPU(const BackendParams& backendParams)
{
    return new rive::gpu::TestingWindowWGPU(backendParams);
}

#endif
