-- UI/Theme/Theme.lua
--
-- A centralized module that provides all styling information for the Toolkit UI.
-- This includes colors, spacing, fonts, sizes, and helper functions to apply
-- standard styles to UI elements.

local addonName, SinsToolkit = ...

-- Ensure the namespace exists.
SinsToolkit.UI = SinsToolkit.UI or {}

local Theme = {}
SinsToolkit.UI.Theme = Theme

--[[---------------------------------------------------------------------------
    Private Theme Data
---------------------------------------------------------------------------]]--

local data = {
    colors = {
        accent = { r = 0.72, g = 0.41, b = 0.88 },
        background = { r = 0.02, g = 0.02, b = 0.025, a = 0.92 },
        border = { r = 0.72, g = 0.41, b = 0.88, a = 0.90 },
        divider = { r = 0.25, g = 0.25, b = 0.25, a = 0.8 },

        success = { r = 0.10, g = 0.95, b = 0.35 },
        warning = { r = 0.85, g = 0.66, b = 0.29 },
        error = { r = 1.00, g = 0.28, b = 0.28 },
        
        font = { r = 1, g = 1, b = 1 },
        font_header = { r = 0.72, g = 0.65, b = 0.84 },
        font_highlight = { r = 0.85, g = 0.85, b = 0.85 },
    },
    spacing = {
        page_padding = 12,
        card_padding = 14,
        section_divider_top = -6,
        section_content_top = -8,
        section_spacing = 14,
        row_spacing = 8,
        checkbox_spacing = 8,
        toolbar_gap = 10,
        button_gap = 10,
        control_vertical_gap = 8,
        scroll_margin = 8,
    },
    density = {
        normal = {
            section_spacing = 18,
            checkbox_row_height = 28,
            card_padding = 16,
            wrapped_text_max_width = 720,
        },
        compact = {
            section_spacing = 14,
            checkbox_row_height = 24,
            card_padding = 14,
            wrapped_text_max_width = 680,
        },
        dense = {
            section_spacing = 10,
            checkbox_row_height = 20,
            card_padding = 10,
            wrapped_text_max_width = 620,
        },
    },
    sizes = {
        button = { width = 160, height = 28 },
        button_small = { width = 120, height = 24 },
        checkbox = { width = 24, height = 24 },
        checkbox_row = { width = 320, height = 24 },
        search_box = { width = 220, height = 24 },
        icon = { width = 28, height = 28 },
    },
    fonts = {
        page_title = "GameFontNormalLarge",
        section_header = "GameFontNormal",
        card_title = "GameFontNormal",
        page_description = "GameFontHighlightSmall",
        body = "GameFontHighlight",
        body_small = "GameFontHighlightSmall",
        status_text = "GameFontHighlightSmall",
        label = "GameFontNormalSmall",
        button = "GameFontNormal",
        tooltip = "GameFontHighlightSmall",
        header = "GameFontNormal",
        text = "GameFontHighlight",
        small = "GameFontHighlightSmall",
    },
    defaultDensity = "compact",
}

--[[---------------------------------------------------------------------------
    Public API
---------------------------------------------------------------------------]]--

--[[
    Retrieves a color table by name.
    @param name The name of the color (e.g., "accent", "success").
    @return A table with r, g, b, (a) values, or the accent color if not found.
--]]
function Theme.GetColor(name)
    return data.colors[name] or data.colors.accent
end

--[[
    Retrieves a spacing/padding value by name.
    @param name The name of the spacing value.
    @return A number, or 0 if not found.
--]]
function Theme.GetSpacing(name)
    return data.spacing[name] or 0
end

--[[
    Retrieves a density preset. Migrated pages should default to "compact" so
    pages fit the visible content area whenever practical without increasing
    global font sizes.
    @param name The density preset name: "normal", "compact", or "dense".
    @return A density preset table.
--]]
function Theme.GetDensity(name)
    return data.density[name or data.defaultDensity] or data.density[data.defaultDensity]
end

function Theme.GetDefaultDensity()
    return data.defaultDensity
end

function Theme.GetCompactSectionSpacing()
    return Theme.GetDensity("compact").section_spacing
end

function Theme.GetCompactCheckboxRowHeight()
    return Theme.GetDensity("compact").checkbox_row_height
end

function Theme.GetCompactCardPadding()
    return Theme.GetDensity("compact").card_padding
end

function Theme.GetWrappedTextMaxWidth(density)
    return Theme.GetDensity(density).wrapped_text_max_width
end

--[[
    Retrieves a standard size table by name.
    @param name The name of the size entry (e.g., "button", "checkbox").
    @return A table with width and height, or a default.
--]]
function Theme.GetSize(name)
    return data.sizes[name] or { width = 0, height = 0 }
end

--[[
    Retrieves the standard size for a button.
    @return A table with width and height.
--]]
function Theme.GetButtonSize()
    -- DEPRECATED: Use GetSize("button") instead.
    return Theme.GetSize("button")
