local event = class("event")

function event:ctor()
  self.eventDic = {}
end

function event:register(eventName, func, register, obj, priority)
  if string.isEmpty(eventName) then
    errorf("eventName is empty!!")
    return
  end
  if func == nil then
    errorf(eventName .. " : func is nill!!")
    return
  end
  local node = {
    register = register,
    obj = obj,
    func = func,
    activeIn = true,
    priority = math.clamp(priority or 1, 0)
  }
  if table.isEmpty(self.eventDic[eventName]) then
    self.eventDic[eventName] = {}
  end
  local ele = self.eventDic[eventName]
  for _, v in ipairs(ele) do
    if not v.needRemove then
      if register ~= nil then
        if v.func == func and v.register == register then
          return
        end
      elseif v.func == func then
        return
      end
    end
  end
  for i, v in ipairs(ele) do
    if node.priority >= v.priority then
      table.insert(ele, i, node)
      return node
    end
  end
  table.insert(ele, node)
  return node
end

function event:unRegister(eventName, func, register)
  local ele = self.eventDic[eventName]
  if ele == nil then
    return
  end
  local metaF = getmetatable(func)
  local node, index = table.ipairsFind(ele, function(v)
    if register ~= nil then
      return v.func == func and v.register == register
    else
      if metaF and getmetatable(v.func) then
        return tostring(v.func) == tostring(func)
      end
      return v.func == func
    end
  end)
  if index then
    if self.isLock then
      node.needRemove = true
    else
      table.remove(ele, index)
    end
  end
end

function event:send(eventName, ...)
  local ele = self.eventDic[eventName]
  if ele == nil then
    return
  end
  self.isLock = true
  for i = #ele, 1, -1 do
    local node = ele[i]
    if node.needRemove then
      table.remove(ele, i)
    else
      local isDo = true
      if node.obj then
        if node.obj:IsNull() then
          table.remove(ele, i)
          isDo = false
        else
          isDo = not node.activeIn or not not node.obj.activeInHierarchy
        end
      end
      if isDo then
        if node.register then
          node.func(node.register, ...)
        else
          node.func(...)
        end
      end
    end
  end
  self.isLock = nil
end

return event
