/*
 * Copyright 2022 Rive
 */

#ifndef TESTING_WINDOW_HPP
#define TESTING_WINDOW_HPP

#include "common/offscreen_render_target.hpp"
#include "rive/renderer/gpu.hpp"
#include "rive/renderer/shader_compilation_mode.hpp"
#include "rive/renderer/triangulation_controller.hpp"
#include "rive/refcnt.hpp"
#include <limits>
#include <memory>
#include <vector>
#include <string>

// Every harness that compares rendered pixels against a baseline (gms,
// goldens) must render deterministically, so none of them impose a frame-time
// limit on triangulation: a path meant to exercise triangulation has to do so
// on every run and machine. The guards still apply -- GMs can tune those per
// test in updateFrameOptions().
//
// Every frame a harness opens has to use these, not just the ones that look
// like they matter: goldens' immediate and deferred paths only produce
// identical pixels if both do.
//
// Interactive tools (the player) deliberately don't use this; they want
// production budgeting behavior.
constexpr rive::gpu::TriangulationThresholds
    DeterministicTriangulationThresholds = {
        .frameBudgetMs = std::numeric_limits<float>::infinity(),
};

namespace rive
{
class Renderer;
class Factory;
namespace gpu
{
class RenderContext;
class RenderContextGLImpl;
class RenderTarget;
class Texture;
class TextureRenderTarget;
} // namespace gpu
}; // namespace rive

// Wraps a factory for rive::Renderer and a singleton target for it to render
// into (GL window, HTML canvas, software buffer, etc.):
//
//   TestingWindow::Init(type);
//   renderer = TestingWindow::Get()->reset(width, height);
//   ...
//

class TestingWindow
{
public:
    enum class Backend
    {
        gl,
        d3d,
        d3d12,
        metal,
        vk,

        // Vulkan on Metal, aka MoltenVK.
        // (defaults to /usr/local/share/vulkan/icd.d/MoltenVK_icd.json if
        // VK_ICD_FILENAMES is not set.)
        moltenvk,

        // Swiftshader, Google's CPU implementation of Vulkan.
        // (defaults to ./vk_swiftshader_icd.json if VK_ICD_FILENAMES is not
        // set.)
        swiftshader,

        angle,
        dawn,
        wgpu,
        external,
        coregraphics,
        skia,
        canvas2d,
        svg,
        null,
        invalid,
    };

    enum class Target
    {
        host,
        android,
        ios,
        iossim,
        unreal,
        unreal_android,
        webbrowser,
        webserver,
        webbrowserandroid,
        webserverandroid,
        console,
    };

    enum class ANGLERenderer
    {
        metal,
        d3d11,
        vk,
        gles,
        gl,
    };

    struct BackendParams
    {
        bool atomic = false;
        bool core = false;
        bool srgb = false;
        bool clockwise = false;
        bool disableValidationLayers = false;
        bool disableDebugCallbacks = false;
        bool wantVulkanSynchronizationValidation = false;

        //  0 => non-depthStencil mode (if supported; else 4x MSAA)
        //  1 => depthStencil w/o MSAA
        // >1 => depthStencil with MSAA
        uint32_t msaaSampleCount = 0;

        rive::gpu::ShaderCompilationMode shaderCompilationMode =
            rive::gpu::ShaderCompilationMode::standard;

        ANGLERenderer angleRenderer =
#ifdef __APPLE__
            ANGLERenderer::metal;
#elif defined(_WIN32)
            ANGLERenderer::d3d11;
#else
            ANGLERenderer::vk;
#endif
        std::string gpuNameFilter;

        // How a window presents: fifo waits for vblank, relaxed tears when
        // late, mailbox and immediate run uncapped. Only the Artemis window
        // reads this today, and it falls back to fifo when the surface lacks
        // the mode.
        enum class PresentMode
        {
            fifo,
            fifoRelaxed,
            mailbox,
            immediate,
        };
        PresentMode presentMode = PresentMode::fifo;
    };

    enum class Visibility
    {
        headless,
        window,
        fullscreen,
    };

    enum class InputEvent
    {
        KeyPress,
        MouseDown,
        MouseUp,
        MouseMove,
        GamepadConnected,
        GamepadDisconnected,
        GamepadChange,
    };

