local addonName, ns = ...
local L = ns.L

ns.Config = {}
local Config = ns.Config

local wipe = wipe

local CORE_STATS  = { "crit", "haste", "mastery", "versatility" }
local EXTRA_STATS = { "leech", "avoidance", "speed", "strength", "agility", "stamina", "intellect" }

local THEME_OPTIONS = {
    { value = "auto",    label = "THEME_AUTO" },
    { value = "classic", label = "THEME_CLASSIC" },
    { value = "elvui",   label = "THEME_ELVUI" },
    { value = "metal",   label = "THEME_METAL" },
}

local LAYOUT_OPTIONS = {
    { value = "circle", label = "LAYOUT_CIRCLE" },
    { value = "bar",    label = "LAYOUT_BAR" },
}

local function SetTheme(value)
    local db = ns.db
    if db.theme == value then return end
    db.theme = value
    if ns.Integration and ns.db.embed and ns.Integration.SelectEmbedTab then
        ns.Integration:SelectEmbedTab()
    end
    if ns.Chart then
        if ns.Chart.ApplyLayout then ns.Chart:ApplyLayout() end
        if ns.Chart.Refresh then ns.Chart:Refresh() end
    end
end

local function SetChartLayout(value)
    local db = ns.db
    if db.chartLayout == value then return end
    db.chartLayout = value
    if ns.Chart then
        if ns.Chart.ApplyLayout then ns.Chart:ApplyLayout() end
        if ns.Chart.Refresh then ns.Chart:Refresh() end
    end
end

local function ColoredName(def)
    local c = def.color
    return ("|cff%02x%02x%02x%s|r"):format(c[1] * 255, c[2] * 255, c[3] * 255, def.name)
end

-- True if the stat currently appears on the chart.
local function IsStatSelected(key)
    local db = ns.db
    if db.useAuto then
        for _, k in ipairs(ns.Stats:GetActiveKeys()) do
            if k == key then return true end
        end
        return false
    end
    return db.shown[key] == true
end

-- Toggling any stat switches to manual mode, seeding from the auto selection.
local function ToggleStat(key)
    local db = ns.db
    if db.useAuto then
        local autoKeys = ns.Stats:GetActiveKeys()
        db.useAuto = false
        wipe(db.shown)
        for _, k in ipairs(autoKeys) do
            db.shown[k] = true
        end
    end
    db.shown[key] = (not db.shown[key]) and true or nil
    if ns.Chart then ns.Chart:Refresh() end
end

local function AddStatCheckbox(node, key)
    local def = ns.STAT_BY_KEY[key]
    if not def then return end
    node:CreateCheckbox(ColoredName(def),
        function() return IsStatSelected(key) end,
        function()
            ToggleStat(key)
            return MenuResponse and MenuResponse.Refresh
        end)
end

function Config:OpenMenu(anchor)
    if not (MenuUtil and MenuUtil.CreateContextMenu) then
        return
    end

    MenuUtil.CreateContextMenu(anchor, function(_, root)
        root:CreateTitle(L["TITLE"])

        root:CreateCheckbox(L["AUTO_PRIORITY"],
            function() return ns.db.useAuto end,
            function()
                local db = ns.db
                db.useAuto = not db.useAuto
                if not db.useAuto and not next(db.shown) then
                    for _, k in ipairs(ns.Stats:GetActiveKeys()) do
                        db.shown[k] = true
                    end
                end
                if ns.Chart then ns.Chart:Refresh() end
                return MenuResponse and MenuResponse.Refresh
            end)

        root:CreateDivider()
        root:CreateTitle(L["MENU_TITLE"])
        for _, key in ipairs(CORE_STATS) do
            AddStatCheckbox(root, key)
        end

        local more = root:CreateButton(L["MORE_STATS"])
        for _, key in ipairs(EXTRA_STATS) do
            AddStatCheckbox(more, key)
        end

        root:CreateDivider()
        local themeMenu = root:CreateButton(L["THEME"])
        for _, opt in ipairs(THEME_OPTIONS) do
            local value = opt.value
            themeMenu:CreateRadio(L[opt.label],
                function() return ns.db.theme == value end,
                function()
                    SetTheme(value)
                    return MenuResponse and MenuResponse.Refresh
                end)
        end

        local layoutMenu = root:CreateButton(L["LAYOUT"])
        for _, opt in ipairs(LAYOUT_OPTIONS) do
            local value = opt.value
            layoutMenu:CreateRadio(L[opt.label],
                function() return (ns.db.chartLayout or "circle") == value end,
                function()
                    SetChartLayout(value)
                    return MenuResponse and MenuResponse.Refresh
                end)
        end

        root:CreateDivider()
        root:CreateCheckbox(L["SHOW_LEGEND"],
            function() return ns.db.showLegend end,
            function()
                ns.db.showLegend = not ns.db.showLegend
                if ns.Chart then ns.Chart:Refresh() end
                return MenuResponse and MenuResponse.Refresh
            end)

        root:CreateCheckbox(L["SHOW_CHROME"],
            function() return ns.db.showChrome end,
            function()
                ns.db.showChrome = not ns.db.showChrome
                if ns.Chart then ns.Chart:ApplyChrome() end
                return MenuResponse and MenuResponse.Refresh
            end)

        root:CreateDivider()

        if not ns.Integration or ns.Integration.CanEmbed() then
            root:CreateCheckbox(L["EMBED"],
                function() return ns.db.embed end,
                function()
                    ns.db.embed = not ns.db.embed
                    if ns.Integration then ns.Integration:ApplyMode() end
                    return MenuResponse and MenuResponse.Refresh
                end)
        end

        if not ns.db.embed then
            root:CreateCheckbox(L["FREE_MOVE"],
                function() return ns.db.freeMove end,
                function()
                    local db = ns.db
                    db.freeMove = not db.freeMove
                    if not db.freeMove then
                        db.pos = nil
                    end
                    if ns.Chart then
                        ns.Chart:ApplyPosition()
                        ns.Chart:UpdateMovable()
                    end
                    return MenuResponse and MenuResponse.Refresh
                end)

            if ns.db.freeMove then
                root:CreateButton(L["RESET_POSITION"], function()
                    if ns.Chart then ns.Chart:ResetPosition() end
                end)
            end
        end
    end)
end
