SFrames.Config = {
    -- Default Settings
    width = 220,
    height = 50,
    portraitWidth = 50,
    castbarHeight = 18,
    
    colors = {
        backdrop = { r = 0.15, g = 0.10, b = 0.15, a = 0.8 }, -- Pinkish dark tint
        border = { r = 1.0, g = 0.5, b = 0.8, a = 1 }, -- Cute pink border
        power = {
            [0] = { r = 0.0, g = 0.0, b = 1.0 }, -- Mana
            [1] = { r = 1.0, g = 0.0, b = 0.0 }, -- Rage
            [2] = { r = 1.0, g = 0.5, b = 0.0 }, -- Focus
            [3] = { r = 1.0, g = 1.0, b = 0.0 }, -- Energy
            [4] = { r = 0.0, g = 1.0, b = 1.0 }, -- Happiness
        },
        class = {
            ["WARRIOR"] = { r = 0.78, g = 0.61, b = 0.43 },
            ["MAGE"]    = { r = 0.41, g = 0.8,  b = 0.94 },
            ["ROGUE"]   = { r = 1.0,  g = 0.96, b = 0.41 },
            ["DRUID"]   = { r = 1.0,  g = 0.49, b = 0.04 },
            ["HUNTER"]  = { r = 0.67, g = 0.83, b = 0.45 },
            ["SHAMAN"]  = { r = 0.14, g = 0.35, b = 1.0 },
            ["PRIEST"]  = { r = 1.0,  g = 1.0,  b = 1.0 },
            ["WARLOCK"] = { r = 0.58, g = 0.51, b = 0.79 },
            ["PALADIN"] = { r = 0.96, g = 0.55, b = 0.73 },
        }
    }
}

--------------------------------------------------------------------------------
-- Theme Engine
--------------------------------------------------------------------------------

SFrames.Theme = {}
SFrames.ActiveTheme = {}

local function HSVtoRGB(h, s, v)
    if s <= 0 then return v, v, v end
    h = h - math.floor(h / 360) * 360
    local hh = h / 60
    local i = math.floor(hh)
    local f = hh - i
    local p = v * (1 - s)
    local q = v * (1 - s * f)
    local t = v * (1 - s * (1 - f))
    if i == 0 then return v, t, p
    elseif i == 1 then return q, v, p
    elseif i == 2 then return p, v, t
    elseif i == 3 then return p, q, v
    elseif i == 4 then return t, p, v
    else return v, p, q end
end

local function toHexChar(n)
    if n < 10 then return string.char(48 + n) end
    return string.char(97 + n - 10)
end

local function RGBtoHex(r, g, b)
    local rr = math.floor(r * 255 + 0.5)
    local gg = math.floor(g * 255 + 0.5)
    local bb = math.floor(b * 255 + 0.5)
    return "ff"
        .. toHexChar(math.floor(rr / 16)) .. toHexChar(rr - math.floor(rr / 16) * 16)
        .. toHexChar(math.floor(gg / 16)) .. toHexChar(gg - math.floor(gg / 16) * 16)
        .. toHexChar(math.floor(bb / 16)) .. toHexChar(bb - math.floor(bb / 16) * 16)
end

SFrames.Theme.Presets = {}
SFrames.Theme.Presets["pink"]    = { name = "樱粉",  hue = 330, satMul = 1.00 }
SFrames.Theme.Presets["frost"]   = { name = "霜蓝",  hue = 210, satMul = 1.00 }
SFrames.Theme.Presets["emerald"] = { name = "翠绿",  hue = 140, satMul = 0.85 }
SFrames.Theme.Presets["flame"]   = { name = "炎橙",  hue = 25,  satMul = 0.90 }
SFrames.Theme.Presets["shadow"]  = { name = "暗紫",  hue = 270, satMul = 0.90 }
SFrames.Theme.Presets["golden"]  = { name = "金辉",  hue = 45,  satMul = 0.80 }
SFrames.Theme.Presets["teal"]    = { name = "碧青",  hue = 175, satMul = 0.85 }
SFrames.Theme.Presets["crimson"] = { name = "绯红",  hue = 5,   satMul = 1.00 }
SFrames.Theme.Presets["holy"]    = { name = "圣光",  hue = 220, satMul = 0.15 }

SFrames.Theme.PresetOrder = { "pink", "frost", "emerald", "flame", "shadow", "golden", "teal", "crimson", "holy" }

