#pragma once

#include "dialogue/DialogueRuntime.h"
#include "render/Renderer.h"
#include "render/TextRenderer.h"
#include "render/TextureManager.h"
#include "UiManager.h"
#include <memory>
#include <string>
#include <vector>

namespace ZL::Dialogue {

class DialogueOverlay {
public:
    bool init(Renderer& renderer, const std::string& zipFile = "");
    void update(const PresentationModel& model, int deltaMs);
    void draw(Renderer& renderer, const PresentationModel& model);

    void handlePointerDown(float x, float y, const PresentationModel& model);
    void handlePointerMoved(float x, float y, const PresentationModel& model);
    bool handlePointerReleased(float x, float y, const PresentationModel& model, int& outChoiceIndex, bool& outAdvanceDialogue);
    bool consumeSkipRequested();

private:
    struct TexturedQuad {
        UiRect rect;
        VertexRenderStruct mesh;
        bool initialized = false;

        void rebuild(const UiRect& newRect);
        void rebuildWithUV(
            const UiRect& newRect,
            const Eigen::Vector2f& uvBottomLeft,
            const Eigen::Vector2f& uvTopLeft,
            const Eigen::Vector2f& uvTopRight,
            const Eigen::Vector2f& uvBottomRight
        );
    };

    struct ResolvedViewport {
        float centerXPx = 0.0f;
        float centerYPx = 0.0f;
        float widthPx = 1.0f;
        float heightPx = 1.0f;
        float rotationDeg = 0.0f;
    };

    Renderer* rendererRef = nullptr;
    std::string zipFilename;

    std::shared_ptr<Texture> textboxTexture;
    std::shared_ptr<Texture> portraitFrameTexture;
    std::shared_ptr<Texture> choiceMainTexture;
    std::shared_ptr<Texture> choiceOptionalTexture;
    std::shared_ptr<Texture> choiceSelectedTexture;
    std::shared_ptr<Texture> cutsceneSubtitleTexture;

    mutable std::vector<UiRect> lastChoiceRects;
    mutable UiRect lastDialogueAdvanceRect{};
	mutable UiRect lastCutsceneAdvanceRect{};
    mutable UiRect lastCutsceneSkipRect{};

    int hoveredChoiceIndex = -1;

    // Cutscene skip UX:
    // First LMB/tap anywhere arms skip and shows a hint for 5 seconds.
    // While armed, holding LMB/touch anywhere for 3.5 seconds requests skip.
    bool cutsceneSkipHintVisible = false;
    bool cutsceneSkipArmed = false;
    bool cutsceneSkipHolding = false;
    bool cutsceneSkipTriggered = false;
    int cutsceneSkipHintRemainingMs = 0;
    int cutsceneSkipHoldElapsedMs = 0;
    static constexpr int CutsceneSkipHintDurationMs = 5000;
    static constexpr int CutsceneSkipHoldDurationMs = 3500;

    std::unique_ptr<TextRenderer> nameRenderer;
    std::unique_ptr<TextRenderer> bodyRenderer;
    std::unique_ptr<TextRenderer> choiceRenderer;
    std::unique_ptr<TextRenderer> cutsceneRenderer;

    TexturedQuad portraitQuad;
    TexturedQuad textboxQuad;
    TexturedQuad subtitleQuad;
    TexturedQuad backgroundQuad;
    TexturedQuad skipHintBgQuad;
    TexturedQuad skipProgressBgQuad;
    TexturedQuad skipProgressFillQuad;
    mutable std::vector<TexturedQuad> choiceQuads;

    void drawDialogue(Renderer& renderer, const PresentationModel& model);
    void drawCutscene(Renderer& renderer, const PresentationModel& model);

    std::shared_ptr<Texture> loadTextureCached(const std::string& path);
    void drawQuad(Renderer& renderer, const TexturedQuad& quad, const std::shared_ptr<Texture>& texture) const;

    static std::string wrapText(const std::string& input, size_t maxLineLength);
    static std::string wrapTextToWidth(const std::string& input, const TextRenderer& textRenderer, float maxWidthPx, float scale);
    static bool rectContains(const UiRect& rect, float x, float y);

    static float lerpFloat(float a, float b, float t);
    static ResolvedViewport resolveViewportPose(
        const CutsceneCameraPose& pose,
        float texW,
        float texH,
        float screenW,
        float screenH
    );
    static ResolvedViewport blendViewport(
        const ResolvedViewport& from,
        const ResolvedViewport& to,
        float t
    );
};

} // namespace ZL::Dialogue
