local SchedulerManager = {
    crossDayCallbackMap = {}
}

local schedulerMap = {}
local waitRemoveList = {}
local waitSchedulerList = {}
local totalSid = 0
local totalNum = 0

local CSTime = CS.UnityEngine.Time

function SchedulerManager:update()
    if totalNum > 0 then
        --这里直接使用deltaTime可能有点不够精确，因为计时开始的时间不一定是上一帧准点
        local inter = CSTime.deltaTime or 0
        for sid, info in pairs(schedulerMap) do
            if not info.needRemove and not info.pause then
                info.tick = info.tick + inter
                if info.tick >= info.inter then
                    info.tick = info.tick - info.inter
                    local stop = not info.rep
                    -- 先设置为true避免func里面报错导致每帧调用都会报错
                    info.needRemove = true
                    if info.func then
                        local s = info.func(inter)
                        stop = stop or s
                        if stop then
                            self:unscheduleGlobal(sid)
                        else
                            info.needRemove = false
                        end
                    else
                        self:unscheduleGlobal(sid)
                    end
                end
            end
        end
    end

    if self.dirty then
        self.dirty = false
        for i = 1, #waitRemoveList do
            local sid = table.remove(waitRemoveList)
            if schedulerMap[sid] then
                schedulerMap[sid] = nil
                totalNum = totalNum - 1
            end
        end
        for i = 1, #waitSchedulerList do
            local info = table.remove(waitSchedulerList)
            schedulerMap[info.sid] = info
            totalNum = totalNum + 1
        end
    end
end

function SchedulerManager:_startSchedule(func, inter, rep)
    totalSid = totalSid + 1
    local info = {sid = totalSid, inter = inter or 0, tick = 0, func = func, rep = rep}
    table.insert(waitSchedulerList, info)
    self.dirty = true
    return totalSid
end

-- 此方法不能直接在外部调用，请使用例如BaseUI，BaseModule等封装好的接口
function SchedulerManager:scheduleGlobal(func, inter)
    return self:_startSchedule(func, inter, true)
end

-- 此方法不能直接在外部调用，请使用例如BaseUI，BaseModule等封装好的接口
function SchedulerManager:performWithDelayGlobal(func, delay)
    return self:_startSchedule(func, delay, false)
end

function SchedulerManager:unscheduleGlobal(sid)
    local info = schedulerMap[sid]
    if info then
        info.needRemove = true
        info.waitRemove = true
        table.insert(waitRemoveList, sid)
        self.dirty = true
    else
        for k, v in ipairs(waitSchedulerList) do
            if sid == v.sid then
                table.remove(waitSchedulerList, k)
                break
            end
        end
    end
end

function SchedulerManager:pause(sid)
    local info = schedulerMap[sid]
    if info then
        if not info.pause and not info.waitRemove then
            info.pause = true
        end
    else
        for k, v in ipairs(waitSchedulerList) do
            if sid == v.sid then
                if not v.pause and not v.waitRemove then
                    v.pause = true
                end
                break
            end
        end
    end
end

function SchedulerManager:resume(sid)
    local info = schedulerMap[sid]
    if info then
        if info.pause and not info.waitRemove then
            info.pause = false
        end
    else
        for k, v in ipairs(waitSchedulerList) do
            if sid == v.sid then
                if v.pause and not v.waitRemove then
                    v.pause = false
                end
                break
            end
        end
    end
end

function SchedulerManager:unscheduleAll()
    schedulerMap = {}
    waitRemoveList = {}
    waitSchedulerList = {}
    totalNum = 0
    self.dirty = false
end

function SchedulerManager:clear()
    self:unscheduleAll()
end

if NOT_PUBLISH then
    function SchedulerManager:_checkDebugScheduleFuncMap()
        if self._debugScheduleFuncMap == nil then
            local ScrollRectBase = require "app/ui/common/scrollrect/scrollrect_base"
            self._debugScheduleFuncMap = {
                [BaseUI.performWithDelayGlobal] = true,
                [BaseUI.scheduleGlobal] = true,
                [BaseScene.performWithDelayGlobal] = true,
                [BaseScene.scheduleGlobal] = true,
                [BaseModule.performWithDelayGlobal] = true,
                [BaseModule.scheduleGlobal] = true,
                [BaseObject.performWithDelayGlobal] = true,
                [BaseObject.scheduleGlobal] = true,
                [SceneManager.scheduleGlobal] = true,
                [SDKManager.doNextFrame] = true,
                [SDKManager.initPayListener] = true,
                [SDKManager.tryLoadRewardedAdDelay] = true,
                [ScrollRectBase.refillCells] = true,
                [DataManager.scheduleGlobal] = true,
                [NetManager.performWithDelayGlobal] = true,
                [NetManager.scheduleGlobal] = true,
            }
        end
    end

    SchedulerManager._releaseScheduleGlobal = SchedulerManager.scheduleGlobal
    function SchedulerManager:scheduleGlobal(...)
        self:_checkDebugScheduleFuncMap()
        local currFunc = debug.getinfo(2, "f").func
        if self._debugScheduleFuncMap[currFunc] == nil then
            Logger.logFatal("you can not call SchedulerManager:scheduleGlobal directly")
        end
        return self:_releaseScheduleGlobal(...)
    end

    SchedulerManager._releasePerformWithDelayGlobal = SchedulerManager.performWithDelayGlobal
    function SchedulerManager:performWithDelayGlobal(...)
        self:_checkDebugScheduleFuncMap()
        local currFunc = debug.getinfo(2, "f").func
        if self._debugScheduleFuncMap[currFunc] == nil then
            Logger.logFatal("you can not call SchedulerManager:performWithDelayGlobal directly")
        end
        return self:_releasePerformWithDelayGlobal(...)
    end
end

return SchedulerManager