local _, MerfinPlus = ...

local AceDB = LibStub("AceDB-3.0")
local AceDBOptions = LibStub("AceDBOptions-3.0")
local AceConfig = LibStub("AceConfig-3.0")
local AceConfigDialog = LibStub("AceConfigDialog-3.0")
local AceConfigRegistry = LibStub("AceConfigRegistry-3.0")
local LSM = LibStub("LibSharedMedia-3.0")

local GetAddOnMetadata = C_AddOns.GetAddOnMetadata

MerfinPlus.defaults = {
    profile = {
        pullStartTime = 0,
        pullExpTime = 0,
        pullTotalTime = 0,
        pullSenderName = 'Unknown',
        breakStartTime = 0,
        breakExpTime = 0,
        breakTotalTime = 0,
        breakSenderName = 'Unknown',
        lfgStartTimer = 0,
        lfgExpTimer = 0,
        font1 = "SFUIDisplayCondensed-Semibold",
        font2 = "SFUIDisplayCondensed-Semibold",
        font3 = "SFUIDisplayCondensed-Semibold",
        font4 = "SFUIDisplayCondensed-Bold",
        bar1 = "MerfinMainDark",
        bar2 = "MerfinMain",
        bar3 = "MerfinMainDark",
    }
}

function MerfinPlus:SetupOptions()
    local function GetFontList()
        local fonts = {}
        local excludedFonts = {
            ["Merfin Font 1"] = true,
            ["Merfin Font 2"] = true,
            ["Merfin Raid Font"] = true,
            ["Merfin Raid Font (Bold)"] = true,
        }
        for name in pairs(LSM:HashTable("font")) do
            if not excludedFonts[name] then
                fonts[name] = name
            end
        end
        return fonts
    end

    local function GetStatusBarList()
        local bars = {}
        local excludedBars = {
            ["Merfin Status Bar 1"] = true,
            ["Merfin Status Bar 2"] = true,
            ["Merfin Raid Status Bar"] = true,
        }
        for name in pairs(LSM:HashTable("statusbar")) do
            if not excludedBars[name] then
                bars[name] = name
            end
        end
        return bars
    end

    local function ConfirmReload()
        StaticPopupDialogs["MERFINPLUS_RELOAD_UI"] = {
            text = "A reload of the interface is required for this change to take effect.\n\nReload now?",
            button1 = "Yes",
            button2 = "No",
            OnAccept = function() ReloadUI() end,
            timeout = 0,
            whileDead = true,
            hideOnEscape = true,
            preferredIndex = 3,
        }
        StaticPopup_Show("MERFINPLUS_RELOAD_UI")
    end

    local mainOptions = {
        type = "group",
        name = "MerfinPlus",
        args = {
            version = { type = "description", name = "|cff00ccffVersion:|r " .. GetAddOnMetadata('MerfinPlus', 'Version'), fontSize = "medium", order = 1 },
            author = { type = "description", name = "Author: Merfin", fontSize = "medium", order = 2 },
            spacer = { type = "description", name = " ", order = 3 },
            description = {
                type = "description",
                name = "MerfinPlus provides a collection of custom fonts, textures, and other media assets for use in the game interface. It also includes utility features that enhance or support WeakAuras and other Merfin-related UI components.",
                fontSize = "large",
                order = 4,
            },
            spacer2 = { type = "description", name = " ", order = 5 },
        },
    }

    local mediaOptions = {
        type = "group",
        name = "Media",
        args = {
            description = {
                type = "description",
                name = "Here you can change the primary fonts and status bar textures used by Merfin features. After reloading the interface, elements such as Merfin WeakAuras or Profiles will update to reflect the new media selection.",
                fontSize = "medium",
                order = 0,
            },
        },
    }

    local fontNames = { "Merfin Font 1", "Merfin Font 2", "Merfin Raid Font", "Merfin Raid Font (Bold)"}
    local barNames  = { "Merfin Status Bar 1", "Merfin Status Bar 2", "Merfin Raid Status Bar" }

    for i = 1, #fontNames do
        mediaOptions.args["font" .. i] = {
            type = "select",
            name = fontNames[i],
            desc = "Select font for element " .. i,
            values = GetFontList,
            get = function() return self.db.profile["font" .. i] end,
            set = function(_, value)
                self.db.profile["font" .. i] = value
                ConfirmReload()
            end,
            dialogControl = "LSM30_Font",
            order = i + 1,
        }
    end

    for i = 1, #barNames do
        mediaOptions.args["bar" .. i] = {
            type = "select",
            name = barNames[i],
            desc = "Select status bar texture for element " .. i,
            values = GetStatusBarList,
            get = function() return self.db.profile["bar" .. i] end,
            set = function(_, value)
                self.db.profile["bar" .. i] = value
                ConfirmReload()
            end,
            dialogControl = "LSM30_Statusbar",
            order = i + 10,
        }
    end

    AceConfigRegistry:RegisterOptionsTable("MerfinPlus", mainOptions)
    self.optionsFrame = AceConfigDialog:AddToBlizOptions("MerfinPlus", "MerfinPlus")

    AceConfigRegistry:RegisterOptionsTable("MerfinPlus_Media", mediaOptions)
    AceConfigDialog:AddToBlizOptions("MerfinPlus_Media", "Media", "MerfinPlus")

    local profilesOptions = AceDBOptions:GetOptionsTable(self.db)
    AceConfigRegistry:RegisterOptionsTable("MerfinPlus_Profiles", profilesOptions)
    AceConfigDialog:AddToBlizOptions("MerfinPlus_Profiles", "Profiles", "MerfinPlus")