    // Aligns with GLFW's mouse button enum
    enum MouseButton : int
    {
        Left,
        Right,
        Middle,
        // can support more buttons
    };

    struct InputEventData
    {
        InputEventData() : InputEventData(InputEvent::KeyPress, '\0') {}

        InputEventData(InputEvent type, float posX, float posY) :
            eventType(type)
        {
            metadata = {.posX = posX, .posY = posY};
        }

        InputEventData(InputEvent type, char c) : eventType(type)
        {
            metadata = {.key = c};
        }

        // A gamepad arriving, with its standard layout button and axis counts.
        InputEventData(InputEvent type,
                       uint32_t deviceId,
                       uint8_t buttonCount,
                       uint8_t axisCount) :
            eventType(type)
        {
            metadata.pad = {.deviceId = deviceId,
                            .buttonCount = buttonCount,
                            .axisCount = axisCount};
        }

        // One standard layout button or axis changing value.
        InputEventData(InputEvent type,
                       uint32_t deviceId,
                       bool isAxis,
                       uint8_t index,
                       float value) :
            eventType(type)
        {
            metadata.pad = {.deviceId = deviceId,
                            .isAxis = isAxis,
                            .index = index,
                            .value = value};
        }

        InputEvent eventType;

        union
        {
            struct
            {
                // Move & down/up mouse press events all have coords
                float posX;
                float posY;
            };

            char key;
            struct
            {
                uint32_t deviceId;
                bool isAxis;
                uint8_t index;
                uint8_t buttonCount;
                uint8_t axisCount;
                float value;
            } pad;
        } metadata;
    };

    static const char* BackendName(Backend);

    static Backend TryParseBackend(const char* name, BackendParams*);
    static Backend ParseBackend(const char* name, BackendParams*);
    static TestingWindow* Init(Backend,
                               const BackendParams&,
                               Visibility,
                               void* platformWindow = nullptr);
    static TestingWindow* Get();
    static void Set(TestingWindow* inWindow);
    static void Destroy();
    static Backend backend() { return s_Backend; }
    static Target target() { return s_Target; }
    static void SetTarget(Target target) { s_Target = target; }
    static bool isUnreal()
    {
        return s_Target == Target::unreal || s_Target == Target::unreal_android;
    }

    uint32_t width() const { return m_width; }
    uint32_t height() const { return m_height; }

    virtual rive::Factory* factory() = 0;
    virtual void resize(int width, int height)
    {
        m_width = width;
        m_height = height;
    }

    // This is called by the gm testing after each GM runs
    virtual void onceAfterGM() {}

    struct FrameOptions
    {
        const char* name;
        uint32_t clearColor;
        bool doClear = true;
        bool forceMSAA = false;
        bool disableRasterOrdering = false;
        bool wireframe = false;
        bool fillsDisabled = false;
        bool strokesDisabled = false;
        bool clockwiseFillOverride = false;
        rive::gpu::TriangulationThresholds triangulationThresholds;
#ifdef WITH_RIVE_TOOLS
        rive::gpu::SynthesizedFailureType synthesizedFailureType =
            rive::gpu::SynthesizedFailureType::none;
        rive::gpu::ShaderCompilationMode shaderCompilationMode =
            rive::gpu::ShaderCompilationMode::standard;
#endif
    };
    virtual std::unique_ptr<rive::Renderer> beginFrame(const FrameOptions&) = 0;
    virtual void endFrame(std::vector<uint8_t>* pixelData = nullptr) = 0;

    // The descriptor fields that pick a frame's interlock mode.
    struct FrameMode
    {
        uint32_t msaaSampleCount = 0;
        bool disableRasterOrdering = false;
        bool clockwiseFillOverride = false;
    };
    // Windows that add backend settings resolve them here, so a replayed
    // canvas opens in the same mode as the screen.
    virtual FrameMode frameMode(const FrameOptions& options) const
    {
        return {options.forceMSAA ? 4u : 0u,
                options.disableRasterOrdering,
                options.clockwiseFillOverride};
    }
    // Override to open a replayed canvas differently from the screen.
    virtual FrameMode canvasFrameMode(const FrameOptions& options) const
    {
        return frameMode(options);
    }

    // For testing directly on RenderContext.
    virtual rive::gpu::RenderContext* renderContext() const { return nullptr; }
    virtual rive::gpu::RenderContextGLImpl* renderContextGLImpl() const
    {
        return nullptr;
    }
    virtual rive::gpu::RenderTarget* renderTarget() const { return nullptr; }

