-- [ ORBIT CONSTANTS ]--------------------------------------------------------------------------------
local _, Orbit = ...

---@class OrbitConstants
Orbit.Constants = {}
local C = Orbit.Constants

-- [ UI PANEL LAYOUT ]--------------------------------------------------------------------------------
C.Panel = {
    Width = 340,
    DialogWidth = 370,
    MinDialogHeight = 150,
    MaxHeight = 800,
    ScrollbarWidth = 26,
    ContentPadding = 3,
    DividerWidth = 280,
    DividerHeight = 16,
    HeaderHeight = 55, -- Height to clear tabs completely
    TitlePadding = 50, -- Dialog title area padding
}


C.Footer = {
    TopPadding = 12,
    BottomPadding = 12,
    ButtonHeight = 20,
    RowSpacing = 6,
    SidePadding = 5,
    ButtonSpacing = 8,
    DividerOffset = 6,
}

-- [ WIDGET LAYOUT ]----------------------------------------------------------------------------------
-- All widgets follow: [Fixed Label, Left] [Dynamic Control, Fill] [Fixed Value, Right]
C.Widget = {
    Width = 240,
    Height = 26,
    LabelWidth = 100, -- Fixed width for left label column
    LabelGap = 3, -- Gap between label and control
    ValueWidth = 65, -- Fixed width for right value column
    ValueInset = 3, -- Right-edge inset for value-column content (text and controls share this)
    ValueSwatchSize = 21, -- Color swatch box in the value column
    ValueCheckboxSize = 26, -- Value-column checkbox; larger than the swatch so its art's padded box renders the same visible size
    CheckboxIconWidth = 32,
    CheckboxIconGap = 4,
}

-- [ FRAME CONSTANTS ]--------------------------------------------------------------------------------
C.Frame = {
    EditModeColor = { r = 0.7, g = 0.6, b = 1.0 }, -- Light Purple
}

C.Selection = {
    ShiftMultiplier = 10, -- Shift+scroll multiplier for padding adjustment
    AnchorLineThickness = 2, -- Green anchor indicator line thickness
    WheelDebounce = 0.05, -- Mouse wheel event debounce delay
    TooltipFadeDuration = 1.0, -- Position tooltip fade-out delay
    PositionTooltip = { Width = 100, Height = 24 },
    OverlayLevelOffset = 100, -- Frame level offset for selection overlay
}

-- [ FRAME LAYER HIERARCHY ]--------------------------------------------------------------------------
-- Draw Layer Sublevels: background → border → icons → highlights → borders → glows → text
C.Layers = {
    BackdropDeep = -8,  -- Deep backgrounds (bar fills, status textures)
    Border = 1,         -- Frame borders
    Icon = 3,           -- Icons, status textures
    Highlight = 5,      -- Border highlights, selection markers
    Glow = 6,           -- Proc/pandemic glow effects
    Text = 7,           -- Text, component icons (role, leader)
}

-- Frame Level Offsets (relative to parent)
C.Levels = {
    StatusBar = 1,          -- Health/power/damage/absorb bars, cooldown swipe
    Border = 5,             -- Borders, glows, base level for highlight band
    DispelGlow = 7,         -- Dispel glow particles, must render above aggro/selection highlight (Border+1)
    Overlay = 7,            -- Text, icons, components, proc overlays, aura containers
    StrataBlockReserve = 50,-- Reserve size allocated per entity in StrataEngine
    SmartGuides = 90,       -- Canvas Mode snap guides (different strata)
    Tooltip = 100,          -- Tooltip/flyout layer (different strata)
    
    IconContent = 1,        -- Icon backdrop
    IconSwipe = 2,          -- Cooldown swipe (border group, below glow)
    IconBorder = 3,         -- Per-icon pixel/NineSlice border
    IconOverlay = 7,        -- Text, stacks, flash
    IconGlow = 9,           -- Pandemic/proc glow — above per-icon AND merged group borders (IconOverlay)
    -- Editor & UI Overlays
    EditModeText = 20,
    EditModeSelection = 100,
    CanvasComponent = 5,
    CanvasOverlay = 10,
    SecondaryDemote = -5,
    ColorPickerSwatch = 10,
    WhatsNewDialog = 200,
}

-- Frame Strata (Semantic mapping to WoW stratas)
C.Strata = {
    Background = "BACKGROUND",    -- Behind everything (e.g., base backdrop bounds)
    Base = "LOW",                 -- Bottom layer UI components
    HUD = "MEDIUM",               -- Standard HUD frames (UnitFrames, ActionBars)
    Overlay = "HIGH",             -- On top of HUD (Canvas Mode, Active Selections)
    Dialog = "DIALOG",            -- Popups (Config panels, EditMode Tour)
    FullscreenDialog = "FULLSCREEN_DIALOG", -- Enforced top popups (Color Picker dialog)
    Topmost = "TOOLTIP",          -- Absolute top (Dropdowns, Cursors, Tooltips)
}

