local L = LibStub("AceLocale-3.0"):GetLocale("CritMatic")
Critmatic = Critmatic or {}

local function colorGroup(tbl, key, name, desc, disabled)
    return {
        key = key,
        name = name,
        desc = desc,
        disabled = disabled,
        get = function() return unpack(tbl().colors[key]) end,
        set = function(_, r, g, b) tbl().colors[key] = { r, g, b } end,
    }
end

local function globalColorGroup(key, name, desc)
    return {
        key = key,
        name = name,
        desc = desc,
        get = function() return unpack(Critmatic.db.profile.globalColors[key]) end,
        set = function(_, r, g, b) Critmatic.db.profile.globalColors[key] = { r, g, b } end,
    }
end

local function compactStyleToggle(field, order, name, desc)
    return {
        name = name,
        desc = desc,
        type = "toggle",
        order = order,
        set = function(_, newVal)
            local broker = Critmatic.db.profile.brokerSettings
            if newVal then
                broker.compactNumbers = false
                broker.compactInitials = false
                broker.compactLabels = false
                broker[field] = true
            else
                broker[field] = false
            end
            if Critmatic.UpdateBroker then Critmatic.UpdateBroker() end
        end,
        get = function()
            return Critmatic.db.profile.brokerSettings[field]
        end,
    }
end

function Critmatic:TooltipAppearanceFragment()
    local function S() return Critmatic.db.profile.tooltipFontSettings end
    local function dis() return S().useGlobalColors end
    return {
        name = L["options_tab_tooltip"],
        order = 2.5,
        font = {
            get = function() return S().font end,
            set = function(_, v) S().font = v end,
        },
        fontSize = {
            get = function() return S().fontSize end,
            set = function(_, v) S().fontSize = v end,
        },
        fontOutline = {
            get = function() return S().fontOutline end,
            set = function(_, v) S().fontOutline = v end,
        },
        colorGroups = {
            colorGroup(S, "spellName", L["appearance_color_spell_name"], L["appearance_color_spell_name_desc"], dis),
            colorGroup(S, "crit",      L["appearance_color_crit"],       L["appearance_color_crit_desc"], dis),
            colorGroup(S, "hit",       L["appearance_color_hit"],        L["appearance_color_hit_desc"], dis),
            colorGroup(S, "critHeal",  L["appearance_color_crit_heal"],  L["appearance_color_crit_heal_desc"], dis),
            colorGroup(S, "heal",      L["appearance_color_heal"],       L["appearance_color_heal_desc"], dis),
        },
        sort = {
            get = function() return S().sortMode end,
            set = function(_, v) S().sortMode = v end,
        },
        group = {
            get = function() return S().groupByType end,
            set = function(_, v) S().groupByType = v end,
        },
        groupOrder = {
            get = function() return S().groupOrder or "damage" end,
            set = function(_, v) S().groupOrder = v end,
        },
        names = {
            font            = L["appearance_font"],
            fontSize        = L["appearance_font_size"],
            fontOutline     = L["appearance_font_outline"],
            outlineNone     = L["options_alert_font_none"],
            outline         = L["options_alert_font_outline"],
            outlineMono     = L["options_alert_font_outline_mono"],
            outlineThick    = L["options_alert_font_outline_thick"],
            outlineThickMono = L["options_alert_font_outline_thick_mono"],
            sort            = L["appearance_sort"],
            sortRecent      = L["appearance_sort_recent"],
            sortHighest     = L["appearance_sort_highest"],
            group           = L["appearance_group"],
            groupDesc       = L["appearance_group_desc"],
            groupOrder       = L["appearance_group_order"],
            groupOrderDesc   = L["appearance_group_order_desc"],
            groupOrderDamage  = L["appearance_group_order_damage"],
            groupOrderHealing = L["appearance_group_order_healing"],
        },
    }
end

