local _AddonName, _EchoRaidTools = ...;


local module = _EchoRaidTools:GetModule("todo-list")
module.eventHandler = {}

local eventHandler = module.eventHandler

local debug = false;
local eventHandlerEnabled = false;


local eventFrame = CreateFrame("Frame", "EchoRaidTools_TodoListEventFrame")

eventHandler.eventList = {};

---comment
---@param event string
function eventHandler:RegisterEvent(event)
    if event == "FORCE" then return end
    if eventHandlerEnabled then
        eventFrame:RegisterEvent(event)
        if debug then
            print("register", event)
        end
    end
end

---comment
---@param event string
function eventHandler:UnregisterEvent(event)
    if event == "FORCE" then return end
    if eventHandlerEnabled then
        eventFrame:UnregisterEvent(event)
        if debug then
            print("unregister", event)
        end
    end
end

eventFrame:SetScript("OnEvent", function(self, event, ...)
    --if not eventHandler.eventList[event] then print ("EVENT MISMATCH") end
    for id, func in pairs(eventHandler.eventList[event]) do
        module:ProcessValueUpdate(func(event, ...))
        if debug then
            print("executed", id, event)
        end
    end
end)

---@param identifier string
---@param func function
---@param eventTable string[]
function eventHandler:RegisterFunction(identifier, func, eventTable)
    eventTable = eventTable or {}
    if not tContains(eventTable, "FORCE") then
        table.insert(eventTable, "FORCE")
    end

    for i, event in ipairs(eventTable) do
        if not eventHandler.eventList[event] then
            eventHandler.eventList[event] = {};
            eventHandler.eventList[event][identifier] = func;
            --should probably run the func once on init
            eventHandler:RegisterEvent(event);
        else
            eventHandler.eventList[event][identifier] = func;
        end
        if debug then
            print("added func", identifier, event)
        end
    end
    eventHandler:EventHandlerForceUpdate(identifier)
end

---@param identifier string
function eventHandler:UnregisterFunction(identifier)
    for event, eventTable in pairs(eventHandler.eventList) do
        for id, func in pairs(eventTable) do
            if id == identifier then
                eventTable[id] = nil;
                if debug then
                    print("removed func", identifier, event)
                end

                if not next(eventTable) then
                    eventHandler.eventList[event] = nil;
                    eventHandler:UnregisterEvent(event);
                end
            end
        end
    end
end

---@param identifier  string | nil
function eventHandler:EventHandlerForceUpdate(identifier)
    local event = "FORCE"
    if not eventHandler.eventList[event] then return end
    if not module.display.IsShown then
        if debug then
            print("did not force update, frame not shown", identifier)
        end
        return
    end
    if identifier then
        local func = eventHandler.eventList[event][identifier]
        module:ProcessValueUpdate(func(event))
        if debug then
            print("executed", identifier, event)
        end
        return
    end
    for id, func in pairs(eventHandler.eventList[event]) do
        module:ProcessValueUpdate(func(event))
        if debug then
            print("executed", id, event)
        end
    end
end

---pause updates, for situations like when list is hidden. starts disabled
function eventHandler:EventHandlerStop()
    for event, eventTable in pairs(eventHandler.eventList) do
        eventHandler:UnregisterEvent(event);
    end

    eventHandlerEnabled = false;
end

function eventHandler:EventHandlerStart()
    --   print("staring event eventHandler")
    eventHandlerEnabled = true;
    for event, eventTable in pairs(eventHandler.eventList) do
        eventHandler:RegisterEvent(event);
    end
    eventHandler:EventHandlerForceUpdate() -- is there ever any situation where we don't want to force update after starting eventHandler?
end

---@return boolean
function eventHandler:GetEventHandlerState()
    return eventHandlerEnabled;
end

local function getEventsForMod(state)
    if not state then return end
    local identifier
    if type(state) == "string" then
        identifier = state
    else
        identifier = state.identifier
    end
    if not identifier then return end
    local eventsT = {}

    for event, eventTable in pairs(eventHandler.eventList) do
        if event ~= "FORCE" then
            if eventTable[identifier] then
                table.insert(eventsT, event)
            end
        end
    end
    return eventsT
end


function eventHandler:UnregisterModEvent(identifier, event)
    local eventList = eventHandler.eventList
    if not eventList[event] then return end
    if not eventList[event][identifier] then return end
    eventList[event][identifier] = nil
end

---removes all but FORCE
function eventHandler:UnregisterAllModEvents(identifier)
    --unregisters all but FORCE, do we even bother with this?-- yea we do.
    local events = getEventsForMod(identifier)
    if not events or #events == 0 then return end

    for i, event in ipairs(events) do
        eventHandler:UnregisterModEvent(identifier, event)
    end
end
