local _, ns = ...
local BDT = ns.DataTexts
local L = BDT.L
BDT.FormatUtils = {}

----------------------------------------------------
-- WoW API Locals
----------------------------------------------------
local BreakUpLargeNumbers = BreakUpLargeNumbers

----------------------------------------------------
-- Add Tooltip Header
----------------------------------------------------
function BDT.FormatUtils:AddTooltipHeader(tooltip, fontSize, text, r, g, b, wrap)
    tooltip = tooltip or BDT.Tooltip
    r = r or 1
    g = g or 0.82
    b = b or 0

    -- Use global setting if fontSize not specified
    fontSize = fontSize or BDT.db.profile.tooltipHeaderFontSize
    
    tooltip:AddLine(text, r, g, b, wrap or false)
    
    -- Force the header to use a specific font size
    local textLeft = _G[tooltip:GetName() .. "TextLeft" .. tooltip:NumLines()]
    if textLeft then
        local fontPath = BDT.LSM:Fetch("font", BDT.db.profile.tooltipFont)
        local outline = BDT.db.profile.tooltipFontOutline
        local safeOutline = (not outline or outline == "NONE") and nil or outline
        if fontPath then pcall(function() textLeft:SetFont(fontPath, fontSize, safeOutline) end) end

        -- Apply shadow setting
        if BDT.db.profile.tooltipShadowEnabled then
            textLeft:SetShadowOffset(1, -1)
            textLeft:SetShadowColor(0, 0, 0, 1)
        else
            textLeft:SetShadowOffset(0, 0)
        end
    end
end

----------------------------------------------------
-- Add Tooltip Line
----------------------------------------------------
function BDT.FormatUtils:AddTooltipLine(tooltip, fontSize, textLeft, textRight, r1, g1, b1, r2, g2, b2, wrap)
    tooltip = tooltip or BDT.Tooltip

    -- Use global setting if fontSize not specified
    fontSize = fontSize or BDT.db.profile.tooltipLineFontSize

    -- Handle single or double lines
    if textRight then
        r1 = r1 or 1
        g1 = g1 or 1
        b1 = b1 or 1
        r2 = r2 or 0.5
        g2 = g2 or 0.5
        b2 = b2 or 0.5
        tooltip:AddDoubleLine(textLeft, textRight, r1, g1, b1, r2, g2, b2, wrap or false)
    else
        r1 = r1 or 1
        g1 = g1 or 1
        b1 = b1 or 1
        tooltip:AddLine(textLeft, r1, g1, b1, wrap or false)
    end

    -- Apply font size to the line
    local fontPath = BDT.LSM:Fetch("font", BDT.db.profile.tooltipFont)
    local outline = BDT.db.profile.tooltipFontOutline
    local lineNum = tooltip:NumLines()
    local textLeftObj = _G[tooltip:GetName() .. "TextLeft" .. lineNum]
    local textRightObj = _G[tooltip:GetName() .. "TextRight" .. lineNum]
    
    -- Convert "NONE" to nil for SetFont (WoW rejects "NONE" as flags arg)
    local safeOutline = (not outline or outline == "NONE") and nil or outline
    if textLeftObj and fontPath then
        pcall(function() textLeftObj:SetFont(fontPath, fontSize, safeOutline) end)
        -- Apply shadow setting
        if BDT.db.profile.tooltipShadowEnabled then
            textLeftObj:SetShadowOffset(1, -1)
            textLeftObj:SetShadowColor(0, 0, 0, 1)
        else
            textLeftObj:SetShadowOffset(0, 0)
        end
    end
    if textRightObj and fontPath then
        pcall(function() textRightObj:SetFont(fontPath, fontSize, safeOutline) end)
        -- Apply shadow setting
        if BDT.db.profile.tooltipShadowEnabled then
            textRightObj:SetShadowOffset(1, -1)
            textRightObj:SetShadowColor(0, 0, 0, 1)
        else
            textRightObj:SetShadowOffset(0, 0)
        end
    end
end

----------------------------------------------------
-- Format Large Numbers
----------------------------------------------------
function BDT.FormatUtils:FormatLargeNumbers(n)
    local locale = BDT.cache.locale
    local sep

    if locale == "frFR" then
        sep = " "
    elseif locale == "deDE" then
        sep = "."
    elseif locale == "enUS" or locale == "enGB" then
        sep = ","
    else
        return BreakUpLargeNumbers(n)
    end

    local s = tostring(math.floor(n))
    while true do
        local k
        s, k = s:gsub("^(-?%d+)(%d%d%d)", "%1"..sep.."%2")
        if k == 0 then break end
    end
    return s
end

----------------------------------------------------
-- Format Percent
----------------------------------------------------
function BDT.FormatUtils:FormatPercent(v, hideDecimals, roundDown)
    if hideDecimals then
        if roundDown then
            return format("%d%%", v)
        else
            -- Round to nearest integer using standard rounding (>= 0.5 rounds up)
            return format("%d%%", v + 0.5)
        end
    else
        return format("%.2f%%", v)
    end
end

----------------------------------------------------
-- Get Tag Color
----------------------------------------------------
function BDT.FormatUtils:GetTagColor()
    if BDT.db.profile.useCustomColor then
        local color = BDT.db.profile.customColorHex:gsub("#", "")
        return "ff"..color
    elseif BDT.db.profile.useClassColor then
        return BDT.cache.colorHex
    end
    return "ffffffff"
end

----------------------------------------------------
-- Color Text
----------------------------------------------------
function BDT.FormatUtils:ColorText(text)
    local color = self:GetTagColor()
    return "|c"..color..text.."|r"
end

----------------------------------------------------
-- Color Module Text
----------------------------------------------------
function BDT.FormatUtils:ColorModuleText(moduleName, text)
    local overrideColor = BDT:GetModuleSetting(moduleName, "overrideTextColor", false)
    if overrideColor then
        local colorSetting = BDT:GetModuleSetting(moduleName, "customTextColor", "#FFFFFF")
        return format("|cff%s%s|r", colorSetting:gsub("#", ""), text)
    else
        return BDT.FormatUtils:ColorText(text)
    end
end

----------------------------------------------------
-- Find Best Anchor Point
----------------------------------------------------
function BDT.FormatUtils:FindBestAnchorPoint(frame)
    local x, y = frame:GetCenter()
    local screenWidth = UIParent:GetRight()
    local screenHeight = UIParent:GetTop()

    if not x or not y then
        return "ANCHOR_BOTTOM"
    else
        if y < screenHeight / 2 then
            return "ANCHOR_TOP"
        else
            return "ANCHOR_BOTTOM"
        end
    end
end
