-- Adds a right-click Modern Status submenu to the vanilla Health sidebar button.
-- The submenu provides quick access to global settings without relying on the old blue gear button.

require "MS/SettingPanel/MS_GlobalSettingsPanel"
require "MS/SettingPanel/MS_PresetsPanel"
require "MS/MS_PerformanceManager"

local function MS_tr(key, fallback)
    if key and getTextOrNull then
        local value = getTextOrNull(key)
        if value and value ~= key then return value end
    end
    if key and getText then
        local ok, value = pcall(getText, key)
        if ok and value and value ~= key then return value end
    end
    return fallback or tostring(key or "")
end

local function MS_contextSetChecked(context, option, checked)
    if context and context.setOptionChecked and option then
        context:setOptionChecked(option, checked == true)
    end
end

local function MS_getPlayerNum(panel)
    if panel and panel.chr and panel.chr.getPlayerNum then
        return panel.chr:getPlayerNum()
    end
    if panel and panel.playerNum ~= nil then
        return panel.playerNum
    end
    return 0
end

local function MS_getGlobalControl(playerNum)
    return StatusWidget and StatusWidget.globalControls and StatusWidget.globalControls[playerNum] or nil
end

local function MS_isPresetsPanelOpen()
    local panel = MS_PresetsPanel and MS_PresetsPanel.CurrentPanel
    return panel ~= nil and panel.getIsVisible and panel:getIsVisible() == true
end

local function MS_openGlobalSettings(playerNum)
    local x = math.floor(getMouseX() + 12)
    local y = math.floor(getMouseY() + 12)
    MS_GlobalSettingsPanel.openForPlayer(playerNum, x, y)
end

local function MS_openPresets(playerNum)
    if MS_PresetsPanel and MS_PresetsPanel.openForPlayer then
        local x = math.floor(getMouseX() + 12)
        local y = math.floor(getMouseY() + 12)
        MS_PresetsPanel.openForPlayer(playerNum, x, y)
    end
end

local function MS_isMultiDragEnabled(playerNum)
    local config = MSConfig and MSConfig.getGlobalConfig and MSConfig.getGlobalConfig(playerNum) or {}
    return config and config.multiDragMode == true
end

local function MS_toggleMultiDrag(playerNum)
    if not MSConfig or not MSConfig.updateGlobalConfig then return end
    MSConfig.updateGlobalConfig(playerNum, "multiDragMode", not MS_isMultiDragEnabled(playerNum))
end

local function MS_setPerformanceMode(playerNum, mode)
    if MS_PerformanceManager and MS_PerformanceManager.setMode then
        MS_PerformanceManager.setMode(playerNum, mode)
    end
end

local function MS_getPerformanceMode(playerNum)
    if MS_PerformanceManager and MS_PerformanceManager.getCurrentMode then
        return MS_PerformanceManager.getCurrentMode(playerNum)
    end
    return "balanced"
end

local function MS_areVanillaMoodlesHidden(playerNum)
    local config = MSConfig and MSConfig.getGlobalConfig and MSConfig.getGlobalConfig(playerNum) or {}
    return config and (config.hideOriginalMoodles == true or config.hideVanillaMoodles == true or config.hideOriginalMoodle == true)
end

local function MS_toggleHideVanillaMoodles(playerNum)
    if not MSConfig or not MSConfig.updateGlobalConfig then return end

    local newValue = not MS_areVanillaMoodlesHidden(playerNum)
    MSConfig.updateGlobalConfig(playerNum, "hideOriginalMoodles", newValue)
    MSConfig.updateGlobalConfig(playerNum, "hideVanillaMoodles", newValue)

    local control = MS_getGlobalControl(playerNum)
    if control and control.applyHideOriginalMoodles then
        control:applyHideOriginalMoodles(newValue)
    end
    if StatusWidget and StatusWidget.pendingMoodleVisibility then
        StatusWidget.pendingMoodleVisibility[playerNum] = { control = control, shouldHide = newValue, ticks = 180 }
    end
end

local function MS_addOptionChecked(context, label, target, callback, checked)
    local option = context:addOption(label, target, callback)
    MS_contextSetChecked(context, option, checked)
    return option
end

local function MS_addModernStatusPerformanceSubMenu(parentContext, parentOption, playerNum)
    local submenu = parentContext:getNew(parentContext)
    parentContext:addSubMenu(parentOption, submenu)

    local currentMode = MS_getPerformanceMode(playerNum)
    local modes = { "responsive", "balanced", "lightweight", "custom" }
    for _, mode in ipairs(modes) do
        local label
        if MS_PerformanceManager and MS_PerformanceManager.getModeLabel then
            label = MS_PerformanceManager.getModeLabel(mode)
        else
            label = mode
        end
        MS_addOptionChecked(submenu, label, nil, function()
            MS_setPerformanceMode(playerNum, mode)
        end, currentMode == mode)
    end