function Critmatic:ColorsFragment()
    local function refresh()
        if Critmatic.UpdateBroker then Critmatic.UpdateBroker() end
        if RedrawCritMaticWidget then RedrawCritMaticWidget() end
    end
    local function globalToggle(getTbl, order, name, desc)
        return {
            name = name,
            desc = desc,
            type = "toggle",
            width = "full",
            order = order,
            get = function() return getTbl().useGlobalColors end,
            set = function(_, v) getTbl().useGlobalColors = v; refresh() end,
        }
    end
    return {
        name = L["options_tab_colors"],
        order = 2.4,
        colorGroups = {
            globalColorGroup("spellName", L["appearance_color_spell_name"], L["appearance_color_spell_name_desc"]),
            globalColorGroup("crit",      L["appearance_color_crit"],       L["appearance_color_crit_desc"]),
            globalColorGroup("hit",       L["appearance_color_hit"],        L["appearance_color_hit_desc"]),
            globalColorGroup("critHeal",  L["appearance_color_crit_heal"],  L["appearance_color_crit_heal_desc"]),
            globalColorGroup("heal",      L["appearance_color_heal"],       L["appearance_color_heal_desc"]),
            globalColorGroup("petCrit",   L["appearance_color_pet_crit"],   L["appearance_color_pet_crit_desc"]),
            globalColorGroup("petHit",    L["appearance_color_pet_value"],  L["appearance_color_pet_value_desc"]),
        },
        extra = {
            useGlobalAlert = globalToggle(function() return Critmatic.db.profile.fontSettings end, 1, L["colors_use_global_alert"], L["colors_use_global_alert_desc"]),
            useGlobalBroker = globalToggle(function() return Critmatic.db.profile.tooltipFontSettings end, 2, L["colors_use_global_broker"], L["colors_use_global_broker_desc"]),
            useGlobalCritlog = globalToggle(function() return Critmatic.db.profile.critLogFontSettings end, 3, L["colors_use_global_critlog"], L["colors_use_global_critlog_desc"]),
        },
    }
end

function Critmatic:CritLogAppearanceFragment()
    local function S() return Critmatic.db.profile.critLogFontSettings end
    local function dis() return S().useGlobalColors end
    return {
        name = L["options_tab_critlog"],
        order = 2.6,
        font = {
            get = function() return S().font end,
            set = function(_, v) S().font = v end,
        },
        fontSize = {
            get = function() return S().fontSize end,
            set = function(_, v) S().fontSize = v end,
        },
        fontOutline = {
            get = function() return S().fontOutline end,
            set = function(_, v) S().fontOutline = v end,
        },
        colorGroups = {
            colorGroup(S, "spellName", L["appearance_color_spell_name"], L["appearance_color_spell_name_desc"], dis),
            colorGroup(S, "crit",      L["appearance_color_crit"],       L["appearance_color_crit_desc"], dis),
            colorGroup(S, "hit",       L["appearance_color_hit"],        L["appearance_color_hit_desc"], dis),
            colorGroup(S, "critHeal",  L["appearance_color_crit_heal"],  L["appearance_color_crit_heal_desc"], dis),
            colorGroup(S, "heal",      L["appearance_color_heal"],       L["appearance_color_heal_desc"], dis),
            colorGroup(S, "petCrit",   L["appearance_color_pet_crit"],   L["appearance_color_pet_crit_desc"], dis),
            colorGroup(S, "petHit",    L["appearance_color_pet_value"],  L["appearance_color_pet_value_desc"], dis),
        },
        sort = {
            get = function() return S().sortMode end,
            set = function(_, v) S().sortMode = v end,
        },
        group = {
            get = function() return S().groupByType end,
            set = function(_, v) S().groupByType = v end,
        },
        groupOrder = {
            get = function() return S().groupOrder or "damage" end,
            set = function(_, v) S().groupOrder = v end,
        },
        names = {
            font            = L["appearance_font"],
            fontSize        = L["appearance_font_size"],
            fontOutline     = L["appearance_font_outline"],
            outlineNone     = L["options_alert_font_none"],
            outline         = L["options_alert_font_outline"],
            outlineMono     = L["options_alert_font_outline_mono"],
            outlineThick    = L["options_alert_font_outline_thick"],
            outlineThickMono = L["options_alert_font_outline_thick_mono"],
            sort            = L["appearance_sort"],
            sortRecent      = L["appearance_sort_recent"],
            sortHighest     = L["appearance_sort_highest"],
            group           = L["appearance_group"],
            groupDesc       = L["appearance_group_desc"],
            groupOrder       = L["appearance_group_order"],
            groupOrderDesc   = L["appearance_group_order_desc"],
            groupOrderDamage  = L["appearance_group_order_damage"],
            groupOrderHealing = L["appearance_group_order_healing"],
        },
    }
