// DragonX Wallet - ImGui Edition
// Copyright 2024-2026 The Hush Developers
// Released under the GPLv3

#pragma once

#include <imgui.h>
#include <vector>
#include <string>

namespace dragonx {
namespace ui {
namespace effects {

/**
 * @brief Per-theme visual effects system.
 *
 * Draws animated accents (hue-cycling, rainbow borders, shimmer sweeps,
 * glow pulses, positional tinting) driven entirely by TOML theme config.
 * All effects use ImDrawList primitives — no shaders or texture uploads.
 */
class ThemeEffects {
public:
    static ThemeEffects& instance();

    /// Called once per frame (timing updates)
    void beginFrame();

    /// Master toggle (from settings)
    void setEnabled(bool enabled) { enabled_ = enabled; }
    bool isEnabled() const { return enabled_; }

    /// Background opacity (from window opacity slider).  Multiplies
    /// all effect alphas so they fade with the backdrop while UI stays opaque.
    void setBackgroundOpacity(float o) { bgOpacity_ = std::max(0.0f, std::min(1.0f, o)); }
    float backgroundOpacity() const { return bgOpacity_; }

    /// Reduced transparency suppresses shimmer + rainbow border
    void setReducedTransparency(bool rt) { reduced_transparency_ = rt; }
    bool isReducedTransparency() const { return reduced_transparency_; }

    /// Reload [effects] config from the active UISchema overlay
    void loadFromTheme();

    // === Drawing APIs ===

    /// Get the current hue-cycled accent color (optionally phase-shifted)
    ImU32 getAccentColor(float phaseOffset = 0.0f) const;

    /// Draw rainbow gradient border around a rect (for glass panels)
    void drawRainbowBorder(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
                           float rounding, float thickness) const;

    /// Draw shimmer sweep over a rect
    void drawShimmer(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
                     float rounding) const;

    /// Get positional hue tint for a given screen Y
    ImU32 getPositionalTint(float screenY) const;

    /// Tint an existing color by positional hue
    ImU32 tintByPosition(ImU32 baseColor, float screenY) const;

    /// Draw glow pulse behind a rect (for active elements)
    void drawGlowPulse(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
                       float rounding) const;

    /// Draw a light that traces along the border perimeter
    void drawEdgeTrace(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
                       float rounding) const;

    /// Draw a border that shifts between two colors over time (gem-like).
    /// phaseOffset (0..1) shifts this element's point in the color cycle so
    /// many panels don't pulse in unison; alphaMul scales the whole effect.
    void drawGradientBorderShift(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
                                 float rounding, float phaseOffset = 0.0f,
                                 float alphaMul = 1.0f) const;

    /// Draw ember particles that rise from an element (fire theme)
    void drawEmberRise(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax) const;

    /// Draw specular glare highlights on a panel (polished surface look)
    void drawSpecularGlare(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
                           float rounding) const;

    /// Draw viewport-wide ambient ember particles (fire theme atmosphere)
    void drawViewportEmbers(ImDrawList* dl) const;

    /// Draw viewport-wide sandstorm particles (wind-driven diagonal sand/dust)
    void drawSandstorm(ImDrawList* dl) const;

    /// Draw shader-like viewport overlay (color wash + vignette post-processing)
    void drawViewportOverlay(ImDrawList* dl) const;

    /// Draw all applicable panel effects (edge trace + ember rise on glass panels)
    /// phaseKey provides per-panel phase diversity based on panel position
    void drawPanelEffects(ImDrawList* dl, ImVec2 pMin, ImVec2 pMax,
                          float rounding) const;