C.UnitFrame = {
    InheritPlugin = "Orbit_PlayerFrame", -- Canonical plugin for settings inheritance
    InheritIndex = 1, -- Enum.EditModeUnitFrameSystemIndices.Player (resolved at runtime)
    TextPadding = 5, -- SetPoint offset for Name/HealthText labels
    ShadowOffset = { x = 1, y = -1 }, -- Standard shadow for text

    CombatIconSize = 18, -- Player combat indicator icon size
    StatusIconSize = 16, -- Role/Leader/Marker/RareElite icon size
    DefaultOffsetX = -200, -- Default X offset for unit frames
    DefaultOffsetY = -140, -- Default Y offset for unit frames
}

C.BossFrame = {
    PowerBarRatio = 0.2, -- Power bar height as ratio of frame height
    FrameSpacing = 20, -- Base spacing between stacked boss frames
}

C.GroupFrames = {
    OutOfRangeAlpha = 0.3,
    OfflineAlpha = 0.35,
    MaxPrivateAuraAnchors = 3,
    AuraBaseIconSize = 10,
    AuraSpacing = 1,
    DefaultPartyOffsetX = 20,
    DefaultPartyOffsetY = -200,
    DefaultRaidOffsetX = 20,
    DefaultRaidOffsetY = -300,
    RolePriority = { TANK = 1, HEALER = 2, DAMAGER = 3, NONE = 4 },
    GrowthDirection = { Down = "down", Up = "up", Left = "left", Right = "right", Center = "center" },
    ContainerAnchor = { down = "TOPLEFT", up = "BOTTOMLEFT", right = "TOPLEFT", left = "TOPRIGHT", center = "CENTER" },
}

C.Stagger = {
    LowThreshold = 30, -- Below 30% = light stagger
    MediumThreshold = 60, -- 30-60% = medium stagger, above = heavy
}

-- [ SETTINGS RANGES (Default min/max/step for sliders) ]---------------------------------------------
C.Settings = {
    Width = { Min = 50, Max = 400, Step = 1, Default = 200 },
    Height = { Min = 10, Max = 50, Step = 1, Default = 20 },
    Scale = { Min = 50, Max = 150, Step = 1, Default = 100 },
    Opacity = { Min = 0, Max = 100, Step = 1, Default = 100 },
    TextSize = { Min = 8, Max = 32, Step = 1, Default = 12 },
    BorderSize = { Min = 1, Max = 5, Step = 1, Default = 2 },
    Spacing = { Min = -5, Max = 50, Step = 1, Default = 2 },
    Padding = { Min = -5, Max = 15, Step = 1, Default = 0 },
    Font = { Default = "Barlow Condensed Bold", FallbackPath = "Fonts\\FRIZQT__.TTF" },
    Texture = { Default = "Orbit Gradient Top-Bottom" },
}

-- [ BORDER STYLE ] ----------------------------------------------------------------------------------
-- Built-in "orbit" style → nil styleEntry → flat-border path; `lsm:`-keyed styles render via edge-file path.
C.BorderStyle = {
    Default = "orbit",
    Offset = 6,
    EdgeSize = 16,
    DefaultPixelSize = 2,
    PixelSize = { Min = 0, Max = 5, Step = 1 },
    Styles = {
        { label = "Orbit", value = "orbit", pixel = true },
    },
}

-- Build reverse lookup: value → style entry
C.BorderStyle.Lookup = {}
for _, entry in ipairs(C.BorderStyle.Styles) do
    C.BorderStyle.Lookup[entry.value] = entry
end

-- Layout reads BorderSize/IconBorderSize; re-sync after the slider changes so callers don't re-derive.
function C.BorderStyle.SyncEffectiveSize(gs)
    if not gs then return end
    local d = C.BorderStyle.DefaultPixelSize
    gs.BorderSize = gs.PixelBorderSize or d
    gs.IconBorderSize = gs.IconPixelBorderSize or d
end

-- [ TIMING CONSTANTS ]-------------------------------------------------------------------------------
C.Timing = {
    DefaultDebounce = 0.1,
    LayoutThrottle = 0.15,
    SettingsApplyDelay = 0.1,
    IconMonitorInterval = 0.25, -- Icon state monitoring (0.25s = ~60% less CPU than 0.1s)
    LayoutMonitorInterval = 0.25, -- Layout change detection
    FadeDuration = 0.3,
    FlashDuration = 0.5,
    KeyboardRestoreDelay = 0.05, -- Restore keyboard propagation after ESC
    RetryShort = 0.5, -- Short retry delay for initialization
    RetryLong = 2.0, -- Long retry delay for slow loads
    ResourceUpdateInterval = 0.05, -- Resource bar OnUpdate throttle
    HoverCheckInterval = 0.1, -- OOC fade mouseover polling interval
}

