local _, ns = ...

local L = ns.L or {}
local addonName = ns.ADDON_NAME
local addonFrame = ns.frame
local PREY_WIDGET_ID = 7663

local function isVaultloomUIShown()
    return ns and ns.UI and ns.UI.frame and ns.UI.frame:IsShown()
end

local function isCustomTaskTrackerShown()
    if not (ns and ns.GetCustomTaskTrackerSettings) then
        return false
    end

    local settings = ns:GetCustomTaskTrackerSettings()
    return type(settings) == "table" and settings.shown == true
end

local function shouldRefreshVisibleTaskData()
    return isVaultloomUIShown() or isCustomTaskTrackerShown()
end

local function getWidgetID(arg)
    if type(arg) == "table" then
        return tonumber(arg.widgetID)
    end

    return tonumber(arg)
end

local function refreshCurrentMoneySnapshot(allowZero, refreshUI)
    if ns.RefreshCurrentCharacterMoneySnapshot then
        ns:RefreshCurrentCharacterMoneySnapshot(allowZero == true)
    end
    if refreshUI == true and isVaultloomUIShown() and ns.UI and ns.UI.Refresh then
        ns.UI:Refresh()
    end
end

local function queueCurrentMoneySnapshot(delay, allowZero)
    if not C_Timer or type(C_Timer.After) ~= "function" then
        return
    end
    C_Timer.After(tonumber(delay) or 0.5, function()
        refreshCurrentMoneySnapshot(allowZero == true, true)
    end)
end