SFrames.Theme.Presets["c_warrior"] = { name = "战士",   hue = 31,  satMul = 0.90, swatchRGB = {0.78, 0.61, 0.43} }
SFrames.Theme.Presets["c_paladin"] = { name = "圣骑士", hue = 334, satMul = 0.50, swatchRGB = {0.96, 0.55, 0.73} }
SFrames.Theme.Presets["c_hunter"]  = { name = "猎人",   hue = 85,  satMul = 0.55, swatchRGB = {0.67, 0.83, 0.45} }
SFrames.Theme.Presets["c_rogue"]   = { name = "潜行者", hue = 56,  satMul = 0.70, swatchRGB = {1.00, 0.96, 0.41} }
SFrames.Theme.Presets["c_priest"]  = { name = "牧师",   hue = 40,  satMul = 0.06, swatchRGB = {1.00, 1.00, 1.00} }
SFrames.Theme.Presets["c_shaman"]  = { name = "萨满",   hue = 225, satMul = 0.95, swatchRGB = {0.14, 0.35, 1.00} }
SFrames.Theme.Presets["c_mage"]    = { name = "法师",   hue = 196, satMul = 0.65, swatchRGB = {0.41, 0.80, 0.94} }
SFrames.Theme.Presets["c_warlock"] = { name = "术士",   hue = 255, satMul = 0.45, swatchRGB = {0.58, 0.51, 0.79} }
SFrames.Theme.Presets["c_druid"]   = { name = "德鲁伊", hue = 28,  satMul = 1.00, swatchRGB = {1.00, 0.49, 0.04} }

SFrames.Theme.ClassPresetOrder = { "c_warrior", "c_paladin", "c_hunter", "c_rogue", "c_priest", "c_shaman", "c_mage", "c_warlock", "c_druid" }

SFrames.Theme.ClassMap = {}
SFrames.Theme.ClassMap["WARRIOR"] = "c_warrior"
SFrames.Theme.ClassMap["PALADIN"] = "c_paladin"
SFrames.Theme.ClassMap["HUNTER"]  = "c_hunter"
SFrames.Theme.ClassMap["ROGUE"]   = "c_rogue"
SFrames.Theme.ClassMap["PRIEST"]  = "c_priest"
SFrames.Theme.ClassMap["SHAMAN"]  = "c_shaman"
SFrames.Theme.ClassMap["MAGE"]    = "c_mage"
SFrames.Theme.ClassMap["WARLOCK"] = "c_warlock"
SFrames.Theme.ClassMap["DRUID"]   = "c_druid"

