local _AddonName, _EchoRaidTools = ...;


local module = _EchoRaidTools:GetModule("todo-list")


local addonLoaded, worldLoaded, modsLoaded = false, false, false
local loadConditionEventFrame = CreateFrame("frame")
local statesToCheck = {}
local trackedMods = {}
local currentState = {
    combat = false,
    encounter = false,
    party = false,
    raid = false,
    specID = 0,
    level = 0,
}

local function registerEvents(eventTable)
    loadConditionEventFrame:UnregisterAllEvents()
    if not eventTable then return end
    for i, event in pairs(eventTable) do
        loadConditionEventFrame:RegisterEvent(event)
    end
end



local function initialiseMods()
    if modsLoaded then return end
    if not addonLoaded then return end
    if not worldLoaded then return end

    module:ImportDefaults()
    module:ImportUserMods()

    module.updateLoadConditions()
    modsLoaded = true
end

function module.Initialize()
    addonLoaded = true
    initialiseMods()
end

loadConditionEventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")


--TODO update this section it's fkin terrible
local function onEvent(self, event, ...)
    if event == "PLAYER_ENTERING_WORLD" then
        if not worldLoaded then
            worldLoaded = true
        end
        initialiseMods()
        return
    elseif event == "ENCOUNTER_START" then
        currentState.encounter = true
    elseif event == "ENCOUNTER_END" then
        currentState.encounter = false
    elseif event == "PLAYER_REGEN_ENABLED" then
        currentState.combat = false
    elseif event == "PLAYER_REGEN_DISABLED" then
        currentState.combat = true
    elseif event == "GROUP_ROSTER_UPDATE" then
        local isInRaid     = IsInRaid()
        currentState.party = isInRaid or IsInGroup()
        currentState.raid  = isInRaid
    elseif event == "PLAYER_LEVEL_UP" then
        currentState.level = UnitLevel("player")
    elseif event == "ACTIVE_PLAYER_SPECIALIZATION_CHANGED" then
        currentState.specID = GetSpecializationInfo(GetSpecialization() or 0)
    else
        currentState.encounter = IsEncounterInProgress()
        currentState.combat    = InCombatLockdown()
        local isInRaid         = IsInRaid()
        currentState.party     = isInRaid or IsInGroup()
        currentState.raid      = isInRaid
        currentState.specID    = GetSpecializationInfo(GetSpecialization() or 0)
        currentState.level     = UnitLevel("player")
    end




    for identifier, state in pairs(trackedMods) do
        local shouldLoad = true
        for i, func in ipairs(state.funcs) do
            if not func() then
                shouldLoad = false
                break
            end
        end
        if shouldLoad ~= state.previousLoadState then
            module:ReloadModFromStorage(identifier)
        end
    end

    for i, state in ipairs(statesToCheck) do
        if currentState[state] then
            module:Hide()
            return
        end
    end
    module:Show()
end


loadConditionEventFrame:SetScript("OnEvent", onEvent)

function module.updateLoadConditions()
    local moduleEnabled = module.GetModuleState()
    if not moduleEnabled then
        module:Hide()
        registerEvents()
        return
    end
    local loadConditionSettings = module:GetSetting({ "loadCondition" })

    local combatType = loadConditionSettings.combatType
    local groupType = loadConditionSettings.groupType
    statesToCheck = {}
    local events = {}
    if combatType == "never" then

    elseif combatType == "encounter" then
        tInsertUnique(events, "ENCOUNTER_START")
        tInsertUnique(events, "ENCOUNTER_END")
        tInsertUnique(statesToCheck, "encounter")
    elseif combatType == "combat" then
        tInsertUnique(statesToCheck, "combat")
        tInsertUnique(events, "PLAYER_REGEN_ENABLED")
        tInsertUnique(events, "PLAYER_REGEN_DISABLED")
    end

    if groupType == "never" then
    elseif groupType == "raid" then
        table.insert(statesToCheck, "raid")
        table.insert(events, "GROUP_ROSTER_UPDATE")
    elseif groupType == "party" then
        tInsertUnique(statesToCheck, "party")
        tInsertUnique(events, "GROUP_ROSTER_UPDATE")
    end

    for identifier, loadState in pairs(trackedMods) do
        if loadState.events then
            for i, event in ipairs(loadState.events) do
                tInsertUnique(events, event)
            end
        end
    end
    registerEvents(events)

    onEvent()
end

---comment
---@param state any
---@return boolean shouldBeLoaded
function module:ShouldModBeLoaded(state)
    local loadConditions = state.loadConditions
    if not loadConditions then return true end
    local checkState = { funcs = {}, previousLoadState = false, events = {} }

    if loadConditions.level and loadConditions.level.enabled then
        local min = loadConditions.level.min
        local max = loadConditions.level.max
        table.insert(checkState.funcs, function()
            return currentState.level >= min and currentState.level <= max
        end)
        table.insert(checkState.events, "PLAYER_LEVEL_UP")
    end

    if loadConditions.spec and loadConditions.spec.enabled then
        table.insert(checkState.funcs, function()
            return loadConditions.spec.specs[currentState.specID]
        end)
        table.insert(checkState.events, "ACTIVE_PLAYER_SPECIALIZATION_CHANGED")
    end

    if #checkState.funcs > 0 then
        local shouldBeLoaded = true
        for i, func in ipairs(checkState.funcs) do
            if not func() then
                shouldBeLoaded = false
                break
            end
        end
        checkState.previousLoadState = shouldBeLoaded
        trackedMods[state.identifier] = checkState
        return shouldBeLoaded
    else
        return true
    end
end