addonFrame:SetScript("OnEvent", function(_, event, ...)
    if event == "ADDON_LOADED" then
        local loadedName = ...
        if loadedName ~= addonName then
            return
        end

        local ok, err = pcall(function()
            if ns.RegisterSlashCommands then
                ns:RegisterSlashCommands()
            end

            ns:EnsureDB()
            refreshCurrentMoneySnapshot(false, false)
            queueCurrentMoneySnapshot(0.75, false)
            queueCurrentMoneySnapshot(3.00, false)
            queueCurrentMoneySnapshot(8.00, false)
            ns:MarkCurrentCharacterProfessionsDirty()

            if ns.ApplyFeatureStates then
                local featureOk, featureErr = pcall(function()
                    ns:ApplyFeatureStates()
                end)
                if not featureOk then
                    ns:Print("Vaultloom feature init failed: " .. tostring(featureErr))
                end
            end

            if ns.InitializeBroker then
                local brokerOk, brokerErr = pcall(function()
                    ns:InitializeBroker()
                end)
                if not brokerOk then
                    ns:Print("Vaultloom broker init failed: " .. tostring(brokerErr))
                end
            end

            C_Timer.After(0, function()
                if ns.UI and ns.UI.EnsureMinimapButton then
                    local minimapOk, minimapErr = pcall(function()
                        ns.UI:EnsureMinimapButton()
                        if ns.UI.RefreshMinimapButton then
                            ns.UI:RefreshMinimapButton()
                        end
                    end)
                    if not minimapOk then
                        ns:Print("Vaultloom minimap init failed: " .. tostring(minimapErr))
                    end
                end
            end)

            addonFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
            addonFrame:RegisterEvent("PLAYER_LOGOUT")
            addonFrame:RegisterEvent("WEEKLY_REWARDS_UPDATE")
            addonFrame:RegisterEvent("CHALLENGE_MODE_MAPS_UPDATE")
            addonFrame:RegisterEvent("QUEST_LOG_UPDATE")
            addonFrame:RegisterEvent("CALENDAR_UPDATE_EVENT_LIST")
            addonFrame:RegisterEvent("QUEST_TURNED_IN")
            addonFrame:RegisterEvent("QUEST_ACCEPTED")
            addonFrame:RegisterEvent("GOSSIP_SHOW")
            addonFrame:RegisterEvent("CURRENCY_DISPLAY_UPDATE")
            addonFrame:RegisterEvent("AREA_POIS_UPDATED")
            addonFrame:RegisterEvent("MAJOR_FACTION_RENOWN_LEVEL_CHANGED")
            addonFrame:RegisterEvent("NEIGHBORHOOD_INITIATIVE_UPDATED")
            addonFrame:RegisterEvent("INITIATIVE_TASKS_TRACKED_UPDATED")
            addonFrame:RegisterEvent("INITIATIVE_TASKS_TRACKED_LIST_CHANGED")
            addonFrame:RegisterEvent("INITIATIVE_TASK_COMPLETED")
            addonFrame:RegisterEvent("INITIATIVE_COMPLETED")
            addonFrame:RegisterEvent("SKILL_LINES_CHANGED")
            addonFrame:RegisterEvent("BAG_UPDATE_DELAYED")
            addonFrame:RegisterEvent("PLAYER_MONEY")
            addonFrame:RegisterEvent("UPDATE_UI_WIDGET")
            addonFrame:RegisterEvent("UPDATE_ALL_UI_WIDGETS")
            addonFrame:RegisterEvent("TRAIT_TREE_CURRENCY_INFO_UPDATED")
            addonFrame:RegisterEvent("TRAIT_CONFIG_UPDATED")
            addonFrame:RegisterEvent("TRADE_SKILL_SHOW")
            addonFrame:RegisterEvent("TRADE_SKILL_LIST_UPDATE")
            ns:SetLiveRefreshEventsEnabled(false)

            ns.newsPromptPending = ns.db
                and ns.db.ui
                and ns.GetNewsCurrentVersion
                and ns.db.ui.newsSeenVersion ~= ns:GetNewsCurrentVersion()
                or false

            ns:Print(string.format(
                L.ADDON_LOADED_MESSAGE or "Vaultloom %s - open Vaultloom with /vl. For the latest updates, check Options > Changelog.",
                ns.VERSION or "Vaultloom"
            ))
        end)
        if not ok then
            ns:Print("Vaultloom startup failed: " .. tostring(err))
        end
    elseif event == "PLAYER_HOUSE_LIST_UPDATED" then
        ns:RememberHousingHouseList(...)
        if ns.UI
            and ns.UI.CaptureCurrentHousingSnapshot
            and ns.UI.IsHousingViewActive
            and ns.UI:IsHousingViewActive()
        then
            ns.UI:CaptureCurrentHousingSnapshot()
        end
    elseif event == "HOUSE_LEVEL_FAVOR_UPDATED" then
        ns:RememberHousingLevelFavor(...)
        if ns.UI
            and ns.UI.CaptureCurrentHousingSnapshot
            and ns.UI.IsHousingViewActive
            and ns.UI:IsHousingViewActive()
        then
            ns.UI:CaptureCurrentHousingSnapshot()
        end
    elseif event == "PLAYER_LOGOUT" then
        ns.isPlayerLoggingOut = true
        if ns.DiscardDeferredLiveRefresh then
            ns:DiscardDeferredLiveRefresh()
        end
        if ns.MarkCurrentCharacterProfessionKnowledgeDirty then
            ns:MarkCurrentCharacterProfessionKnowledgeDirty()
        end
        refreshCurrentMoneySnapshot(false, false)
        if ns.RefreshCurrentCharacterLiveData and ns.BuildLiveRefreshSpec then
            ns:RefreshCurrentCharacterLiveData(ns:BuildLiveRefreshSpec(
                "vault",
                "utility"
            ), true)
        else
            ns:RefreshCurrentCharacterVaultData()
        end
    elseif event == "PLAYER_ENTERING_WORLD"
        or event == "WEEKLY_REWARDS_UPDATE"
        or event == "CHALLENGE_MODE_MAPS_UPDATE"
        or event == "MYTHIC_PLUS_CURRENT_AFFIX_UPDATE"
        or event == "HOUSE_LEVEL_CHANGED"
        or event == "NEIGHBORHOOD_INITIATIVE_UPDATED"
        or event == "INITIATIVE_TASKS_TRACKED_UPDATED"
        or event == "INITIATIVE_TASKS_TRACKED_LIST_CHANGED"
        or event == "INITIATIVE_TASK_COMPLETED"
        or event == "INITIATIVE_COMPLETED"
        or event == "QUEST_LOG_UPDATE"
        or event == "CALENDAR_UPDATE_EVENT_LIST"
        or event == "QUEST_TURNED_IN"
        or event == "QUEST_ACCEPTED"
        or event == "CURRENCY_DISPLAY_UPDATE"
        or event == "AREA_POIS_UPDATED"
        or event == "MAJOR_FACTION_RENOWN_LEVEL_CHANGED"
        or event == "SKILL_LINES_CHANGED"
        or event == "BAG_UPDATE_DELAYED"
        or event == "PLAYER_MONEY"
        or event == "UPDATE_UI_WIDGET"
        or event == "UPDATE_ALL_UI_WIDGETS"
        or event == "TRAIT_TREE_CURRENCY_INFO_UPDATED"
        or event == "TRAIT_CONFIG_UPDATED"
        or event == "TRADE_SKILL_SHOW"
        or event == "TRADE_SKILL_LIST_UPDATE" then
        if ns.isPlayerLoggingOut == true then
            return
        end

        local refreshSpec
        if event == "PLAYER_ENTERING_WORLD" then
            refreshCurrentMoneySnapshot(false, true)
            queueCurrentMoneySnapshot(0.75, false)
            queueCurrentMoneySnapshot(3.00, false)
            queueCurrentMoneySnapshot(8.00, false)
        elseif event == "PLAYER_MONEY" then
            refreshCurrentMoneySnapshot(true, true)
        end
        if event == "PLAYER_ENTERING_WORLD" or event == "SKILL_LINES_CHANGED" then
            ns:MarkCurrentCharacterProfessionsDirty()
        end
        if (event == "CURRENCY_DISPLAY_UPDATE"
            or event == "TRAIT_TREE_CURRENCY_INFO_UPDATED"
            or event == "TRAIT_CONFIG_UPDATED")
            and ns.MarkCurrentCharacterProfessionKnowledgeDirty
        then
            ns:MarkCurrentCharacterProfessionKnowledgeDirty()
        end
        if event == "PLAYER_ENTERING_WORLD" and ns.PrimeMidnightRareQuestCompletionCache then
            ns:PrimeMidnightRareQuestCompletionCache()
        end
        if event == "QUEST_LOG_UPDATE" and ns.QueueMidnightRareQuestLogProbe then
            ns:QueueMidnightRareQuestLogProbe()
        end
        if event == "PLAYER_ENTERING_WORLD" and ns.RequestDarkmoonFaireCalendarRefresh then
            ns:RequestDarkmoonFaireCalendarRefresh()
        end
        if event == "CALENDAR_UPDATE_EVENT_LIST" and ns.ClearDarkmoonFaireActiveCache then
            ns:ClearDarkmoonFaireActiveCache()
        end

        local refreshVisibleData = shouldRefreshVisibleTaskData()

        if event == "PLAYER_ENTERING_WORLD" then
            refreshSpec = ns:BuildLiveRefreshSpec("vault", "utility", "prey", "dailyPve", "delves", "worldWeekly", "darkmoonFaire", "pvpWeekly", "professionWeekly", "professionKnowledge", "professionCooldowns")
        elseif event == "WEEKLY_REWARDS_UPDATE" or event == "CHALLENGE_MODE_MAPS_UPDATE" then
            refreshSpec = ns:BuildLiveRefreshSpec("vault", "renownForce")
        elseif event == "QUEST_TURNED_IN" then
            local turnedInQuestID = select(1, ...)
            turnedInQuestID = tonumber(turnedInQuestID)
            if ns.RememberPreyQuestTurnIn then
                ns:RememberPreyQuestTurnIn(turnedInQuestID)
            end
            if ns.RememberDelveQuestTurnIn then
                ns:RememberDelveQuestTurnIn(turnedInQuestID)
            end
            if ns.IsMidnightRareQuestID and ns:IsMidnightRareQuestID(turnedInQuestID) then
                refreshSpec = ns:BuildLiveRefreshSpec("vault", "prey", "dailyPve", "midnightRares", "delves", "worldWeekly", "darkmoonFaire", "pvpWeekly", "professionWeekly", "renownForce")
            else
                refreshSpec = ns:BuildLiveRefreshSpec("vault", "prey", "dailyPve", "delves", "worldWeekly", "darkmoonFaire", "pvpWeekly", "professionWeekly", "renownForce")
            end
        elseif event == "QUEST_LOG_UPDATE" then
            refreshSpec = ns:BuildLiveRefreshSpec("vault", "prey", "dailyPve", "delves", "worldWeekly", "darkmoonFaire", "pvpWeekly", "professionWeekly")
        elseif event == "QUEST_ACCEPTED" then
            refreshSpec = ns:BuildLiveRefreshSpec("vault", "prey", "dailyPve", "delves", "worldWeekly", "darkmoonFaire", "pvpWeekly", "professionWeekly")
        elseif event == "CALENDAR_UPDATE_EVENT_LIST" then
            refreshSpec = ns:BuildLiveRefreshSpec("darkmoonFaire", "professionWeekly")
        elseif event == "CURRENCY_DISPLAY_UPDATE" then
            if refreshVisibleData then
                refreshSpec = ns:BuildLiveRefreshSpec("utility", "delves", "worldWeekly", "professionKnowledge", "professionCooldowns")
            else
                refreshSpec = ns:BuildLiveRefreshSpec("utility")
            end
        elseif event == "AREA_POIS_UPDATED" then
            if refreshVisibleData then
                refreshSpec = ns:BuildLiveRefreshSpec("dailyPve", "worldWeekly")
            end
        elseif event == "MAJOR_FACTION_RENOWN_LEVEL_CHANGED" then
            if refreshVisibleData then
                refreshSpec = ns:BuildLiveRefreshSpec("prey", "delves", "worldWeekly")
            end
        elseif event == "NEIGHBORHOOD_INITIATIVE_UPDATED"
            or event == "INITIATIVE_TASKS_TRACKED_UPDATED"
            or event == "INITIATIVE_TASKS_TRACKED_LIST_CHANGED"
            or event == "INITIATIVE_TASK_COMPLETED"
            or event == "INITIATIVE_COMPLETED" then
            if refreshVisibleData then
                refreshSpec = ns:BuildLiveRefreshSpec("renownForce")
            end
        elseif event == "SKILL_LINES_CHANGED" then
            if refreshVisibleData then
                refreshSpec = ns:BuildLiveRefreshSpec("professionWeekly", "professionKnowledge", "professionCooldowns")
            end
        elseif event == "BAG_UPDATE_DELAYED" then
            if refreshVisibleData then
                refreshSpec = ns:BuildLiveRefreshSpec("utility", "delves", "worldWeekly", "darkmoonFaire")
            else
                refreshSpec = ns:BuildLiveRefreshSpec("utility")
            end
        elseif event == "PLAYER_MONEY" then
            refreshSpec = ns:BuildLiveRefreshSpec("utility")
        elseif event == "UPDATE_UI_WIDGET" then
            local widgetID = getWidgetID(...)
            if widgetID == PREY_WIDGET_ID then
                if refreshVisibleData then
                    refreshSpec = ns:BuildLiveRefreshSpec("prey", "vault", "delves", "worldWeekly", "renownForce")
                else
                    refreshSpec = ns:BuildLiveRefreshSpec("prey")
                end
            elseif widgetID == nil then
                if refreshVisibleData then
                    refreshSpec = ns:BuildLiveRefreshSpec("prey", "vault", "delves", "worldWeekly")
                else
                    refreshSpec = ns:BuildLiveRefreshSpec("prey")
                end
            elseif refreshVisibleData then
                refreshSpec = ns:BuildLiveRefreshSpec("vault", "delves", "worldWeekly")
            end
        elseif event == "UPDATE_ALL_UI_WIDGETS" then
            if refreshVisibleData then
                refreshSpec = ns:BuildLiveRefreshSpec("prey", "vault", "delves", "worldWeekly")
            end
        elseif event == "TRAIT_TREE_CURRENCY_INFO_UPDATED" or event == "TRAIT_CONFIG_UPDATED" then
            if refreshVisibleData then
                refreshSpec = ns:BuildLiveRefreshSpec("professionKnowledge", "renownForce")
            end
        elseif event == "TRADE_SKILL_SHOW" or event == "TRADE_SKILL_LIST_UPDATE" then
            refreshSpec = ns:BuildLiveRefreshSpec("professionCooldowns")
        end

        if refreshSpec then
            ns:ScheduleLiveDataRefresh(0.25, refreshSpec)
            if (event == "TRAIT_TREE_CURRENCY_INFO_UPDATED" or event == "TRAIT_CONFIG_UPDATED")
                and C_Timer
                and type(C_Timer.After) == "function"
            then
                C_Timer.After(0.85, function()
                    ns:ScheduleLiveDataRefresh(0.05, ns:BuildLiveRefreshSpec("professionKnowledge", "renownForce"))
                end)
            end
            if event == "TRADE_SKILL_SHOW" and C_Timer and type(C_Timer.After) == "function" then
                C_Timer.After(0.75, function()
                    ns:ScheduleLiveDataRefresh(0.05, ns:BuildLiveRefreshSpec("professionCooldowns"))
                end)
            end
        end

        if event == "PLAYER_ENTERING_WORLD" and ns.newsPromptPending == true then
            ns.newsPromptPending = false
            local newsVersion = (ns.GetNewsCurrentVersion and ns:GetNewsCurrentVersion()) or ns.VERSION or ""
            ns:Print(string.format(
                L.NEWS_LOGIN_HINT or "Vaultloom %s - open Vaultloom with /vl. For the latest updates, check Options > Changelog.",
                newsVersion
            ))
            if ns.db and ns.db.ui and ns.GetNewsCurrentVersion then
                ns.db.ui.newsSeenVersion = ns:GetNewsCurrentVersion()
            end
        end

        if (event == "PLAYER_ENTERING_WORLD"
            or event == "WEEKLY_REWARDS_UPDATE"
            or event == "CHALLENGE_MODE_MAPS_UPDATE"
            or event == "MYTHIC_PLUS_CURRENT_AFFIX_UPDATE")
            and ns.UI
            and ns.UI.CaptureCurrentMythicPlusSnapshot
        then
            ns.UI:CaptureCurrentMythicPlusSnapshot()
        end
        if (event == "PLAYER_ENTERING_WORLD"
            or event == "HOUSE_LEVEL_CHANGED"
            or event == "NEIGHBORHOOD_INITIATIVE_UPDATED"
            or event == "INITIATIVE_TASKS_TRACKED_UPDATED"
            or event == "INITIATIVE_TASKS_TRACKED_LIST_CHANGED"
            or event == "INITIATIVE_TASK_COMPLETED"
            or event == "INITIATIVE_COMPLETED"
            or event == "QUEST_LOG_UPDATE"
            or event == "QUEST_TURNED_IN"
            or event == "QUEST_ACCEPTED"
            or event == "CURRENCY_DISPLAY_UPDATE")
            and ns.UI
            and ns.UI.IsHousingViewActive
            and ns.UI:IsHousingViewActive()
            and ns.UI.CaptureCurrentHousingSnapshot
        then
            ns.UI:CaptureCurrentHousingSnapshot()
        end
    elseif event == "GOSSIP_SHOW" then
        local discoveredHarandarQuests = {}
        if ns.CollectHarandarWantedQuestIDsFromGossip then
            discoveredHarandarQuests = ns:CollectHarandarWantedQuestIDsFromGossip()
        end
        if ns.RememberHarandarWantedQuests and ns:RememberHarandarWantedQuests(discoveredHarandarQuests) then
            ns:ScheduleLiveDataRefresh(0.05, ns:BuildLiveRefreshSpec("dailyPve"))
        end
    end
end)

addonFrame:RegisterEvent("ADDON_LOADED")