local function GenerateTheme(H, satMul)
    satMul = satMul or 1.0
    local function S(s)
        local v = s * satMul
        if v > 1 then v = 1 end
        return v
    end
    local function C3(s, v)
        local r, g, b = HSVtoRGB(H, S(s), v)
        return { r, g, b }
    end
    local function C4(s, v, a)
        local r, g, b = HSVtoRGB(H, S(s), v)
        return { r, g, b, a }
    end
    local t = {}
    t.accent      = C4(0.40, 0.80, 0.98)
    t.accentDark  = C3(0.45, 0.55)
    t.accentLight = C3(0.30, 1.00)
    t.accentHex   = RGBtoHex(t.accentLight[1], t.accentLight[2], t.accentLight[3])
    t.panelBg       = C4(0.50, 0.12, 0.95)
    t.panelBorder   = C4(0.45, 0.55, 0.90)
    t.headerBg      = C4(0.60, 0.10, 0.98)
    t.sectionBg     = C4(0.43, 0.14, 0.82)
    t.sectionBorder = C4(0.38, 0.45, 0.86)
    t.bg            = t.panelBg
    t.border        = t.panelBorder
    t.slotBg       = C4(0.20, 0.07, 0.90)
    t.slotBorder   = C4(0.10, 0.28, 0.80)
    t.slotHover    = C4(0.38, 0.40, 0.90)
    t.slotSelected = C4(0.43, 0.70, 1.00)
    t.buttonBg          = C4(0.44, 0.18, 0.94)
    t.buttonBorder      = C4(0.40, 0.50, 0.90)
    t.buttonHoverBg     = C4(0.47, 0.30, 0.96)
    t.buttonDownBg      = C4(0.50, 0.14, 0.96)
    t.buttonDisabledBg  = C4(0.43, 0.14, 0.65)
    t.buttonActiveBg    = C4(0.52, 0.42, 0.98)
    t.buttonActiveBorder = C4(0.42, 0.90, 1.00)
    t.buttonText        = C3(0.16, 0.90)
    t.buttonActiveText  = C3(0.08, 1.00)
    t.buttonDisabledText = C4(0.14, 0.55, 0.68)
    t.btnBg           = t.buttonBg
    t.btnBorder       = t.buttonBorder
    t.btnHoverBg      = t.buttonHoverBg
    t.btnHoverBd      = C4(0.40, 0.80, 0.98)
    t.btnDownBg       = t.buttonDownBg
    t.btnText         = t.buttonText
    t.btnActiveText   = t.buttonActiveText
    t.btnDisabledText = C3(0.14, 0.40)
    t.btnHover        = C4(0.47, 0.30, 0.95)
    t.btnHoverBorder  = t.btnHoverBd
    t.tabBg           = t.buttonBg
    t.tabBorder       = t.buttonBorder
    t.tabActiveBg     = C4(0.50, 0.32, 0.96)
    t.tabActiveBorder = C4(0.40, 0.80, 0.98)
    t.tabText         = C3(0.21, 0.70)
    t.tabActiveText   = t.buttonActiveText
    t.checkBg          = t.buttonBg
    t.checkBorder      = t.buttonBorder
    t.checkHoverBorder = C4(0.40, 0.80, 0.95)
    t.checkFill        = C4(0.43, 0.88, 0.98)
    t.checkOn          = C3(0.40, 0.80)
    t.checkOff         = C4(0.40, 0.25, 0.60)
    t.sliderTrack      = C4(0.45, 0.22, 0.90)
    t.sliderFill       = C4(0.35, 0.85, 0.92)
    t.sliderThumb      = C4(0.25, 1.00, 0.95)
    t.text          = C3(0.11, 0.92)
    t.title         = C3(0.30, 1.00)
    t.gold          = t.title
    t.nameText      = C3(0.06, 0.92)
    t.dimText       = C3(0.25, 0.60)
    t.bodyText      = C3(0.05, 0.82)
    t.sectionTitle  = C3(0.24, 0.90)
    t.catHeader     = C3(0.31, 0.80)
    t.colHeader     = C3(0.25, 0.80)
    t.labelText     = C3(0.23, 0.65)
    t.valueText     = t.text
    t.subText       = t.labelText
    t.pageText      = C3(0.19, 0.80)
    t.objectiveText = C3(0.10, 0.90)
    t.optionText    = t.tabText
    t.countText     = t.tabText
    t.trackText     = C3(0.25, 0.80)
    t.divider  = C4(0.45, 0.55, 0.40)
    t.sepColor = C4(0.44, 0.45, 0.50)
    t.scrollThumb = C4(0.45, 0.55, 0.70)
    t.scrollTrack = C4(0.50, 0.08, 0.50)
    t.inputBg     = C4(0.50, 0.08, 0.95)
    t.inputBorder = C4(0.38, 0.40, 0.80)
    t.searchBg     = C4(0.50, 0.08, 0.80)
    t.searchBorder = C4(0.38, 0.40, 0.60)
    t.progressBg   = C4(0.50, 0.08, 0.90)
    t.progressFill = C4(0.50, 0.70, 1.00)
    t.modelBg     = C4(0.60, 0.08, 0.85)
    t.modelBorder = C4(0.43, 0.35, 0.70)
    t.emptySlot   = C4(0.40, 0.25, 0.40)
    t.emptySlotBg = C4(0.50, 0.08, 0.40)
    t.emptySlotBd = C4(0.40, 0.25, 0.30)
    t.barBg = C4(0.60, 0.10, 1.00)
    t.rowNormal   = C4(0.50, 0.06, 0.30)
    t.rowNormalBd = C4(0.22, 0.20, 0.30)
    t.raidGroup       = t.sectionBg
    t.raidGroupBorder = C4(0.38, 0.40, 0.70)
    t.raidSlotEmpty   = C4(0.50, 0.08, 0.60)
    t.questSelected  = C4(0.70, 0.60, 0.85)
    t.questSelBorder = C4(0.47, 0.95, 1.00)
    t.questSelBar    = C4(0.45, 1.00, 1.00)
    t.questHover     = C4(0.52, 0.25, 0.50)
    t.zoneHeader     = t.catHeader
    t.zoneBg         = C4(0.50, 0.14, 0.50)
    t.collapseIcon   = C3(0.31, 0.70)
    t.trackBar       = C4(0.53, 0.95, 1.00)
    t.trackGlow      = C4(0.53, 0.95, 0.22)
    t.rewardBg       = C4(0.50, 0.10, 0.85)
    t.rewardBorder   = C4(0.45, 0.40, 0.70)
    t.listBg       = C4(0.50, 0.08, 0.80)
    t.listBorder   = C4(0.43, 0.35, 0.60)
    t.detailBg     = C4(0.50, 0.09, 0.92)
    t.detailBorder = t.listBorder
    t.selectedRowBg     = C4(0.65, 0.35, 0.60)
    t.selectedRowBorder = C4(0.50, 0.90, 0.70)
    t.selectedNameText  = { 1, 0.95, 1 }
    t.overlayBg     = C4(0.75, 0.04, 0.55)
    t.accentLine    = C4(0.50, 1.00, 0.90)
    t.titleColor    = t.title
    t.nameColor     = { 1, 1, 1 }
    t.valueColor    = t.text
    t.labelColor    = C3(0.28, 0.58)
    t.dimColor      = C3(0.29, 0.48)
    t.clockColor    = C3(0.18, 1.00)
    t.timerColor    = C3(0.27, 0.75)
    t.brandColor    = C4(0.37, 0.60, 0.70)
    t.particleColor = C3(0.40, 1.00)
    t.wbGold        = { 1, 0.88, 0.55 }
    t.wbBorder      = { 0.95, 0.75, 0.25 }
    t.passive = { 0.60, 0.60, 0.65 }
    return t