    // === Query which effects are available ===
    bool hasRainbowBorder()    const { return enabled_ && !reduced_transparency_ && rainbow_border_.enabled; }
    bool hasShimmer()          const { return enabled_ && !reduced_transparency_ && shimmer_.enabled; }
    bool hasGlowPulse()        const { return enabled_ && glow_pulse_.enabled; }
    bool hasHueCycle()         const { return enabled_ && hue_cycle_.enabled; }
    bool hasPositionalHue()    const { return enabled_ && positional_hue_.enabled; }
    bool hasEdgeTrace()        const { return enabled_ && edge_trace_.enabled; }    bool hasGradientBorder()    const { return enabled_ && gradient_border_.enabled; }    bool hasEmberRise()        const { return enabled_ && ember_rise_.enabled; }
    bool hasSpecularGlare()    const { return enabled_ && !reduced_transparency_ && specular_glare_.enabled; }
    bool hasSandstorm()        const { return enabled_ && sandstorm_.enabled; }
    bool hasViewportOverlay()  const { return enabled_ && (viewport_overlay_.colorWashEnabled || viewport_overlay_.vignetteEnabled); }

    /// True when any per-panel visual effect is active (rainbow, shimmer, specular, edge, ember, gradient)
    bool hasAnyPanelEffect() const {
        return hasRainbowBorder() || hasShimmer() || hasSpecularGlare()
            || hasEdgeTrace() || hasEmberRise() || hasGradientBorder();
    }

    /// True when any time-dependent effect is active and needs continuous redraws
    bool hasActiveAnimation() const {
        if (!enabled_) return false;
        return hue_cycle_.enabled || rainbow_border_.enabled || shimmer_.enabled
            || glow_pulse_.enabled || edge_trace_.enabled || ember_rise_.enabled
            || gradient_border_.enabled || specular_glare_.enabled || sandstorm_.enabled
            || (viewport_overlay_.colorWashEnabled
                && (viewport_overlay_.washRotateSpeed > 0.0f || viewport_overlay_.washPulseSpeed > 0.0f));
    }

private:
    ThemeEffects() = default;

    bool enabled_ = true;
    bool reduced_transparency_ = false;
    float time_ = 0.0f;
    float bgOpacity_ = 1.0f;   ///< window-opacity multiplier for effect alphas

    // Viewport bounds (set each frame)
    float vpMinY_ = 0.0f;
    float vpMaxY_ = 1.0f;

    // ---- Cached config from [effects] ----

    struct HueCycleConfig {
        bool enabled = false;
        float speed = 0.1f, sat = 0.6f, val = 0.85f;
        float range = 1.0f, offset = 0.0f;
    } hue_cycle_;

    struct RainbowBorderConfig {
        bool enabled = false;
        float speed = 0.05f, alpha = 0.25f;
        std::vector<ImU32> stops;
    } rainbow_border_;

    struct ShimmerConfig {
        bool enabled = false;
        float speed = 0.12f, width = 80.0f, alpha = 0.06f, angle = 30.0f;
        ImU32 color = IM_COL32(255,255,255,255);
    } shimmer_;

    struct PositionalHueConfig {
        bool enabled = false;
        ImVec4 topColor{1,0.42f,0.62f,1};
        ImVec4 bottomColor{0.4f,0.91f,0.98f,1};
        float strength = 0.3f;
    } positional_hue_;

    struct GlowPulseConfig {
        bool enabled = false;
        float speed = 2.0f, minAlpha = 0.0f, maxAlpha = 0.15f, radius = 4.0f;
        ImU32 color = IM_COL32(255,255,255,255);
    } glow_pulse_;

    struct EdgeTraceConfig {
        bool enabled = false;
        float speed = 0.3f;       ///< full circuits per second
        float length = 0.20f;     ///< fraction of perimeter lit (tail length)
        float thickness = 1.5f;   ///< line thickness in pixels
        float alpha = 0.6f;       ///< peak alpha at head of trace
        ImU32 color = IM_COL32(255,255,255,255);
    } edge_trace_;

    struct EmberRiseConfig {
        bool enabled = false;
        int count = 8;            ///< number of ember particles
        float speed = 0.4f;       ///< rise cycles per second
        float particleSize = 1.5f;///< ember radius in pixels
        float alpha = 0.5f;       ///< peak alpha
        ImU32 color = IM_COL32(255, 120, 20, 255);
    } ember_rise_;