    // Creates a new render target, for testing offscreen rendering.
    // If riveRenderable is false, the texture will lack features required by
    // Rive for rendering directly to it (e.g., input attachment, UAV, etc.),
    // which will exercise indirect rendering fallbacks.
    virtual rive::rcp<rive_tests::OffscreenRenderTarget>
    makeOffscreenRenderTarget(uint32_t width,
                              uint32_t height,
                              bool riveRenderable) const
    {
        return nullptr;
    }

    // For testing render pass breaks. Caller must call
    // renderContext()->beginFrame() again.
    virtual void flushPLSContext(
        rive::gpu::RenderTarget* offscreenRenderTarget = nullptr)
    {}

    virtual bool consumeInputEvent(InputEventData& eventData) { return false; }
    virtual InputEventData waitForInputEvent()
    {
        fprintf(stderr, "TestingWindow::waitForInputEvent not implemented.");
        abort();
    }

    virtual bool shouldQuit() const { return false; }

    virtual void hotloadShaders() {}

#if defined(__APPLE__)
    // Returns the Metal command queue as void* to avoid <Metal/Metal.h> in
    // this cross-platform header (same pattern as externalCommandBuffer).
    virtual void* metalQueue() const { return nullptr; }
#endif

#ifdef RIVE_VULKAN
    // Vulkan accessors for ORE VK backend initialization in GMs.
    virtual void* vulkanGraphicsQueue() const { return nullptr; }
    virtual uint32_t vulkanGraphicsQueueFamilyIndex() const { return 0; }
    virtual void* vulkanGetInstanceProcAddr() const { return nullptr; }
#endif

    // Returns the host's currently-recording command buffer (as
    // void*) Returns nullptr on backends that don't use command buffers / lists
    virtual void* getCurrentCommandBuffer() const { return nullptr; }

    // Host-managed ore::Context, or nullptr. Player wires into the file's
    // ScriptingContext for GPUCanvas content.
    virtual void* getOreContext() const { return nullptr; }

    // Per-frame ORE driving; no-op on non-ORE harnesses.
    virtual void beginOreFrame() {}
    virtual void endOreFrame() {}

    // Whether scripts may draw into renderTarget() under Rive's content, and
    // its format, answered without touching it so the recording thread can
    // declare it.
    struct OreTarget
    {
        bool exposed = false;
        bool bgra = false;
    };
    virtual OreTarget oreTarget() const { return {}; }

    // Whether beginFrame through endFrame may run off the thread that made the
    // window. A current GL context or GLFW event polling in endFrame says no.
    virtual bool supportsRenderThread() const { return false; }

    virtual ~TestingWindow() {}

    static TestingWindow* MakeEGL(Backend,
                                  const BackendParams&,
                                  void* platformWindow);
#if defined(__APPLE__) && !defined(RIVE_UNREAL)
    static TestingWindow* MakeMetalTexture(const BackendParams&);
#endif
#if defined(RIVE_IOS) || defined(RIVE_IOS_SIMULATOR)
    static TestingWindow* MakeMetalLayer(const BackendParams&,
                                         void* platformWindow);
#endif
    static TestingWindow* MakeCoreGraphics();
    static TestingWindow* MakeFiddleContext(Backend,
                                            const BackendParams&,
                                            Visibility,
                                            void* platformWindow);
    static TestingWindow* MakeVulkanTexture(const BackendParams&);
    static TestingWindow* MakeAndroidVulkan(const BackendParams&,
                                            void* platformWindow);
    // Hook for platforms without rive_vk_bootstrap; default returns nullptr.
    // Platform packages override in their own TU + define
    // RIVE_PLATFORM_TESTING_WINDOW.
    static TestingWindow* MakePlatformVulkan(const BackendParams&);
    static TestingWindow* MakeWGPU(const BackendParams&);
    static TestingWindow* MakeSVG();
    static TestingWindow* MakeSkia();
    static TestingWindow* MakeCanvas2D();
    static TestingWindow* MakeNULL();

protected:
    uint32_t m_width = 0;
    uint32_t m_height = 0;

    static Backend s_Backend;
    static Target s_Target;
};

#endif