end

function SFrames.Theme:Extend(extras)
    local override = extras or {}
    local proxy = {}
    setmetatable(proxy, {
        __index = function(self, k)
            local v = override[k]
            if v ~= nil then return v end
            return SFrames.ActiveTheme[k]
        end
    })
    return proxy
end

function SFrames.Theme:Apply(presetKey)
    local key = presetKey or "pink"
    local preset = self.Presets[key]
    if not preset then key = "pink"; preset = self.Presets["pink"] end
    local newTheme = GenerateTheme(preset.hue, preset.satMul)
    local oldKeys = {}
    for k, v in pairs(SFrames.ActiveTheme) do
        table.insert(oldKeys, k)
    end
    for i = 1, table.getn(oldKeys) do
        SFrames.ActiveTheme[oldKeys[i]] = nil
    end
    for k, v in pairs(newTheme) do
        SFrames.ActiveTheme[k] = v
    end
    if SFrames.Config and SFrames.Config.colors then
        local a = SFrames.ActiveTheme
        SFrames.Config.colors.border  = { r = a.accent[1], g = a.accent[2], b = a.accent[3], a = 1 }
        SFrames.Config.colors.backdrop = { r = a.panelBg[1], g = a.panelBg[2], b = a.panelBg[3], a = a.panelBg[4] or 0.8 }
    end
    if SFrames.MinimapButton and SFrames.MinimapButton.Refresh then
        SFrames.MinimapButton:Refresh()
    end
end

function SFrames.Theme:GetCurrentPreset()
    local dbExists = SFramesDB and true or false
    local themeExists = SFramesDB and type(SFramesDB.Theme) == "table" and true or false
    local savedPreset = themeExists and SFramesDB.Theme.preset or "nil"
    if SFramesDB and type(SFramesDB.Theme) == "table" then
        if SFramesDB.Theme.useClassTheme then
            local _, class = UnitClass("player")
            if class and self.ClassMap[class] then
                return self.ClassMap[class]
            end
        end
        if SFramesDB.Theme.preset and self.Presets[SFramesDB.Theme.preset] then
            return SFramesDB.Theme.preset
        end
    end
    return "pink"
end

function SFrames.Theme:GetAccentHex()
    return SFrames.ActiveTheme.accentHex or "ffffb3d9"
end

SFrames.Theme.HSVtoRGB = HSVtoRGB
SFrames.Theme.RGBtoHex = RGBtoHex

SFrames.Theme:Apply(SFrames.Theme:GetCurrentPreset())

local themeInitFrame = CreateFrame("Frame")
themeInitFrame:RegisterEvent("VARIABLES_LOADED")
themeInitFrame:RegisterEvent("PLAYER_LOGIN")
themeInitFrame:SetScript("OnEvent", function()
    SFrames.Theme:Apply(SFrames.Theme:GetCurrentPreset())
end)
