local ADDON_NAME, ns = ...
local WF = ns.WF

local Events = WF.Events
Events._handlers = Events._handlers or {}
Events._registered = Events._registered or {}
Events._pending = Events._pending or {}

local f = CreateFrame("Frame")

local function RegisterNow(event)
  if Events._registered[event] then
    return
  end
  Events._registered[event] = true
  f:RegisterEvent(event)
end

local function SafeRegister(event)
  if InCombatLockdown and InCombatLockdown() then
    Events._pending[event] = true
    return
  end
  RegisterNow(event)
end

f:SetScript("OnEvent", function(_, event, ...)
  if event == "PLAYER_REGEN_ENABLED" then
    for e in pairs(Events._pending) do
      Events._pending[e] = nil
      RegisterNow(e)
    end
    return
  end

  local list = Events._handlers[event]
  if not list then
    return
  end
  for i = 1, #list do
    WF.Util:SafeCall(list[i], event, ...)
  end
end)

-- Always listen for leaving combat so we can safely register queued events.
RegisterNow("PLAYER_REGEN_ENABLED")

function Events:On(event, fn)
  if not self._handlers[event] then
    self._handlers[event] = {}
    SafeRegister(event)
  end
  table.insert(self._handlers[event], fn)
end
