-- Portal Pro :: Core/Events.lua
-- One frame for every game event in the addon. Handlers are refcounted, so unregistering
-- the last listener for an event actually stops the client sending it to us.

local ADDON_NAME, PP = ...

local frame = CreateFrame("Frame", "PortalProEventFrame")
local handlers = {}

frame:SetScript("OnEvent", function(self, event, ...)
	local list = handlers[event]
	if not list then return end
	-- Iterate a snapshot: a handler is allowed to unregister itself.
	for i = #list, 1, -1 do
		local fn = list[i]
		if fn then
			local ok, err = pcall(fn, event, ...)
			if not ok then
				PP:Error(("%s handler failed: %s"):format(event, tostring(err)))
			end
		end
	end
end)

--- @param event string game event name
--- @param fn fun(event:string, ...):void
function PP:RegisterEvent(event, fn)
	local list = handlers[event]
	if not list then
		list = {}
		handlers[event] = list
		local ok = pcall(frame.RegisterEvent, frame, event)
		if not ok then
			-- Event doesn't exist on this client build. Not fatal; the handler just never fires.
			PP:Debug("event not available on this client:", event)
		end
	end
	list[#list + 1] = fn
	return fn
end

function PP:UnregisterEvent(event, fn)
	local list = handlers[event]
	if not list then return end
	for i = #list, 1, -1 do
		if list[i] == fn then table.remove(list, i) end
	end
	if #list == 0 then
		handlers[event] = nil
		pcall(frame.UnregisterEvent, frame, event)
	end
end

PP.eventFrame = frame