end

local BROKER_ICON_CHOICES = {
    ["Interface\\AddOns\\CritMatic\\Media\\Textures\\critmatic-medallion.tga"] = "|TInterface\\AddOns\\CritMatic\\Media\\Textures\\critmatic-medallion.tga:20|t",
    ["Interface\\Icons\\Ability_Rogue_Eviscerate"]  = "|TInterface\\Icons\\Ability_Rogue_Eviscerate:20|t",
    ["Interface\\Icons\\Ability_Warrior_Decisivestrike"] = "|TInterface\\Icons\\Ability_Warrior_Decisivestrike:20|t",
    ["Interface\\Icons\\Spell_Fire_FlameBolt"]      = "|TInterface\\Icons\\Spell_Fire_FlameBolt:20|t",
    ["Interface\\Icons\\Spell_Holy_Heal"]           = "|TInterface\\Icons\\Spell_Holy_Heal:20|t",
    ["Interface\\Icons\\Spell_Holy_FlashHeal"]      = "|TInterface\\Icons\\Spell_Holy_FlashHeal:20|t",
    ["Interface\\Icons\\Spell_Holy_Renew"]          = "|TInterface\\Icons\\Spell_Holy_Renew:20|t",
    ["Interface\\Icons\\Spell_Nature_HealingTouch"] = "|TInterface\\Icons\\Spell_Nature_HealingTouch:20|t",
    ["Interface\\Icons\\Ability_Hunter_BeastCall"]  = "|TInterface\\Icons\\Ability_Hunter_BeastCall:20|t",
    ["Interface\\Icons\\Ability_Hunter_BeastTaming"] = "|TInterface\\Icons\\Ability_Hunter_BeastTaming:20|t",
    ["Interface\\Icons\\Spell_Nature_SpiritWolf"]   = "|TInterface\\Icons\\Spell_Nature_SpiritWolf:20|t",
    ["Interface\\Icons\\Ability_Druid_CatForm"]     = "|TInterface\\Icons\\Ability_Druid_CatForm:20|t",
}

local BROKER_ICON_DEFAULTS = {
    damage = "Interface\\AddOns\\CritMatic\\Media\\Textures\\critmatic-medallion.tga",
    healing = "Interface\\Icons\\Spell_Holy_Heal",
    pet = "Interface\\Icons\\Ability_Hunter_BeastCall",
}

local function brokerIconSelect(category, order, name, desc)
    return {
        name = name,
        desc = desc,
        type = "select",
        width = "double",
        order = order,
        values = BROKER_ICON_CHOICES,
        get = function()
            local icons = Critmatic.db.profile.brokerSettings.icons or {}
            return icons[category] or BROKER_ICON_DEFAULTS[category]
        end,
        set = function(_, v)
            local broker = Critmatic.db.profile.brokerSettings
            broker.icons = broker.icons or {}
            broker.icons[category] = v
            if Critmatic.UpdateBroker then Critmatic.UpdateBroker() end
        end,
    }
end

local function brokerPetColor(key, order, name, desc, disabled)
    return {
        name = name,
        desc = desc,
        type = "color",
        width = "normal",
        order = order,
        disabled = disabled,
        get = function() return unpack(Critmatic.db.profile.tooltipFontSettings.colors[key]) end,
        set = function(_, r, g, b)
            Critmatic.db.profile.tooltipFontSettings.colors[key] = { r, g, b }
            if Critmatic.UpdateBroker then Critmatic.UpdateBroker() end
        end,
    }
end

