local ADDON_NAME, ns = ...

-- unify ns across files
ns = _G[ADDON_NAME] or ns
_G[ADDON_NAME] = ns

ns.config = ns.config or {}
local Cfg = ns.config

-- =============================================================
-- pom_config.lua
-- Main menu: general + skins + launchers for sub-UIs
-- NOTE:
-- - Heights UI lives in pom_heights.lua
-- - Base Colors UI lives in pom_base_colors_ui.lua (ns.BaseColorsUI)
-- - Threat UI lives in pom_threat_ui.lua (ns.ThreatUI)
-- This file should NOT own any threat settings logic.
-- =============================================================

local AVAILABLE_FONTS = {
    { name = "Default (Friz Quadrata)", path = _G.STANDARD_TEXT_FONT or "Fonts\\FRIZQT__.TTF" },
    { name = "Friz Quadrata",           path = "Fonts\\FRIZQT__.TTF" },
    { name = "Arial Narrow",            path = "Fonts\\ARIALN.TTF" },
    { name = "Skurri",                  path = "Fonts\\skurri.ttf" },
    { name = "Morpheus",                path = "Fonts\\MORPHEUS.ttf" },
    { name = "2002",                    path = "Fonts\\2002.ttf" },
}

-- =========================================================
-- Popup: Skins
-- =========================================================
local function ShowSkinList(anchor, skins, currentID, onPick)
    if Cfg._skinList and Cfg._skinList:IsShown() then
        Cfg._skinList:Hide()
    end

    if not Cfg._skinList then
        local f = CreateFrame("Frame", nil, UIParent, "BackdropTemplate")
        f:SetFrameStrata("DIALOG")
        f:SetBackdrop({ bgFile="Interface\\Buttons\\WHITE8x8", edgeFile="Interface\\Buttons\\WHITE8x8", edgeSize=1 })
        f:SetBackdropColor(0,0,0,0.95)
        f:SetBackdropBorderColor(0,0,0,1)
        f.buttons = {}
        Cfg._skinList = f
    end

    local f = Cfg._skinList
    f:ClearAllPoints()
    f:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, -2)

    for i = 1, #f.buttons do
        f.buttons[i]:Hide()
    end

    local btnH = 18
    local w = 260
    local maxShown = 30

    local count = math.min(#skins, maxShown)
    f:SetSize(w, count * btnH + 8)

    for i = 1, count do
        local skin = skins[i]
        local b = f.buttons[i]
        if not b then
            b = CreateFrame("Button", nil, f)
            b:SetSize(w - 8, btnH)
            b:SetPoint("TOPLEFT", f, "TOPLEFT", 4, -4 - (i-1) * btnH)

            local t = b:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
            t:SetPoint("LEFT", b, "LEFT", 4, 0)
            t:SetJustifyH("LEFT")
            b.text = t

            b:SetScript("OnEnter", function(self) self.text:SetTextColor(1, 0.82, 0) end)
            b:SetScript("OnLeave", function(self) self.text:SetTextColor(1, 1, 1) end)

            f.buttons[i] = b
        end

        b.text:SetText(((i == currentID) and "|cff00ff00•|r " or "  ") .. (skin.name or ("Skin " .. i)))
        b:SetScript("OnClick", function()
            f:Hide()
            if onPick then onPick(i) end
        end)

        b:Show()
    end

    f:Show()
end

-- =========================================================
-- Popup: Fonts
-- =========================================================
local function ShowFontList(anchor, fonts, currentPath, onPick)
    if Cfg._fontList and Cfg._fontList:IsShown() then
        Cfg._fontList:Hide()
    end

    if not Cfg._fontList then
        local f = CreateFrame("Frame", nil, UIParent, "BackdropTemplate")
        f:SetFrameStrata("DIALOG")
        f:SetBackdrop({ bgFile="Interface\\Buttons\\WHITE8x8", edgeFile="Interface\\Buttons\\WHITE8x8", edgeSize=1 })
        f:SetBackdropColor(0,0,0,0.95)
        f:SetBackdropBorderColor(0,0,0,1)
        f.buttons = {}
        Cfg._fontList = f
    end

    local f = Cfg._fontList
    f:ClearAllPoints()
    f:SetPoint("TOPLEFT", anchor, "BOTTOMLEFT", 0, -2)

    for i = 1, #f.buttons do
        f.buttons[i]:Hide()
    end

    local btnH = 18
    local w = 260
    local maxShown = 18

    local count = math.min(#fonts, maxShown)
    f:SetSize(w, count * btnH + 8)

    for i = 1, count do
        local font = fonts[i]
        local b = f.buttons[i]
        if not b then
            b = CreateFrame("Button", nil, f)
            b:SetSize(w - 8, btnH)
            b:SetPoint("TOPLEFT", f, "TOPLEFT", 4, -4 - (i-1) * btnH)

            local t = b:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
            t:SetPoint("LEFT", b, "LEFT", 4, 0)
            t:SetJustifyH("LEFT")
            b.text = t

            b:SetScript("OnEnter", function(self) self.text:SetTextColor(1, 0.82, 0) end)
            b:SetScript("OnLeave", function(self) self.text:SetTextColor(1, 1, 1) end)

            f.buttons[i] = b
        end

        local isCurrent = (font.path == currentPath)
        b.text:SetText((isCurrent and "|cff00ff00•|r " or "  ") .. (font.name or ("Font " .. i)))
        b:SetScript("OnClick", function()
            f:Hide()
            if onPick then onPick(font) end
        end)

        b:Show()
    end

    f:Show()
end

local function ApplyAll(applyAll)
    if applyAll then applyAll() end
end

local function GetCheckLabel(cb)
    if not cb then return nil end
    if cb.Text and cb.Text.SetText then return cb.Text end
    if cb.text and cb.text.SetText then return cb.text end
    local n = cb.GetName and cb:GetName()
    if n and _G[n .. "Text"] and _G[n .. "Text"].SetText then
        return _G[n .. "Text"]
    end
    return nil
end

local function MakeSectionTitle(parent, text, x, y)
    local t = parent:CreateFontString(nil, "OVERLAY", "GameFontNormalLarge")
    t:SetPoint("TOPLEFT", parent, "TOPLEFT", x, y)
    t:SetText(text)
    return t
end

local function MakeCheck(parent, label, key, x, y, applyAll)
    local cb = CreateFrame("CheckButton", nil, parent, "ChatConfigCheckButtonTemplate")
    cb:SetPoint("TOPLEFT", parent, "TOPLEFT", x, y)

    local lbl = GetCheckLabel(cb)
    if lbl then lbl:SetText(label) end

    local function refresh()
        local db = PlateOMaticDB
        cb:SetChecked((db and db[key]) and true or false)
    end
    refresh()

    cb:SetScript("OnClick", function(self)
        PlateOMaticDB[key] = self:GetChecked() and true or false
        ApplyAll(applyAll)
    end)

    return cb
end

local function MakeColorSwatch(parent, x, y, getColor, setColor, applyAll)
    local b = CreateFrame("Button", nil, parent)
    b:SetSize(18, 18)
    b:SetPoint("TOPLEFT", parent, "TOPLEFT", x, y)

    local bg = b:CreateTexture(nil, "BACKGROUND")
    bg:SetAllPoints()
    bg:SetColorTexture(0.15, 0.15, 0.15, 1)

    local sw = b:CreateTexture(nil, "OVERLAY")
    sw:SetPoint("TOPLEFT", 1, -1)
    sw:SetPoint("BOTTOMRIGHT", -1, 1)

    local function SafeColor()
        local c = nil
        if getColor then c = getColor() end
        if type(c) ~= "table" then c = { r=1, g=1, b=1, a=1 } end
        c.r = tonumber(c.r) or 1
        c.g = tonumber(c.g) or 1
        c.b = tonumber(c.b) or 1
        c.a = tonumber(c.a) or 1
        return c
    end

    local function refresh()
        local c = SafeColor()
        sw:SetColorTexture(c.r, c.g, c.b, c.a)
    end
    refresh()

    b:SetScript("OnClick", function()
        local c = SafeColor()

        ColorPickerFrame:SetupColorPickerAndShow({
            r = c.r, g = c.g, b = c.b,
            opacity = 1 - c.a,
            hasOpacity = true,

            swatchFunc = function()
                local r, g, b = ColorPickerFrame:GetColorRGB()
                local a = 1 - (ColorPickerFrame:GetColorAlpha() or 0)
                if setColor then setColor(r, g, b, a) end
                refresh()
                ApplyAll(applyAll)
            end,

            opacityFunc = function()
                local r, g, b = ColorPickerFrame:GetColorRGB()
                local a = 1 - (ColorPickerFrame:GetColorAlpha() or 0)
                if setColor then setColor(r, g, b, a) end
                refresh()
                ApplyAll(applyAll)
            end,

            cancelFunc = function(prev)
                if prev and setColor then
                    local a = 1 - (prev.opacity or 0)
                    setColor(prev.r, prev.g, prev.b, a)
                end
                refresh()
                ApplyAll(applyAll)
            end,
        })
    end)

    return b
end

local function MakeSkinRow(parent, skins, label, typeKey, x, y, applyAll)
    local row = CreateFrame("Frame", nil, parent)
    row:SetSize(420, 20)
    row:SetPoint("TOPLEFT", parent, "TOPLEFT", x, y)

    local txt = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    txt:SetPoint("LEFT", row, "LEFT", 0, 0)
    txt:SetText(label)

    local btn = CreateFrame("Button", nil, row, "UIPanelButtonTemplate")
    btn:SetSize(220, 20)
    btn:SetPoint("RIGHT", row, "RIGHT", 0, 0)

    local function refresh()
        local db = PlateOMaticDB
        local id = (db and db.skins and db.skins[typeKey]) or 1
        local s = skins[id]
        btn:SetText(s and s.name or ("Skin " .. id))
    end
    refresh()

    btn:SetScript("OnClick", function()
        PlateOMaticDB.skins = PlateOMaticDB.skins or {}
        local currentID = PlateOMaticDB.skins[typeKey] or 1
        ShowSkinList(btn, skins, currentID, function(id)
            PlateOMaticDB.skins[typeKey] = id
            refresh()
            ApplyAll(applyAll)
        end)
    end)

    return row
end

local function MakeSlider(parent, label, key, x, y, minV, maxV, step, applyAll, width)
    width = tonumber(width) or 340

    local row = CreateFrame("Frame", nil, parent)
    row:SetSize(width, 42)
    row:SetPoint("TOPLEFT", parent, "TOPLEFT", x, y)

    local txt = row:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    txt:SetPoint("TOPLEFT", row, "TOPLEFT", 0, 0)
    txt:SetText(label)

    local s = CreateFrame("Slider", nil, row, "OptionsSliderTemplate")
    s:SetPoint("TOPLEFT", row, "TOPLEFT", 0, -16)
    s:SetPoint("TOPRIGHT", row, "TOPRIGHT", 0, -16)
    s:SetMinMaxValues(minV, maxV)
    s:SetValueStep(step)
    s:SetObeyStepOnDrag(true)

    local low  = s.Low
    local high = s.High
    local text = s.Text

    if not low then
        low = s:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        low:SetPoint("TOPLEFT", s, "BOTTOMLEFT", 0, -2)
        s.Low = low
    end
    if not high then
        high = s:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        high:SetPoint("TOPRIGHT", s, "BOTTOMRIGHT", 0, -2)
        s.High = high
    end
    if not text then
        text = s:CreateFontString(nil, "OVERLAY", "GameFontHighlightSmall")
        text:SetPoint("TOP", s, "BOTTOM", 0, -2)
        s.Text = text
    end

    local function refresh()
        local db = PlateOMaticDB
        local v = (db and db[key])
        if v == nil then v = minV end
        s:SetValue(v)
        low:SetText(tostring(minV))
        high:SetText(tostring(maxV))
        text:SetText(string.format("%.2f", v))
    end
    refresh()

    s:SetScript("OnValueChanged", function(self, value)
        PlateOMaticDB[key] = value
        self.Text:SetText(string.format("%.2f", value))
        ApplyAll(applyAll)
    end)

    return row
end

local function MakeFontButton(parent, fonts, x, y, applyAll)
    local btn = CreateFrame("Button", nil, parent, "UIPanelButtonTemplate")
    btn:SetSize(220, 20)
    btn:SetPoint("TOPLEFT", parent, "TOPLEFT", x, y)

    local function FontNameFromPath(p)
        for _, fnt in ipairs(fonts) do
            if fnt.path == p then return fnt.name end
        end
        return "Custom"
    end

    local function refresh()
        local db = PlateOMaticDB or {}
        btn:SetText("Font: " .. FontNameFromPath(db.fontPath))
    end
    refresh()

    btn:SetScript("OnClick", function()
        local db = PlateOMaticDB or {}
        ShowFontList(btn, fonts, db.fontPath, function(pick)
            PlateOMaticDB.fontPath = pick.path
            refresh()
            ApplyAll(applyAll)
        end)
    end)

    return btn
end

local function RunSlash(cmd)
    if ChatEdit_ExecuteCommand then
        ChatEdit_ExecuteCommand(cmd)
        return
    end
    local eb = ChatFrame1EditBox or _G.ChatFrame1EditBox
    if eb and eb.SetText and ChatEdit_SendText then
        eb:SetText(cmd)
        ChatEdit_SendText(eb, 0)
    end
end

-- =========================================================
-- Build()
-- =========================================================
function Cfg:Build(frame, skins, applyAll)
    local Lx  = 16
    local Rx  = 460
    local top = -40

    local y = top

    -- LEFT COLUMN
    MakeSectionTitle(frame, "Skins", Lx, y); y = y - 28
    MakeSkinRow(frame, skins, "Normal", "normal", Lx, y, applyAll); y = y - 24
    MakeSkinRow(frame, skins, "Highlevel (+2)", "highlevel", Lx, y, applyAll); y = y - 24
    MakeSkinRow(frame, skins, "Player +1", "plusOne", Lx, y, applyAll); y = y - 24
    MakeSkinRow(frame, skins, "Elite Caster", "caster", Lx, y, applyAll); y = y - 24
    MakeSkinRow(frame, skins, "Elite Melee", "melee", Lx, y, applyAll); y = y - 32

    MakeSectionTitle(frame, "Heights", Lx, y); y = y - 28
    local hBtn = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
    hBtn:SetSize(220, 20)
    hBtn:SetPoint("TOPLEFT", frame, "TOPLEFT", Lx, y)
    hBtn:SetText("Open Heights Settings")
    hBtn:SetScript("OnClick", function()
        if ns and ns.heights and ns.heights.ToggleFrame then
            ns.heights:ToggleFrame(applyAll)
        end
    end)
    y = y - 32

    MakeSectionTitle(frame, "Base Colors", Lx, y); y = y - 28
    local bcBtn = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
    bcBtn:SetSize(220, 20)
    bcBtn:SetPoint("TOPLEFT", frame, "TOPLEFT", Lx, y)
    bcBtn:SetText("Open Base Color Settings")
    bcBtn:SetScript("OnClick", function()
        if ns and ns.BaseColorsUI and ns.BaseColorsUI.ToggleFrame then
            ns.BaseColorsUI:ToggleFrame(applyAll)
        elseif ns and ns.basecolors_ui and ns.basecolors_ui.Toggle then
            ns.basecolors_ui:Toggle(applyAll)
        else
            print("|cFF00FF00Plate-o-Matic:|r Base Colors UI not loaded.")
        end
    end)
    y = y - 32

    MakeSectionTitle(frame, "Threat", Lx, y); y = y - 28
    local thBtn = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
    thBtn:SetSize(220, 20)
    thBtn:SetPoint("TOPLEFT", frame, "TOPLEFT", Lx, y)
    thBtn:SetText("Open Threat Settings")
    thBtn:SetScript("OnClick", function()
        if ns and ns.ThreatUI and ns.ThreatUI.ToggleFrame then
            ns.ThreatUI:ToggleFrame(applyAll)
        else
            print("|cFF00FF00Plate-o-Matic:|r Threat UI not loaded.")
        end
    end)
    y = y - 32

    -- =========================================================
    -- Specials (launcher)
    -- =========================================================
    MakeSectionTitle(frame, "Specials", Lx, y); y = y - 28
    local spBtn = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
    spBtn:SetSize(220, 20)
    spBtn:SetPoint("TOPLEFT", frame, "TOPLEFT", Lx, y)
    spBtn:SetText("Open Specials (/pomspecials)")
    spBtn:SetScript("OnClick", function()
        if ns and ns.Specials and ns.Specials.ToggleFrame then
            ns.Specials:ToggleFrame(applyAll)
        elseif ns and ns.Specials and ns.Specials.Toggle then
            ns.Specials:Toggle(applyAll)
        else
            RunSlash("/pomspecial")
        end
    end)
    y = y - 32

    MakeSectionTitle(frame, "Target Border", Lx, y); y = y - 28
    local tbRow = CreateFrame("Frame", nil, frame)
    tbRow:SetSize(390, 22)
    tbRow:SetPoint("TOPLEFT", frame, "TOPLEFT", Lx, y)

    local tbTxt = tbRow:CreateFontString(nil, "OVERLAY", "GameFontHighlight")
    tbTxt:SetPoint("LEFT", tbRow, "LEFT", 0, 0)
    tbTxt:SetText("Target Border Color")

    MakeColorSwatch(
        tbRow, 240, -2,
        function()
            -- READ ONLY: do not create keys here
            local db = PlateOMaticDB
            return (db and db.targetBorderColor) or { r=1, g=0.82, b=0, a=1 }
        end,
        function(r,g,b,a)
            -- WRITE ONLY on user action
            PlateOMaticDB.targetBorderColor = PlateOMaticDB.targetBorderColor or { r=1, g=0.82, b=0, a=1 }
            PlateOMaticDB.targetBorderColor.r = r
            PlateOMaticDB.targetBorderColor.g = g
            PlateOMaticDB.targetBorderColor.b = b
            PlateOMaticDB.targetBorderColor.a = a
        end,
        applyAll
    )

    -- RIGHT COLUMN
    MakeSectionTitle(frame, "Options", Rx, top)

    local cy = top - 28
    local cgap = 24

    MakeFontButton(frame, AVAILABLE_FONTS, Rx, cy, applyAll); cy = cy - cgap

    local outlineBtn = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
    outlineBtn:SetSize(220, 20)
    outlineBtn:SetPoint("TOPLEFT", frame, "TOPLEFT", Rx, cy)

    local function refreshOutline()
        local v = (PlateOMaticDB and PlateOMaticDB.fontOutline) or "OUTLINE"
        outlineBtn:SetText("Outline: " .. v)
    end
    refreshOutline()

    outlineBtn:SetScript("OnClick", function()
        local v = (PlateOMaticDB and PlateOMaticDB.fontOutline) or "OUTLINE"
        local nxt = (v == "NONE") and "OUTLINE" or (v == "OUTLINE") and "THICKOUTLINE" or "NONE"
        PlateOMaticDB.fontOutline = nxt
        refreshOutline()
        ApplyAll(applyAll)
    end)
    cy = cy - cgap

    MakeSlider(frame, "Font Size", "fontSize", Rx, cy, 6, 20, 1, applyAll); cy = cy - 46

    local soloCheck = MakeCheck(frame, "Use Base Colors When Solo (Overrides Other Colors)", "useBaseColorsSolo", Rx, cy, applyAll)
    local soloLbl = GetCheckLabel(soloCheck)
    if soloLbl then soloLbl:SetTextColor(0.9, 0.9, 0.9) end
    cy = cy - cgap

    local caBtn = CreateFrame("Button", nil, frame, "UIPanelButtonTemplate")
    caBtn:SetSize(220, 20)
    caBtn:SetPoint("TOPLEFT", frame, "TOPLEFT", Rx, cy)
    caBtn:SetText("Open Castbar Settings (/pomca)")
    caBtn:SetScript("OnClick", function()
        RunSlash("/pomca")
    end)
    cy = cy - (cgap + 6)

    MakeCheck(frame, "Hide Elite Icon", "hideClassIcon", Rx, cy, applyAll); cy = cy - cgap
    MakeCheck(frame, "Show Target Arrows", "showTargetArrow", Rx, cy, applyAll); cy = cy - cgap
    MakeCheck(frame, "Invert Arrows", "arrowPointingOut", Rx, cy, applyAll); cy = cy - cgap
    MakeCheck(frame, "Show Quest Icon", "showQuestIcon", Rx, cy, applyAll); cy = cy - cgap
    MakeCheck(frame, "Show Quest Progress", "showQuestProg", Rx, cy, applyAll); cy = cy - cgap

    MakeSectionTitle(frame, "Sliders", Rx, cy); cy = cy - 28
    MakeSlider(frame, "Global Scale", "globalScale", Rx, cy, 0.6, 1.6, 0.01, applyAll); cy = cy - 46
    MakeSlider(frame, "Target Scale", "targetScale", Rx, cy, 1.0, 1.6, 0.01, applyAll); cy = cy - 46
    MakeSlider(frame, "Buff Size", "buffSize", Rx, cy, 12, 40, 1, applyAll); cy = cy - 46
    MakeSlider(frame, "Debuff Size", "debuffSize", Rx, cy, 12, 40, 1, applyAll); cy = cy - 46
end