-- [ ICON & TEXTURE CONSTANTS ]-----------------------------------------------------------------------
C.IconScale = {
    MaskOversize = 4, -- Ensure mask doesn't clip non-square icons
    FlashScale = 1.2, -- Flash animation slightly larger than icon
    ProcGlowScale = 1.4, -- Proc glow extends beyond icon
    PandemicPadding = 12, -- Pandemic border padding
    BorderPaddingH = 16, -- Native border horizontal padding
    BorderPaddingV = 16, -- Native border vertical padding
}

C.Texture = {
    BlizzardIconBorderTrim = 0.08,
}

C.Atlases = {
    CooldownBorder = "UI-HUD-CoolDownManager-IconOverlay",
    OutofRangeShadow = "UI-CooldownManager-OORshadow",
}

C.Assets = {
    SwipeCustom = "Interface\\Cooldown\\player-cooldown-swipe",
    SwipeDefault = "Interface\\HUD\\UI-HUD-CoolDownManager-Icon-Swipe",
}

-- [ SKINNING CONSTANTS ]-----------------------------------------------------------------------------
C.Skin = {
    DefaultIconSize = 34,
    BorderOffsetGeneric = 7,
    BorderOffsetPandemic = 6,
    OORAlpha = 0.5,
    DebuffBorderAlpha = 0,
}

C.Aura = {
    SkinWithTimer = { zoom = 0, borderStyle = 1, borderSize = 1, showTimer = true },
    SkinNoTimer = { zoom = 0, borderStyle = 1, borderSize = 1, showTimer = false },
}

-- [ COMPONENT DEFAULTS ]-----------------------------------------------------------------------------
-- Note: PlayerCastBar is shared by PlayerCastBar, TargetCastBar, FocusCastBar, and CastBarMixin
C.PlayerCastBar = {
    DefaultWidth = 200,
    DefaultHeight = 15,
    DefaultY = -200,
}

C.Cooldown = {
    DefaultLimit = 10,
    DefaultPadding = 2,
    DefaultIconSize = 34,
    MaxChildFrames = 14,
    SystemIndex = {
        Essential = 1,
        Utility = 2,
        BuffIcon = 3,
        BuffBar = 30,
    },
}

-- Global counter ids; container records are sparse in a flat global table and never reused.
C.Tracked = {
    MaxIconContainers = 10, -- Per-spec cap on icon containers
    MaxBars = 10, -- Per-spec cap on single-spell bars
    SystemIndexBase = 1000, -- Counter starts here to avoid colliding with native cooldown system indices
}

-- Unified Glow configuration parameters (LibOrbitGlow)
C.Glow = {
    -- Glow type enum mapping to LibOrbitGlow standard
    Type = {
        None = 0,
        Pixel = 1,
        Medium = 2,
        Autocast = 3,
        Classic = 4,
        Blizzard = 5,
        Thin = 6,
        Thick = 7,
        Static = 8,
    },

    DefaultType = 2, -- Medium (Proc)
    DefaultColor = { r = 1, g = 0.8, b = 0, a = 1 }, -- Gold/amber

    -- Default fallback parameters per type
    Defaults = {
        Pixel = {
            Lines = 4,
            Frequency = 0.20,
            Length = 15,
            Thickness = 2,
            XOffset = 0,
            YOffset = 0,
            Border = false,
        },
        Medium = {
            Speed = 1.0,
            -- Uses default icon scaling in LibOrbitGlow based on native properties
        },
        Autocast = {
            Particles = 4,
            Frequency = 0.125,
        },
        Classic = {
            Frequency = 0.125,
            FrameLevel = 5,
        },
        Thin = {
            Speed = 1.0,
        },
        Thick = {
            Speed = 1.0,
        },
        Static = {
            -- Static does not animate, so it has no Speed property
        },
    },
}

-- [ UI FONTS (Template Names) ]----------------------------------------------------------------------
C.UI = {
    LabelFont = "GameFontHighlight", -- White font for widget labels
    ValueFont = "GameFontHighlightSmall", -- Yellow font for value displays
    UnitFrameTextSize = 12, -- Standard text size for UnitFrames (Name, Health)
}

-- [ COLORS ]-----------------------------------------------------------------------------------------
C.PowerTypeIds = {
    Mana = 0,
    Rage = 1,
    Focus = 2,
    Energy = 3,
    ComboPoints = 4,
    Runes = 5,
    RunicPower = 6,
    SoulShards = 7,
    LunarPower = 8,
    HolyPower = 9,
    Maelstrom = 11,
    Chi = 12,
    Insanity = 13,
    Obsolete = 14,
    Obsolete2 = 15,
    ArcaneCharges = 16,
    Fury = 17,
    Pain = 18,
    Essence = 19,
}

