#include "fiddle_context.hpp"

#ifndef _WIN32

std::unique_ptr<FiddleContext> FiddleContext::MakeD3DPLS(FiddleContextOptions) { return nullptr; }

#else

#include "rive/pls/pls_renderer.hpp"
#include "rive/pls/d3d/pls_render_context_d3d_impl.hpp"
#include "rive/pls/d3d/d3d11.hpp"
#include <array>
#include <dxgi1_2.h>

#define GLFW_INCLUDE_NONE
#define GLFW_EXPOSE_NATIVE_WIN32
#include "GLFW/glfw3.h"
#include <GLFW/glfw3native.h>

using namespace rive;
using namespace rive::pls;

class FiddleContextD3DPLS : public FiddleContext
{
public:
    FiddleContextD3DPLS(ComPtr<IDXGIFactory2> d3dFactory,
                        ComPtr<ID3D11Device> gpu,
                        ComPtr<ID3D11DeviceContext> gpuContext,
                        const PLSRenderContextD3DImpl::ContextOptions& contextOptions) :
        m_d3dFactory(std::move(d3dFactory)),
        m_gpu(std::move(gpu)),
        m_gpuContext(std::move(gpuContext)),
        m_plsContext(PLSRenderContextD3DImpl::MakeContext(m_gpu, m_gpuContext, contextOptions))
    {}

    float dpiScale(GLFWwindow*) const override { return 1; }

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

    rive::pls::PLSRenderContext* plsContextOrNull() override { return m_plsContext.get(); }

    rive::pls::PLSRenderTarget* plsRenderTargetOrNull() override { return m_renderTarget.get(); }

    void onSizeChanged(GLFWwindow* window, int width, int height, uint32_t sampleCount) override
    {
        m_swapchain.Reset();

        DXGI_SWAP_CHAIN_DESC1 scd{};
        scd.Width = width;
        scd.Height = height;
        scd.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
        scd.SampleDesc.Count = 1;
        scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_UNORDERED_ACCESS;
        scd.BufferCount = 2;
        scd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
        VERIFY_OK(m_d3dFactory->CreateSwapChainForHwnd(m_gpu.Get(),
                                                       glfwGetWin32Window(window),
                                                       &scd,
                                                       NULL,
                                                       NULL,
                                                       m_swapchain.ReleaseAndGetAddressOf()));

        auto plsContextImpl = m_plsContext->static_impl_cast<PLSRenderContextD3DImpl>();
        m_renderTarget = plsContextImpl->makeRenderTarget(width, height);
        m_readbackTexture = nullptr;
    }

    void toggleZoomWindow() override {}

    std::unique_ptr<Renderer> makeRenderer(int width, int height) override
    {
        return std::make_unique<PLSRenderer>(m_plsContext.get());
    }

    void begin(const rive::pls::PLSRenderContext::FrameDescriptor& frameDescriptor) override
    {
        m_plsContext->beginFrame(frameDescriptor);
    }

    void flushPLSContext() final
    {
        if (m_renderTarget->targetTexture() == nullptr)
        {
            ComPtr<ID3D11Texture2D> backbuffer;
            VERIFY_OK(m_swapchain->GetBuffer(
                0,
                __uuidof(ID3D11Texture2D),
                reinterpret_cast<void**>(backbuffer.ReleaseAndGetAddressOf())));
            m_renderTarget->setTargetTexture(backbuffer);
        }
        m_plsContext->flush({.renderTarget = m_renderTarget.get()});
    }