end

function MerfinPlus:RegisterCustomFonts()
    local db = self:GetDB()
    local fonts = {
        {key = "font1", name = "Merfin Font 1"},
        {key = "font2", name = "Merfin Font 2"},
        {key = "font3", name = "Merfin Raid Font"},
        {key = "font4", name = "Merfin Raid Font (Bold)"},
    }
    for _, font in ipairs(fonts) do
        local path = LSM:Fetch("font", db[font.key], true)
        if path then
            LSM:Register("font", font.name, path, LSM.LOCALE_BIT_western + LSM.LOCALE_BIT_ruRU + LSM.LOCALE_BIT_koKR + LSM.LOCALE_BIT_zhCN + LSM.LOCALE_BIT_zhTW)
        else
            --print(string.format("|cffff0000[MerfinPlus]|r Failed to register %s - invalid font path", font.name))
        end
    end
end

function MerfinPlus:RegisterCustomBars()
    local db = self:GetDB()

    local bars = {
        {key = "bar1", name = "Merfin Status Bar 1"},
        {key = "bar2", name = "Merfin Status Bar 2"},
        {key = "bar3", name = "Merfin Raid Status Bar"},
    }

    for _, bar in ipairs(bars) do
        local path = LSM:Fetch("statusbar", db[bar.key], true)
        if path then
            LSM:Register("statusbar", bar.name, path)
        else
            --print(string.format("|cffff0000[MerfinPlus]|r Failed to register %s - invalid status bar path", bar.name))
        end
    end
end

function MerfinPlus:RegisterMediaAliasesFromCallback()
    local db = self:GetDB()

    local fontMap = {
        { key = db.font1, alias = "Merfin Font 1" },
        { key = db.font2, alias = "Merfin Font 2" },
        { key = db.font3, alias = "Merfin Raid Font" },
        { key = db.font4, alias = "Merfin Raid Font (Bold)" },
    }

    local barMap = {
        { key = db.bar1, alias = "Merfin Status Bar 1" },
        { key = db.bar2, alias = "Merfin Status Bar 2" },
        { key = db.bar3, alias = "Merfin Raid Status Bar" },
    }

    LSM.RegisterCallback(self, "LibSharedMedia_Registered", function(_, mediatype, key)
        if mediatype == "font" then
            for _, entry in ipairs(fontMap) do
                if entry.key == key then
                    local path = LSM:Fetch("font", entry.key)
                    if path then
                        LSM:Register("font", entry.alias, path, LSM.LOCALE_BIT_western + LSM.LOCALE_BIT_ruRU + LSM.LOCALE_BIT_koKR + LSM.LOCALE_BIT_zhCN + LSM.LOCALE_BIT_zhTW)
                    end
                end
            end
        elseif mediatype == "statusbar" or mediatype == 'statusbar_atlas' then
            for _, entry in ipairs(barMap) do
                if entry.key == key then
                    local path = LSM:Fetch("statusbar", entry.key)
                    if path then
                        LSM:Register("statusbar", entry.alias, path)
                    end
                end
            end
        end
    end)

end