end

local function MS_showGlobalSettingsHealthButtonContext(panel)
    if not panel then return true end
    if not (ISContextMenu and ISContextMenu.get) then return true end

    local playerNum = MS_getPlayerNum(panel)
    local context = ISContextMenu.get(playerNum, getMouseX(), getMouseY())
    if not context then return true end

    local rootOption = context:addOption(MS_tr("IGUI_ModernStatus_ModName", "Modern Status"), nil, nil)
    local rootMenu = context:getNew(context)
    context:addSubMenu(rootOption, rootMenu)

    MS_addOptionChecked(rootMenu, "Global Settings", nil, function()
        MS_openGlobalSettings(playerNum)
    end, MS_GlobalSettingsPanel and MS_GlobalSettingsPanel.isOpen and MS_GlobalSettingsPanel.isOpen())

    MS_addOptionChecked(rootMenu, MS_tr("IGUI_ModernStatus_Presets", "Presets"), nil, function()
        MS_openPresets(playerNum)
    end, MS_isPresetsPanelOpen())

    MS_addOptionChecked(rootMenu, MS_tr("IGUI_ModernStatus_MultiDrag", "Multi Drag"), nil, function()
        MS_toggleMultiDrag(playerNum)
    end, MS_isMultiDragEnabled(playerNum))

    local performanceOption = rootMenu:addOption("Performance", nil, nil)
    MS_addModernStatusPerformanceSubMenu(rootMenu, performanceOption, playerNum)

    MS_addOptionChecked(rootMenu, MS_tr("IGUI_ModernStatus_HideVanillaMoodles", "Hide Vanilla Moodles"), nil, function()
        MS_toggleHideVanillaMoodles(playerNum)
    end, MS_areVanillaMoodlesHidden(playerNum))

    return true
end

local function MS_attachHealthButtonContext(panel)
    if not panel then return end
    local button = panel.healthBtn
    if not button or button._ModernStatus_GlobalSettingsCtxHooked then return end

    button._ModernStatus_GlobalSettingsCtxHooked = true
    local oldRightDown = button.onRightMouseDown
    local oldRightUp = button.onRightMouseUp
    local oldRightUpOutside = button.onRightMouseUpOutside

    button.onRightMouseDown = function(_self, _x, _y)
        if oldRightDown then oldRightDown(_self, _x, _y) end
        return true
    end

    button.onRightMouseUp = function(_self, _x, _y)
        if oldRightUp then oldRightUp(_self, _x, _y) end
        return MS_showGlobalSettingsHealthButtonContext(panel)
    end

    button.onRightMouseUpOutside = function(_self, _x, _y)
        if oldRightUpOutside then return oldRightUpOutside(_self, _x, _y) end
        return false
    end
end

local function MS_patchISEquippedItemInitialise()
    if not ISEquippedItem or ISEquippedItem._ModernStatus_GlobalSettingsHealthInitWrapped then return end

    ISEquippedItem._ModernStatus_GlobalSettingsHealthInitWrapped = true
    local oldInitialise = ISEquippedItem.initialise

    function ISEquippedItem:initialise(...)
        if oldInitialise then oldInitialise(self, ...) end
        MS_attachHealthButtonContext(self)
    end
end

local function MS_tryHookExistingEquippedPanel()
    if ISEquippedItem and ISEquippedItem.instance then
        MS_attachHealthButtonContext(ISEquippedItem.instance)
    end
end

local function MS_bootstrapHealthButtonContext()
    if _G.ModernStatus_GlobalSettingsHealthBootstrapRunning then return end
    _G.ModernStatus_GlobalSettingsHealthBootstrapRunning = true

    local function tickFn()
        if not ISEquippedItem then return end

        MS_patchISEquippedItemInitialise()
        MS_tryHookExistingEquippedPanel()

        local instance = ISEquippedItem.instance
        if instance and instance.healthBtn and instance.healthBtn._ModernStatus_GlobalSettingsCtxHooked then
            Events.OnTick.Remove(tickFn)
            _G.ModernStatus_GlobalSettingsHealthBootstrapRunning = false
        end
    end

    Events.OnTick.Add(tickFn)
end

if Events and Events.OnGameBoot then Events.OnGameBoot.Add(MS_bootstrapHealthButtonContext) end
if Events and Events.OnGameStart then Events.OnGameStart.Add(MS_bootstrapHealthButtonContext) end
if Events and Events.OnTick then MS_bootstrapHealthButtonContext() end

return true