    struct GradientBorderConfig {
        bool enabled = false;
        bool panels = false;       ///< also draw on glass panels, not just the active nav button
        float speed = 0.15f;       ///< full color shift cycles per second
        float thickness = 1.5f;    ///< border line thickness in pixels
        float alpha = 0.6f;        ///< peak alpha
        ImU32 colorA = IM_COL32(206, 147, 216, 255);  ///< first color (amethyst)
        ImU32 colorB = IM_COL32(26, 35, 126, 255);    ///< second color (indigo)
    } gradient_border_;

    struct SpecularGlareConfig {
        bool enabled = false;
        float speed = 0.02f;       ///< drift speed (Lissajous orbit cycles/sec)
        float intensity = 0.06f;   ///< peak alpha at glare center
        float radius = 0.5f;       ///< glare radius as fraction of panel min-dim
        int   count = 2;           ///< number of specular spots per panel
        ImU32 color = IM_COL32(255, 255, 255, 255);
    } specular_glare_;

    struct SandstormConfig {
        bool enabled = false;
        int   count = 80;           ///< number of sand particles
        float speed = 0.35f;        ///< base horizontal velocity (viewport widths/sec)
        float windAngle = 15.0f;    ///< degrees from horizontal (+ve = downward)
        float particleSize = 1.5f;  ///< base particle radius in pixels
        float alpha = 0.35f;        ///< peak particle alpha
        float gustSpeed = 0.07f;    ///< gust oscillation frequency (Hz)
        float gustStrength = 0.4f;  ///< speed variation from gusts (fraction)
        float streakLength = 3.0f;  ///< motion blur multiplier for fast particles
        ImU32 color = IM_COL32(200, 160, 96, 255);
    } sandstorm_;

    struct ViewportOverlayConfig {
        // --- Color wash: full-screen 4-corner gradient overlay ---
        bool colorWashEnabled = false;
        ImU32 cornerTL = IM_COL32(255,100,0,255);  ///< top-left corner color (RGB; alpha applied separately)
        ImU32 cornerTR = IM_COL32(68,34,0,255);    ///< top-right
        ImU32 cornerBL = IM_COL32(68,17,0,255);    ///< bottom-left
        ImU32 cornerBR = IM_COL32(255,153,0,255);  ///< bottom-right
        float washAlpha = 0.05f;                    ///< overall wash intensity
        float washRotateSpeed = 0.0f;               ///< corner color rotation (turns/sec)
        float washPulseSpeed = 0.0f;                ///< alpha breathing speed (Hz)
        float washPulseDepth = 0.0f;                ///< pulse depth (0=none, 1=full fade)

        // --- Vignette: edge darkening/tinting ---
        bool vignetteEnabled = false;
        ImU32 vignetteColor = IM_COL32(0,0,0,255);  ///< tint color at edges
        float vignetteRadius = 0.35f;                ///< fade zone as fraction of viewport
        float vignetteAlpha = 0.30f;                 ///< max alpha at outer edge
    } viewport_overlay_;

    /// Map a 0..1 fraction to a point on the rounded rect perimeter
    ImVec2 perimeterPoint(ImVec2 pMin, ImVec2 pMax, float t, float rounding = 0.0f) const;

    // Helper: parse hex color string "#RRGGBB" or "#RRGGBBAA" to ImU32
    static ImU32 parseHexColor(const std::string& hex, ImU32 fallback = IM_COL32(255,255,255,255));
    static ImVec4 parseHexColorVec4(const std::string& hex, ImVec4 fallback = ImVec4(1,1,1,1));

    // Helper: sample a rotating multi-stop gradient
    ImU32 sampleGradient(float t) const;
};

} // namespace effects
} // namespace ui
} // namespace dragonx
