-- PHMenu: root controller for the Pasture & Herding standalone tabbed menu.
-- Opened via the PH_OPEN_MENU input action (default Ctrl+P). Two tabs:
-- Settings (global mod config) and Grazing (per-barn state + actions).
--
-- Lifecycle:
--   1. install() — call once at mod load. Hooks player input registration so
--      our keybind callback exists for both on-foot and in-vehicle contexts.
--      Also hooks Mission00.loadMapFinished so setupGui() runs after the GUI
--      manager is fully constructed.
--   2. setupGui()  — load child-frame XMLs first, then this menu's XML.
--   3. addPlayerActionEvents() — register the keybind -> PHMenu.open callback.
--   4. open() / onButtonBack() / onClose() — standard TabbedMenu lifecycle.

PHMenu = PHMenu or {}
local PHMenu_mt = Class(PHMenu, TabbedMenu)

PHMenu.ACTION_NAME = "PH_OPEN_MENU"
PHMenu._installed = false
PHMenu._guiReady = false

local modDirectory = g_currentModDirectory

function PHMenu.new(target, custom_mt)
    local self = TabbedMenu.new(target, custom_mt or PHMenu_mt)
    self.isOpen = false
    return self
end

function PHMenu.setupGui()
    if g_gui == nil then
        PastureHerdingLog.warning("[PHMenu] setupGui: g_gui is nil; deferring")
        return
    end
    PHMenuSettingsFrame.setupGui()
    PHMenuGrazingFrame.setupGui()
    PHMenuNotificationsFrame.setupGui()
    PHMenuInfoFrame.setupGui()
    PHMenuMapFrame.setupGui()

    g_phMenu = PHMenu.new()
    local xmlPath = Utils.getFilename("gui/PHMenu.xml", modDirectory)
    g_gui:loadGui(xmlPath, "PHMenu", g_phMenu, false)
    PHMenu._guiReady = true
    PastureHerdingLog.dev("[PHMenu] setupGui complete")
end

function PHMenu:onGuiSetupFinished()
    PHMenu:superClass().onGuiSetupFinished(self)
    self:setupMenuPages()
end

function PHMenu:setupMenuPages()
    local basePredicate = function() return g_currentMission ~= nil end

    self:registerPage(self.grazingFrame, 1, basePredicate)
    self:addPageTab(self.grazingFrame, nil, nil, "gui.icon_ingameMenu_animals")
    if self.grazingFrame and self.grazingFrame.initialize then self.grazingFrame:initialize() end

    -- Map tab (the visual setup menu) sits where the old Setup tab was — it now
    -- does everything the Setup tab did (register / remove / rename / paths /
    -- move herd / etc.), so the Setup tab is retired.
    if self.mapFrame ~= nil then
        self:registerPage(self.mapFrame, 2, basePredicate)
        self:addPageTab(self.mapFrame, nil, nil, "gui.icon_ingameMenu_map")
        if self.mapFrame.initialize then self.mapFrame:initialize() end
    else
        PastureHerdingLog.warning("[PHMap] setupMenuPages: mapFrame NOT bound — FrameReference failed; tab skipped")
    end

    self:registerPage(self.settingsFrame, 3, basePredicate)
    self:addPageTab(self.settingsFrame, nil, nil, "gui.icon_options_generalSettings")
    if self.settingsFrame and self.settingsFrame.initialize then self.settingsFrame:initialize() end

    self:registerPage(self.notifFrame, 4, basePredicate)
    self:addPageTab(self.notifFrame, nil, nil, "gui.icon_ingameMenu_calendar")
    if self.notifFrame and self.notifFrame.initialize then self.notifFrame:initialize() end

    self:registerPage(self.infoFrame, 5, basePredicate)
    self:addPageTab(self.infoFrame, nil, nil, "gui.icon_options_help")
    if self.infoFrame and self.infoFrame.initialize then self.infoFrame:initialize() end
end

