require "MS/SettingPanel/MS_SquareButton"

MS_TitlePanelButtons = MS_TitlePanelButtons or {}

local ACTIVE_GREEN = { r = 0.12, g = 0.75, b = 0.25 }

local PANEL_DEFS = {
    all = {
        className = "MS_AllIndicatorsPanel",
        requirePath = "MS/SettingPanel/MS_AllIndicatorsPanel",
        iconPath = "media/ui/ModernStatus/ICON/ALL.png",
        tooltipKey = "IGUI_ModernStatus_OpenAllSettings"
    },
    matrix = {
        className = "MS_MatrixStylePanel",
        requirePath = "MS/SettingPanel/MS_MatrixStylePanel",
        iconPath = "media/ui/ModernStatus/ICON/Icon_Matrix.png",
        tooltipKey = "IGUI_ModernStatus_OpenMatrixSettings"
    },
    unlinked = {
        className = "MS_UnlinkedStylePanel",
        requirePath = "MS/SettingPanel/MS_UnlinkedStylePanel",
        iconPath = "media/ui/ModernStatus/ICON/Icon_Independent.png",
        tooltipKey = "IGUI_ModernStatus_OpenUnlinkedSettings"
    }
}

local function getGlobalByName(name)
    return _G and _G[name] or nil
end

local function getPanelClass(panelType)
    local def = PANEL_DEFS[panelType]
    if not def then return nil end

    local class = getGlobalByName(def.className)
    if not class and def.requirePath then
        require(def.requirePath)
        class = getGlobalByName(def.className)
    end
    return class
end

local function isVisible(panel)
    if not panel then return false end
    if panel.getIsVisible then
        return panel:getIsVisible()
    end
    if panel.isVisible then
        return panel:isVisible()
    end
    return true
end

local function getSourcePlayerIndex(sourcePanel)
    if not sourcePanel then return 0 end
    if sourcePanel.playerIndex ~= nil then
        return sourcePanel.playerIndex
    end
    if sourcePanel.indicator and sourcePanel.indicator.playerIndex ~= nil then
        return sourcePanel.indicator.playerIndex
    end
    return 0
end

local function getCenteredAnchor(class, playerIndex)
    local screenWidth = getCore():getScreenWidth()
    local screenHeight = getCore():getScreenHeight()
    local width, height = 420, 420

    -- Prefer the panel's own sizing helper so buttons open the same panel size as the context menu.
    if class and class.calculateRequiredSize then
        local size = class.calculateRequiredSize()
        width = size and size.width or width
        height = size and size.height or height
    elseif class and class.calculateRequiredWidth and class.calculateRequiredHeight then
        width = class.calculateRequiredWidth()
        height = class.calculateRequiredHeight(playerIndex or 0)
    end

    return math.floor((screenWidth - width) / 2), math.floor((screenHeight - height) / 2)
end

local function createAllIndicatorsPanel(class, playerIndex, anchorX, anchorY)
    if not class or not class.new then return nil end

    local screenWidth = getCore():getScreenWidth()
    local screenHeight = getCore():getScreenHeight()
    local panel = class:new(anchorX or 100, anchorY or 100, nil, nil, playerIndex)
    panel:initialise()
    panel:addToUIManager()
    panel:setVisible(true)

    local x = anchorX or math.floor((screenWidth - panel:getWidth()) / 2)
    local y = anchorY or math.floor((screenHeight - panel:getHeight()) / 2)
    panel:setX(math.max(10, math.min(screenWidth - panel:getWidth() - 10, x)))
    panel:setY(math.max(10, math.min(screenHeight - panel:getHeight() - 10, y)))

    class.CurrentPanel = panel
    return panel
end

function MS_TitlePanelButtons.isPanelOpen(panelType)
    local class = getPanelClass(panelType)
    return class and isVisible(class.CurrentPanel) or false
end

function MS_TitlePanelButtons.openPanel(sourcePanel, panelType)
    local class = getPanelClass(panelType)
    if not class then return nil end

    local playerIndex = getSourcePlayerIndex(sourcePanel)

    if class.openForPlayer then
        return class.openForPlayer(playerIndex)
    end

    -- MS_AllIndicatorsPanel in older local copies may not have openForPlayer; keep a safe fallback.
    if panelType == "all" then
        local anchorX, anchorY = getCenteredAnchor(class, playerIndex)
        return createAllIndicatorsPanel(class, playerIndex, anchorX, anchorY)
    end

    return nil
end

function MS_TitlePanelButtons.togglePanel(sourcePanel, panelType)
    local class = getPanelClass(panelType)
    if not class then return end

    if isVisible(class.CurrentPanel) and class.CurrentPanel.close then
        class.CurrentPanel:close()
        return
    end

    MS_TitlePanelButtons.openPanel(sourcePanel, panelType)
end

function MS_TitlePanelButtons.onPanelButtonClick(sourcePanel, button, panelType)
    MS_TitlePanelButtons.togglePanel(sourcePanel, panelType)
end

function MS_TitlePanelButtons.addButtons(panel, orderedTypes, buttonSize)
    if not panel or not orderedTypes or #orderedTypes == 0 then return end
    if not panel.closeButton then return end

    panel.msTitleBarButtons = panel.msTitleBarButtons or {}

    local size = buttonSize or FONT_HGT_SMALL or 14
    local gap = math.max((panel.padding or 0) * 2, math.floor(size * 0.3))
    local closeX = panel.closeButton.getX and panel.closeButton:getX() or (panel.width - size - (panel.padding or 0))
    local y = ((panel.titleBarHeight or size) - size) / 2
    local totalWidth = #orderedTypes * size + (#orderedTypes - 1) * gap
    local startX = closeX - gap - totalWidth

    for index, panelType in ipairs(orderedTypes) do
        local def = PANEL_DEFS[panelType]
        if def then
            local targetType = panelType
            local tooltipKey = def.tooltipKey
            local iconPath = def.iconPath
            local button = MS_SquareButton:new(startX + (index - 1) * (size + gap), y, size, getTexture(iconPath), panel, MS_TitlePanelButtons.onPanelButtonClick)
            button:initialise()
            button.onClickArgs = { targetType }
            button:setIconSizeRatio(0.75)
            button:setActiveColor(ACTIVE_GREEN.r, ACTIVE_GREEN.g, ACTIVE_GREEN.b)
            if button.setTooltip and tooltipKey then
                button:setTooltip(getText(tooltipKey))
            end
            button.prerender = function(control)
                control:setActive(MS_TitlePanelButtons.isPanelOpen(targetType))
                control:setActiveColor(ACTIVE_GREEN.r, ACTIVE_GREEN.g, ACTIVE_GREEN.b)
                if control.setTooltip and tooltipKey then
                    control:setTooltip(getText(tooltipKey))
                end
            end
            panel:addChild(button)
            table.insert(panel.msTitleBarButtons, button)
        end
    end
end

return MS_TitlePanelButtons