function Critmatic:BrokerAppearanceFragment()
    local function T() return Critmatic.db.profile.tooltipFontSettings end
    local function dis() return T().useGlobalColors end
    return {
        name = L["options_tab_broker"],
        order = 2.7,
        font = {
            get = function() return T().font end,
            set = function(_, v) T().font = v end,
        },
        fontSize = {
            get = function() return T().fontSize end,
            set = function(_, v) T().fontSize = v end,
        },
        fontOutline = {
            get = function() return T().fontOutline end,
            set = function(_, v) T().fontOutline = v end,
        },
        names = {
            font            = L["appearance_font"],
            fontSize        = L["appearance_font_size"],
            fontOutline     = L["appearance_font_outline"],
            outlineNone     = L["options_alert_font_none"],
            outline         = L["options_alert_font_outline"],
            outlineMono     = L["options_alert_font_outline_mono"],
            outlineThick    = L["options_alert_font_outline_thick"],
            outlineThickMono = L["options_alert_font_outline_thick_mono"],
        },
        extra = {
            brokerPetCrit = brokerPetColor("petCrit", 11, L["appearance_color_pet_crit"], L["appearance_color_pet_crit_desc"], dis),
            brokerPetValue = brokerPetColor("petHit", 12, L["appearance_color_pet_value"], L["appearance_color_pet_value_desc"], dis),
            brokerDamageIcon = brokerIconSelect("damage", 50, L["options_broker_damage_icon"], L["options_broker_damage_icon_desc"]),
            brokerHealingIcon = brokerIconSelect("healing", 51, L["options_broker_healing_icon"], L["options_broker_healing_icon_desc"]),
            brokerPetIcon = brokerIconSelect("pet", 52, L["options_broker_pet_icon"], L["options_broker_pet_icon_desc"]),
            brokerHitFirst = {
                name = L["options_broker_hit_first"],
                desc = L["options_broker_hit_first_desc"],
                type = "toggle",
                order = 40,
                set = function(_, newVal)
                    Critmatic.db.profile.brokerSettings.hitFirst = newVal and true or false
                    if Critmatic.UpdateBroker then Critmatic.UpdateBroker() end
                end,
                get = function()
                    return Critmatic.db.profile.brokerSettings.hitFirst
                end,
            },
            brokerCompactNumbers = compactStyleToggle("compactNumbers", 41, L["options_broker_compact_numbers"], L["options_broker_compact_numbers_desc"]),
            brokerCompactInitials = compactStyleToggle("compactInitials", 42, L["options_broker_compact_initials"], L["options_broker_compact_initials_desc"]),
            brokerCompactLabels = compactStyleToggle("compactLabels", 43, L["options_broker_compact_labels"], L["options_broker_compact_labels_desc"]),
            brokerShowFullLog = {
                name = L["options_broker_show_full_log"],
                desc = L["options_broker_show_full_log_desc"],
                type = "toggle",
                order = 44,
                set = function(_, newVal)
                    Critmatic.db.profile.brokerSettings.showFullLog = newVal and true or false
                end,
                get = function()
                    return Critmatic.db.profile.brokerSettings.showFullLog ~= false
                end,
            },
            brokerTooltipCap = {
                name = L["options_broker_tooltip_cap"],
                desc = L["options_broker_tooltip_cap_desc"],
                type = "range",
                order = 45,
                min = 5,
                max = 50,
                step = 1,
                set = function(_, newVal)
                    Critmatic.db.profile.brokerSettings.tooltipSpellCap = newVal
                end,
                get = function()
                    return Critmatic.db.profile.brokerSettings.tooltipSpellCap or 15
                end,
            },
            brokerShowDamageIcon = {
                name = L["options_broker_show_damage_icon"],
                desc = L["options_broker_show_damage_icon_desc"],
                type = "toggle",
                order = 46,
                set = function(_, newVal)
                    if Critmatic.SetCategoryMinimapHidden then Critmatic.SetCategoryMinimapHidden("damage", not newVal) end
                end,
                get = function()
                    local mm = Critmatic.db.profile.minimapDamage
                    return mm and not mm.hide
                end,
            },
            brokerShowHealingIcon = {
                name = L["options_broker_show_healing_icon"],
                desc = L["options_broker_show_healing_icon_desc"],
                type = "toggle",
                order = 47,
                set = function(_, newVal)
                    if Critmatic.SetCategoryMinimapHidden then Critmatic.SetCategoryMinimapHidden("healing", not newVal) end
                end,
                get = function()
                    local mm = Critmatic.db.profile.minimapHealing
                    return mm and not mm.hide
                end,
            },
            brokerShowPetIcon = {
                name = L["options_broker_show_pet_icon"],
                desc = L["options_broker_show_pet_icon_desc"],
                type = "toggle",
                order = 48,
                set = function(_, newVal)
                    if Critmatic.SetCategoryMinimapHidden then Critmatic.SetCategoryMinimapHidden("pet", not newVal) end
                end,
                get = function()
                    local mm = Critmatic.db.profile.minimapPets
                    return mm and not mm.hide
                end,
            },
        },
    }
end