    void end(GLFWwindow*, std::vector<uint8_t>* pixelData = nullptr) override
    {
        flushPLSContext();
        if (pixelData != nullptr)
        {
            uint32_t w = m_renderTarget->width();
            uint32_t h = m_renderTarget->height();
            if (m_readbackTexture == nullptr)
            {
                D3D11_TEXTURE2D_DESC readbackTexDesc{};
                readbackTexDesc.Width = w;
                readbackTexDesc.Height = h;
                readbackTexDesc.MipLevels = 1;
                readbackTexDesc.ArraySize = 1;
                readbackTexDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
                readbackTexDesc.SampleDesc.Count = 1;
                readbackTexDesc.Usage = D3D11_USAGE_STAGING;
                readbackTexDesc.BindFlags = 0;
                readbackTexDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
                readbackTexDesc.MiscFlags = 0;
                VERIFY_OK(m_gpu->CreateTexture2D(&readbackTexDesc,
                                                 nullptr,
                                                 m_readbackTexture.ReleaseAndGetAddressOf()));
            }

            D3D11_MAPPED_SUBRESOURCE map;
            m_gpuContext->CopyResource(m_readbackTexture.Get(), m_renderTarget->targetTexture());
            m_gpuContext->Map(m_readbackTexture.Get(), 0, D3D11_MAP_READ, 0, &map);
            pixelData->resize(h * w * 4);
            for (int y = 0; y < h; ++y)
            {
                auto row = reinterpret_cast<const char*>(map.pData) + map.RowPitch * y;
                memcpy(pixelData->data() + (h - y - 1) * w * 4, row, w * 4);
            }
            m_gpuContext->Unmap(m_readbackTexture.Get(), 0);
        }
        m_swapchain->Present(0, 0);

        m_renderTarget->setTargetTexture(nullptr);
    }

private:
    ComPtr<IDXGIFactory2> m_d3dFactory;
    ComPtr<ID3D11Device> m_gpu;
    ComPtr<ID3D11DeviceContext> m_gpuContext;
    ComPtr<IDXGISwapChain1> m_swapchain;
    ComPtr<ID3D11Texture2D> m_readbackTexture;
    std::unique_ptr<PLSRenderContext> m_plsContext;
    rcp<PLSRenderTargetD3D> m_renderTarget;
};

std::unique_ptr<FiddleContext> FiddleContext::MakeD3DPLS(FiddleContextOptions fiddleOptions)
{
    // Create a DXGIFactory object.
    ComPtr<IDXGIFactory2> factory;
    VERIFY_OK(CreateDXGIFactory(__uuidof(IDXGIFactory2),
                                reinterpret_cast<void**>(factory.ReleaseAndGetAddressOf())));

    ComPtr<IDXGIAdapter> adapter;
    DXGI_ADAPTER_DESC adapterDesc{};
    PLSRenderContextD3DImpl::ContextOptions contextOptions;
    if (fiddleOptions.disableRasterOrdering)
    {
        contextOptions.disableRasterizerOrderedViews = true;
        // Also disable typed UAVs in atomic mode, to get more complete test coverage.
        contextOptions.disableTypedUAVLoadStore = true;
    }
    for (UINT i = 0; factory->EnumAdapters(i, &adapter) != DXGI_ERROR_NOT_FOUND; ++i)
    {
        adapter->GetDesc(&adapterDesc);
        contextOptions.isIntel = adapterDesc.VendorId == 0x163C || adapterDesc.VendorId == 0x8086 ||
                                 adapterDesc.VendorId == 0x8087;
        break;
    }

    ComPtr<ID3D11Device> gpu;
    ComPtr<ID3D11DeviceContext> gpuContext;
    D3D_FEATURE_LEVEL featureLevels[] = {D3D_FEATURE_LEVEL_11_1};
    UINT creationFlags = 0;
#ifdef DEBUG
    creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
    VERIFY_OK(D3D11CreateDevice(adapter.Get(),
                                D3D_DRIVER_TYPE_UNKNOWN,
                                NULL,
                                creationFlags,
                                featureLevels,
                                std::size(featureLevels),
                                D3D11_SDK_VERSION,
                                gpu.ReleaseAndGetAddressOf(),
                                NULL,
                                gpuContext.ReleaseAndGetAddressOf()));
    if (!gpu || !gpuContext)
    {
        return nullptr;
    }

    printf("D3D device: %S\n", adapterDesc.Description);

    return std::make_unique<FiddleContextD3DPLS>(std::move(factory),
                                                 std::move(gpu),
                                                 std::move(gpuContext),
                                                 contextOptions);
}

#endif