C.Colors = {
    Background = { r = 0.08, g = 0.08, b = 0.08, a = 0.5 },
    Absorb = { r = 0.4, g = 0.75, b = 1.0, a = 0.85 },

    -- Power Type colors, keyed by Enum.PowerType.
    PowerType = {
        [0] = { r = 0, g = 0, b = 1 }, -- Mana
        [1] = { r = 1, g = 0, b = 0 }, -- Rage
        [2] = { r = 1, g = 0.5, b = 0.25 }, -- Focus
        [3] = { r = 1, g = 1, b = 0 }, -- Energy
        [4] = { r = 0, g = 1, b = 1 }, -- Combo Points
        [5] = { r = 0.5, g = 0.5, b = 0.5 }, -- Runes
        [6] = { r = 0, g = 0.82, b = 1 }, -- Runic Power
        [7] = { r = 0.5, g = 0.32, b = 0.55 }, -- Soul Shards
        [8] = { r = 0.95, g = 0.9, b = 0.6 }, -- Lunar Power
        [9] = { r = 0.3, g = 0.52, b = 0.9 }, -- Holy Power
        [11] = { r = 0.65, g = 0.63, b = 0.35 }, -- Maelstrom
        [12] = { r = 0.6, g = 0.09, b = 0.16 }, -- Chi
        [13] = { r = 1, g = 0.61, b = 0 }, -- Insanity
        [16] = { r = 0.3, g = 0.52, b = 0.9 }, -- Arcane Charges
        [17] = { r = 1, g = 0.6, b = 0.2 }, -- Fury
        [18] = { r = 0.27, g = 0.75, b = 0.65 }, -- Pain
        [19] = { r = 0.19, g = 0.58, b = 0.77 }, -- Essence
    },

    PlayerResources = {
        ROGUE = { r = 1.0, g = 0.96, b = 0.41 },
        DRUID = { r = 1.0, g = 0.96, b = 0.41 },
        PALADIN = { r = 0.95, g = 0.9, b = 0.6 },
        MONK = { r = 0.71, g = 1.0, b = 0.92 },
        WARLOCK = { r = 0.5, g = 0.35, b = 0.9 },
        MAGE = { r = 0.4, g = 0.6, b = 1.0 },
        DEATHKNIGHT = { r = 0.8, g = 0.1, b = 0.2 },
        EVOKER = { r = 0.6, g = 0.8, b = 1.0 },
        ChargedComboPoint = { r = 0.169, g = 0.733, b = 0.992 },
        RuneBlood = { r = 1.0, g = 0.2, b = 0.3 },
        RuneFrost = { r = 0.0, g = 0.6, b = 1.0 },
        RuneUnholy = { r = 0.1, g = 1.0, b = 0.1 },
        StaggerLow = { r = 0.52, g = 1.0, b = 0.52 },
        StaggerMedium = { r = 1.0, g = 0.98, b = 0.72 },
        StaggerHeavy = { r = 1.0, g = 0.42, b = 0.42 },
        SoulFragments = { r = 0.278, g = 0.125, b = 0.796 },
        SoulFragmentsVoidMeta = { r = 0.037, g = 0.220, b = 0.566 },
        EbonMight = { r = 0.2, g = 0.8, b = 0.4 },
        MaelstromWeapon = { r = 0.0, g = 0.5, b = 1.0 },
    },

    EmpowerStage = {
        [1] = { r = 0.7, g = 0.7, b = 0.3 },
        [2] = { r = 0.8, g = 0.5, b = 0.2 },
        [3] = { r = 0.9, g = 0.3, b = 0.1 },
        [4] = { r = 1.0, g = 0.2, b = 0.2 },
    },

    DebuffTypeColor = {
        ["none"] = { r = 0.80, g = 0, b = 0 },
        ["Magic"] = { r = 0.20, g = 0.60, b = 1.00 },
        ["Curse"] = { r = 0.60, g = 0.00, b = 1.00 },
        ["Disease"] = { r = 0.60, g = 0.40, b = 0 },
        ["Poison"] = { r = 0.00, g = 0.60, b = 0 },
        [""] = { r = 0.80, g = 0, b = 0 },
    },
}

-- Helper function for class resource colors
function C.Colors:GetResourceColor(classFileName)
    return self.PlayerResources[classFileName]
end

-- Helper function for power type colors (Mana, Rage, Energy, etc.)
function C.Colors:GetPowerColor(powerType)
    return self.PowerType[powerType] or { r = 0.5, g = 0.5, b = 0.5 }
end

-- [ BACKWARDS COMPATIBILITY ALIAS ] -----------------------------------------------------------------
-- Orbit.Colors points to C.Colors for existing code
Orbit.Colors = C.Colors
