local eventRouteConfig = require("crossEvent.cross_event_router")
local crossEventClient = require("events.cross.cross_event_client")

------------------------------------------------
local EventDispatcher = class("EventDispatcher")

function EventDispatcher:initialize(crossEventType)
    self.crossEventType = crossEventType
    self.beforeListeners = {}
    self.listeners = {}
    self.nextListenerHandleIndex = 0

    self.eventAmongService = eventRouteConfig.amongService[self.crossEventType]
    self.eventAmongCluster = eventRouteConfig.amongCluster[self.crossEventType]
end

function EventDispatcher:addEventListener(eventId, listener, obj)
    assert(type(eventId) == "number" and eventId ~= "", "EventDispatcher:addEventListener() - invalid eventId")
    if self.listeners[eventId] == nil then
        self.listeners[eventId] = {}
    end

    self.nextListenerHandleIndex = self.nextListenerHandleIndex + 1
    local handle = self.nextListenerHandleIndex
    self.listeners[eventId][handle] = {listener, obj}

    return handle
end

function EventDispatcher:addBeforeEventListener(eventId, listener, obj)
    assert(type(eventId) == "number" or type(eventId) == "string" and eventId,
        "EventDispatcher:addBeforeEventListener() - invalid eventId")
    if self.beforeListeners[eventId] == nil then
        self.beforeListeners[eventId] = {}
    end

    self.nextListenerHandleIndex = self.nextListenerHandleIndex + 1
    local handle = self.nextListenerHandleIndex
    self.beforeListeners[eventId][handle] = {listener, obj}

    return handle
end

local function execListeners(listeners, event)
    local listenerlist = {}
    for _, listener in pairs(listeners) do
        table.insert(listenerlist, listener)
    end

    for _, listener in ipairs(listenerlist) do
        if listener[2] then
            listener[1](listener[2], event)
        else
            listener[1](event)
        end
    end
end

function EventDispatcher:dispatchEvent(eventId, event)
    local beforeListeners = self.beforeListeners[eventId]
    if beforeListeners then
        event.eventId = eventId
        execListeners(beforeListeners, event)
    end

    local listeners = self.listeners[eventId]
    if listeners then
        event.eventId = eventId
        execListeners(listeners, event)
    end

    local amongSvr = self.eventAmongService and self.eventAmongService[eventId]
    local amongCluster = self.eventAmongCluster and self.eventAmongCluster[eventId]
    local nodeNames

    if amongCluster then
        nodeNames = {}
        for _, nodeTypeName in pairs(self.eventAmongCluster[eventId]) do
            local tmpNodeNames = self:getNodeNames(nodeTypeName)
            for _, nodeName in pairs(tmpNodeNames) do
                table.insert(nodeNames, nodeName)
            end
        end
    end

    if amongSvr or amongCluster then
        local eventType = self.crossEventType
        local objId = self:getOwnerId()
        ZLog.debug("[EventDispatcher].dispatchEvent,cross,eventType=%s,objId=%s", eventType, objId)
        crossEventClient.dispatchEventDispatcheroseBySend(eventType, eventId, objId, event, amongSvr, amongCluster,
            nodeNames)
    end
end

function EventDispatcher:removeEventListener(handleToRemove)
    for _, listenersForEvent in pairs(self.beforeListeners) do
        local isRemoved = false
        for handle, _ in pairs(listenersForEvent) do
            if handle == handleToRemove then
                listenersForEvent[handle] = nil
                isRemoved = true
                break
            end
        end
        if isRemoved then
            break
        end
    end

    for _, listenersForEvent in pairs(self.listeners) do
        local isRemoved = false
        for handle, _ in pairs(listenersForEvent) do
            if handle == handleToRemove then
                listenersForEvent[handle] = nil
                isRemoved = true
                break
            end
        end
        if isRemoved then
            break
        end
    end
end

return EventDispatcher
