-- LibDataBroker data source for Dynamic Profiles.
-- Shows on ChocolateBar / Titan / Bazooka / etc. Same click semantics as the picker.
-- Text format is user-configurable via Settings → Broker Config
-- (%profile%, %icon%, %shortname%, %fullname%).

local addonName, DP = ...
DP = DP or _G.DynamicProfiles or {}

local LDB = LibStub and LibStub("LibDataBroker-1.1", true)
local dataObject

local DEFAULT_TEXT_FORMAT = "%profile%"
local SHORT_NAME = "DP"
local FULL_NAME = "Dynamic Profiles"
local ICON = "Interface\\AddOns\\DynamicProfiles\\DynamicProfiles_broker.png"
local ICON_INLINE = "|T" .. ICON .. ":16:16:0:0|t"

local function GetBrokerDB()
    local db = DP.GetDB and DP.GetDB() or DynamicProfilesDB
    if not db then return nil end
    db.broker = db.broker or {}
    if type(db.broker.textFormat) ~= "string" or db.broker.textFormat == "" then
        db.broker.textFormat = DEFAULT_TEXT_FORMAT
    end
    return db.broker
end

function DP.GetActiveProfileLabel()
    if not DP.ResolveActiveProfile then return "Dynamic Profiles" end
    local profile, mode = DP.ResolveActiveProfile()
    if mode == "manual" and profile then
        return profile.name or "Profile"
    elseif mode == "auto" and profile then
        return "Auto: " .. (profile.name or "Profile")
    end
    return "Auto"
end

function DP.GetBrokerTextFormat()
    local broker = GetBrokerDB()
    return (broker and broker.textFormat) or DEFAULT_TEXT_FORMAT
end

function DP.GetDefaultBrokerTextFormat()
    return DEFAULT_TEXT_FORMAT
end

function DP.GetBrokerIconPath()
    return ICON
end

--- Expand a format string with broker tokens.
--- @param format string|nil format string; nil uses saved format
function DP.FormatBrokerText(format)
    local text = format
    if type(text) ~= "string" then
        text = DP.GetBrokerTextFormat()
    end
    local profile = DP.GetActiveProfileLabel() or ""
    -- Function-based gsub so profile names containing % are safe.
    text = string.gsub(text, "%%profile%%", function() return profile end)
    text = string.gsub(text, "%%icon%%", function() return ICON_INLINE end)
    text = string.gsub(text, "%%shortname%%", function() return SHORT_NAME end)
    text = string.gsub(text, "%%fullname%%", function() return FULL_NAME end)
    return text
end

function DP.SetBrokerTextFormat(format)
    local broker = GetBrokerDB()
    if not broker then return end
    if type(format) ~= "string" or format == "" then
        format = DEFAULT_TEXT_FORMAT
    end
    broker.textFormat = format
    DP.UpdateBroker()
end

function DP.ResetBrokerTextFormat()
    DP.SetBrokerTextFormat(DEFAULT_TEXT_FORMAT)
end

function DP.UpdateBroker()
    if not dataObject then return end
    local reloadIndicator = DP.GetReloadIndicator and DP.GetReloadIndicator() or ""
    dataObject.text = DP.FormatBrokerText() .. reloadIndicator
    dataObject.icon = ICON
end

local function ShowProfileMenu(owner)
    if not MenuUtil or not MenuUtil.CreateContextMenu then return end
    MenuUtil.CreateContextMenu(owner, function(_, rootDescription)
        local activeID = DP.GetActiveProfileID and DP.GetActiveProfileID()

        rootDescription:CreateTitle("Dynamic Profiles")
        rootDescription:CreateRadio(
            "Auto (by resolution)",
            function() return activeID == nil end,
            function()
                if DP.SelectAutoMode then DP.SelectAutoMode(true) end
            end
        )

        for _, profile in ipairs(DP.GetSortedProfiles and DP.GetSortedProfiles() or {}) do
            local id = profile.id
            local label = profile.name or id
            rootDescription:CreateRadio(
                label,
                function() return activeID == id end,
                function()
                    if DP.SelectProfile then DP.SelectProfile(id, true) end
                end
            )
        end
    end)
end

local function OnClick(brokerFrame, button)
    if button == "RightButton" then
        if DP.OpenProfilesCategory then
            DP.OpenProfilesCategory()
        end
    elseif button == "MiddleButton" then
        if DP.ExecuteReload then
            DP.ExecuteReload()
        end
    else
        ShowProfileMenu(brokerFrame)
    end
end

local function OnTooltipShow(tooltip)
    if not tooltip or not tooltip.AddLine then return end
    tooltip:AddLine("Dynamic Profiles", 1, 1, 1)
    if DP.AddPendingReloadTooltip then
        DP.AddPendingReloadTooltip(tooltip)
    end
    tooltip:AddLine("Left-click to choose a profile.", 0.8, 0.8, 0.8, true)
    tooltip:AddLine("Right-click to open Profile settings.", 0.8, 0.8, 0.8, true)
    tooltip:AddLine("Middle-click to reload UI.", 0.8, 0.8, 0.8, true)
end

local function GetAddonVersion()
    if C_AddOns and C_AddOns.GetAddOnMetadata then
        return C_AddOns.GetAddOnMetadata(addonName, "Version")
    elseif GetAddOnMetadata then
        return GetAddOnMetadata(addonName, "Version")
    end
    return nil
end

local function InitBroker()
    if dataObject or not LDB then return end
    -- Note: intentionally NO `tocname`. Bazooka renders the dropdown title as
    -- "name[addonTitle]" when tocname is set, which duplicates to
    -- "Dynamic Profiles[Dynamic Profiles]". Category/label/version below give
    -- Titan what it needs without relying on tocname.
    dataObject = LDB:NewDataObject("Dynamic Profiles", {
        type = "data source",
        text = DP.FormatBrokerText(),
        label = "Dynamic Profiles",
        icon = ICON,
        category = "Interface",
        version = GetAddonVersion(),
        OnClick = OnClick,
        OnTooltipShow = OnTooltipShow,
    })
    DP.UpdateBroker()
end

InitBroker()