end

--[[
    Retrieves a font object name.
    @param name The name of the font type ("header", "text", "small").
    @return A string with the font object name.
--]]
function Theme.GetFont(name)
    return data.fonts[name] or data.fonts.text
end

function Theme.ApplyFont(fontString, fontName, colorName)
    if not fontString then return fontString end
    if fontString.SetFontObject then
        local fontObject = Theme.GetFont(fontName)
        if type(fontObject) == "string" then
            fontObject = _G[fontObject] or fontObject
        end
        fontString:SetFontObject(fontObject)
    end
    local color = Theme.GetColor(colorName or "font")
    if fontString.SetTextColor and color then
        fontString:SetTextColor(color.r, color.g, color.b, color.a or 1)
    end
    return fontString
end

function Theme.ApplyPageTitle(fontString)
    return Theme.ApplyFont(fontString, "page_title", "accent")
end

function Theme.ApplySectionHeader(fontString)
    return Theme.ApplyFont(fontString, "section_header", "warning")
end

function Theme.ApplyCardTitle(fontString)
    return Theme.ApplyFont(fontString, "card_title", "warning")
end

function Theme.ApplyBodyFont(fontString)
    return Theme.ApplyFont(fontString, "body", "font_highlight")
end

function Theme.ApplyPageDescription(fontString)
    return Theme.ApplyFont(fontString, "page_description", "font_header")
end

function Theme.ApplySmallBodyFont(fontString)
    return Theme.ApplyFont(fontString, "body_small", "font_header")
end

function Theme.ApplyStatusText(fontString)
    return Theme.ApplyFont(fontString, "status_text", "font_header")
end

function Theme.ApplyLabelFont(fontString)
    return Theme.ApplyFont(fontString, "label", "warning")
end

function Theme.ApplyButtonText(fontString)
    return Theme.ApplyFont(fontString, "button", "warning")
end

function Theme.ApplyTooltipFont(fontString)
    return Theme.ApplyFont(fontString, "tooltip", "font_highlight")
end

function Theme.GetPagePadding(density)
    return Theme.GetDensity(density).page_padding or Theme.GetSpacing("page_padding")
end

function Theme.GetCardPadding(density)
    return Theme.GetDensity(density).card_padding or Theme.GetSpacing("card_padding")
end

function Theme.GetSectionSpacing(density)
    return Theme.GetDensity(density).section_spacing or Theme.GetSpacing("section_spacing")
end

function Theme.GetRowSpacing(density)
    return Theme.GetDensity(density).row_spacing or Theme.GetSpacing("row_spacing")
end

function Theme.GetCheckboxRowHeight(density)
    return Theme.GetDensity(density).checkbox_row_height or Theme.GetSize("checkbox_row").height
end

--[[
    Applies the standard Toolkit panel backdrop style to a frame.
    This is for main window containers.
    @param frame The frame to style.
--]]
function Theme.ApplyPanel(frame)
    frame:SetBackdrop({
        bgFile = "Interface\\Buttons\\WHITE8X8",
        edgeFile = "Interface\\Buttons\\WHITE8X8",
        tile = true, tileSize = 8, edgeSize = 1,
        insets = { left = 1, right = 1, top = 1, bottom = 1 },
    })
    local bg = data.colors.background
    local border = data.colors.border
    frame:SetBackdropColor(bg.r, bg.g, bg.b, bg.a)
    frame:SetBackdropBorderColor(border.r, border.g, border.b, border.a)
    SinsToolkit.RegisterOpacityFrame(frame, bg.r, bg.g, bg.b, border.r, border.g, border.b, border.a)
end

--[[
    Applies the standard Toolkit card backdrop style to a frame.
    This is for content containers inside pages.
    @param frame The frame to style.
--]]
function Theme.ApplyCard(frame)
    Theme.ApplyPanel(frame) -- For now, cards and panels share the same style.
end

--[[
    Creates and applies the style for a standard section header.
    @param parent The parent frame.
    @param text The header text.
    @return The header FontString and the divider Texture.
--]]
function Theme.ApplySection(parent, text)
    local header = parent:CreateFontString(nil, "OVERLAY", Theme.GetFont("header"))
    header:SetPoint("TOPLEFT", Theme.GetSpacing("card_padding"), -Theme.GetSpacing("card_padding"))
    header:SetText(text or "")
    
    local divider = parent:CreateTexture(nil, "BACKGROUND")
    divider:SetPoint("TOPLEFT", header, "BOTTOMLEFT", 0, Theme.GetSpacing("section_divider_top"))
    divider:SetPoint("RIGHT", parent, "RIGHT", -Theme.GetSpacing("card_padding"), 0)
    divider:SetHeight(1)
    local divColor = Theme.GetColor("divider")
    divider:SetColorTexture(divColor.r, divColor.g, divColor.b, divColor.a)
    
    return header, divider
end