function PHMenu:setupMenuButtonInfo()
    PHMenu:superClass().setupMenuButtonInfo(self)
    self.clickBackCallback = self:makeSelfCallback(self.onButtonBack)
    self.backButtonInfo = {
        inputAction = InputAction.MENU_BACK,
        text = g_i18n:getText("button_back"),
        callback = self.clickBackCallback,
    }
    self.defaultMenuButtonInfo = { self.backButtonInfo }
    self.defaultMenuButtonInfoByActions[InputAction.MENU_BACK] = self.backButtonInfo
    self.defaultButtonActionCallbacks = {
        [InputAction.MENU_BACK] = self.clickBackCallback,
    }
end

function PHMenu:onButtonBack()
    self:exitMenu()
end

function PHMenu:onClose()
    PHMenu:superClass().onClose(self)
    self.isOpen = false
end

function PHMenu:onOpen()
    PHMenu:superClass().onOpen(self)
    self.isOpen = true
    -- First time the menu is opened on this save, fire the startup-alert
    -- dialog. _maybeShowStartupAlert short-circuits after the player acks
    -- it (persisted as framework.startupAlertAcked), so opening the menu
    -- again is a no-op.
    local f = rawget(_G, "g_pastureHerding")
    if f ~= nil and type(f._maybeShowStartupAlert) == "function" then
        pcall(function() f:_maybeShowStartupAlert() end)
    end
    -- If a walk-path recording is in progress, jump straight to the Map tab so
    -- the player can just click Finish (the map frame auto-opens the recording
    -- pasture's popup in onFrameOpen).
    if f ~= nil and type(f.isRecordingPath) == "function" and f:isRecordingPath()
       and self.mapFrame ~= nil and type(self.goToPage) == "function" then
        pcall(function() self:goToPage(self.mapFrame, true) end)
    end
end

-- Static open() — wired to the keybind callback.
function PHMenu.open()
    if not PHMenu._guiReady or g_phMenu == nil then
        PastureHerdingLog.warning("[PHMenu] open(): GUI not ready yet")
        return
    end
    if g_gui ~= nil then
        g_gui:showGui("PHMenu")
    end
end

local function onOpenPressedCallback(_, _, _, _, _)
    PastureHerdingLog.dev("[PHMenu] PH_OPEN_MENU pressed")
    PHMenu.open()
end

function PHMenu.addPlayerActionEvents()
    if g_inputBinding == nil then return end
    local triggerUp, triggerDown, triggerAlways = false, true, false
    local startActive, callbackState, disableConflicting = true, nil, true
    local ok, eventId = g_inputBinding:registerActionEvent(
        PHMenu.ACTION_NAME,
        PHMenu,
        onOpenPressedCallback,
        triggerUp, triggerDown, triggerAlways,
        startActive, callbackState, disableConflicting
    )
    if ok then
        g_inputBinding:setActionEventTextVisibility(eventId, false)
        PastureHerdingLog.dev("[PHMenu] action %s registered, eventId=%s",
            PHMenu.ACTION_NAME, tostring(eventId))
    else
        PastureHerdingLog.dev("[PHMenu] action %s NOT registered (eventId=%s); benign double-call",
            PHMenu.ACTION_NAME, tostring(eventId))
    end
end

function PHMenu.install()
    if PHMenu._installed then return end
    PHMenu._installed = true
    if PlayerInputComponent ~= nil
       and type(PlayerInputComponent.registerGlobalPlayerActionEvents) == "function" then
        PlayerInputComponent.registerGlobalPlayerActionEvents = Utils.appendedFunction(
            PlayerInputComponent.registerGlobalPlayerActionEvents,
            PHMenu.addPlayerActionEvents
        )
    else
        PastureHerdingLog.warning("[PHMenu] PlayerInputComponent.registerGlobalPlayerActionEvents missing; keybind will not work")
    end
    if Mission00 ~= nil and Mission00.loadMapFinished ~= nil then
        Mission00.loadMapFinished = Utils.appendedFunction(
            Mission00.loadMapFinished,
            function() PHMenu.setupGui() end
        )
    else
        PastureHerdingLog.warning("[PHMenu] Mission00.loadMapFinished missing; menu GUI will not load")
    end
    PastureHerdingLog.dev("[PHMenu] installed (PlayerInputComponent + loadMapFinished hooks)")
end
