---------------------------------------------------------
-- 图标管理

-- updateIcon 			刷新图标

-- module接口
-- isOpen 如果模块没有这个函数默认是开启 human, YYInfo, funcConfig
-- isRed 如果模块没这个函数 默认是没红点 human, YYInfo, funcConfig
-- getIcon 如果模块没这个函数 默认从yunying表里面读iconid
-- isActive 跟模块关联的激活状态
-- updateDaily 隔天处理
-- onCharge 充值回调
-- onZero 0点处理
-- onLevelUp 升级回调
-- onLogin 登陆回调
---------------------------------------------------------

local YunYingExcel = require("excel.yunying")
local Lang = require("common.Lang")
local Config = require("Config")
local Util = require("common.Util")
local Msg = require("core.Msg")
local Broadcast = require("broadcast.Broadcast")
local ObjHuman = require("core.ObjHuman")
local BannerExcel = require("excel.yunying")
local AbsActLogic = require("absAct.AbsActLogic")
local SysParameter = require("common.SysParameter")
local PanelDefine = require("broadcast.PanelDefine")
local HeroGrid = require("hero.HeroGrid")
local HeroUpLogic = require("absAct.HeroUpLogic")
local AbsActExcel = require("excel.absAct")
local HtmlUtil = require("common.HtmlUtil")
local Json = require("common.Json")
local YunYingDefine = require("yunying.YunYingDefine")
local CommonDB = require("common.CommonDB")
local MiddleConnect = require("middle.MiddleConnect")
local InnerMsg = require("core.InnerMsg")
local AbsReachRankDB = require("absAct.AbsReachRankDB")
local OpenServerActPowerUp = require("present.OpenServerActPowerUp")
local WeekendLoopActManger = require("WeekendLoopActivity.WeekendLoopActManager")
local OpenServerActAddUpCharge = require("present.OpenServerActAddUpCharge")
local ServerCommerceActManger = require("serverCommerce.ServerCommerceManager")
local CycleActivityLogic = require("yunying.CycleActivity")

ID2YYInfo = ID2YYInfo or { } -- 每个id是一个主界面上方运营活动大图标入口
PANELID2OPENLV = PANELID2OPENLV or { }
YYFUNCINFO = YYFUNCINFO or { } -- 活动列表 用于快捷查询
BANNER_LIST_SERVER = {}



YUNYING_POS_TYPE1 = 1   -- 运营活动
YUNYING_POS_TYPE2 = 2   -- abs活动

function inServerIndex(svrIndexs)
	for i = 1, #svrIndexs do
		local index1 = svrIndexs[i][1]
		local index2 = svrIndexs[i][2]
		if Config.SVR_INDEX >= index1 and Config.SVR_INDEX <= index2 then
			return true
		end
	end
end

-- 根据funcID确定配置文件
function getFuncConfig(funcID)
    local funcConfig = YunYingExcel.func[funcID]
    if not funcConfig then
        funcConfig = AbsActExcel.absActivity[funcID]
    end
    return funcConfig
end

-- 根据funcID 确定modouleFn数据
local function getYYFuncInfo(funcID)
    if not YYFUNCINFO then return end
    return YYFUNCINFO[funcID]
end

-- 是否是运营活动
local function isYYfunc(funcID)
    if YunYingExcel.func[funcID] then
       return true
    end
    return false
end

-- 是否是Abs活动
local function isAbsfunc(funcID)
    if AbsActExcel.absActivity[funcID] then
       return true
    end
    return false
end

-- 初始化数据
local function initYYInfo(yyID, config)
    local YYInfo = ID2YYInfo[yyID] or { }
    YYInfo.yyID = yyID
    YYInfo.config = config

    local moduleList = nil
    local openLv = 0
    for i = 1, #config.funcs do
        local funcID = config.funcs[i]
        local funcConfig = getFuncConfig(funcID)

        if YYFUNCINFO[funcID] then
           -- 如果 funcID 已经存在，说明可能是在热更新时重复初始化，或者配置有重复
           -- 先清理旧的，然后继续初始化
        --    print("WARNING: funcID "..funcID.." already exists in YYFUNCINFO, clearing old data")
           YYFUNCINFO[funcID] = nil
        end

        if funcConfig then
            if funcConfig.moduleFn ~= "" then
                moduleList = moduleList or { }
                local moduleFn = load("return require(\"" .. funcConfig.moduleFn .. "\")")()
                moduleList[funcID] = moduleFn
                if moduleFn then
                    moduleFn.funcID = moduleFn.funcID or {}
                    moduleFn.funcID[funcID] = funcID

                    moduleFn.YYInfo = moduleFn.YYInfo or {}
                    moduleFn.YYInfo[funcID] = YYInfo

                    moduleFn.pos = moduleFn.pos or {}
                    moduleFn.pos[funcID] = config.pos
                    moduleFn.yyID = moduleFn.yyID or {}
                    moduleFn.yyID[funcID] = yyID

                    funcConfig.funcID = funcID

                    YYFUNCINFO[funcID] = moduleFn
                    PANELID2OPENLV[funcConfig.panelID] = funcConfig.openLv
                end
            end

            -- 取子功能里面最低等级
            if openLv > funcConfig.openLv or openLv == 0 then
                openLv = funcConfig.openLv
            end
        end
    end

    YYInfo.moduleList = moduleList
    YYInfo.openLv = openLv
    ID2YYInfo[yyID] = YYInfo

    return YYInfo
end

-- 初始化
function init()
    ID2YYInfo = ID2YYInfo or { }
    -- 先保存旧的 YYFUNCINFO 用于清理，然后清空
    local oldYYFUNCINFO = YYFUNCINFO or {}
    YYFUNCINFO = {}
	BANNER_LIST_SERVER = {}

    for yyID, noUse in pairs(ID2YYInfo) do
        if YunYingExcel.config[yyID] == nil then
            ID2YYInfo[yyID] = nil
        end
    end

    -- 清理旧的 YYFUNCINFO 中不再存在的配置
    for funcID, info in pairs(oldYYFUNCINFO) do
        if YunYingExcel.func[funcID] == nil and AbsActExcel.absActivity[funcID] == nil then
           -- 配置已不存在，不需要清理（因为已经清空了）
        end
    end
    
    for yyID, config in pairs(YunYingExcel.config) do
        if inServerIndex(config.serverIndex) then
           initYYInfo(yyID, config)
        end
    end

    -- 广告
    for k, config in pairs(BannerExcel.banner) do
       if inServerIndex(config.serverIndex) then
          BANNER_LIST_SERVER[#BANNER_LIST_SERVER + 1] = k
       end
    end

    handleAbs()
	
    -- 活动初始化后 才能去实始化ABS排名活动
    AbsReachRankDB.init()
    OpenServerActPowerUp.Init()
    WeekendLoopActManger.WeekLoopACT_Init()
    OpenServerActAddUpCharge.Init()
    ServerCommerceActManger.CommerceAct_Init()
end


ABS_LOOP_TYPE1 = 1 -- 指定时间的活动
ABS_LOOP_TYPE2 = 2 -- 指定时间的活动 指定间隔天数 循环一次
ABS_LOOP_TYPE3 = 3 -- 按开服时间    指定间隔天数 一直循环 支持间隔时间设置
ABS_LOOP_TYPE4 = 4 -- 按开服时间    指定间隔天数 循环一次
ABS_LOOP_TYPE5 = 5 -- 按合服时间    指定间隔天数 循环一次
ABS_LOOP_TYPE6 = 6 -- 每周周几开
ABS_LOOP_TYPE7 = 7 -- 每月几号开
DAY_SEC = 24 * 3600


-- 指定时间的活动
local function handleAbsInit(openDay, now, config, funcID)
   config.actId = config.actId or 0
   config.adIcon = 0
   config.realStartTime = 0
   config.realEndTime = 0
end



function handleAbs7MiddleReturn(fd,msg)
    if msg.isOpen == 0 then
        return
    end

    local config = getFuncConfig(msg.funcID)

    local openDay = CommonDB.getServerOpenDay()
    if openDay == nil then return end
    
    if config.loopType ~= ABS_LOOP_TYPE7 then return end

    local now = os.time()

    local days = config.days                        -- 持续几天
    local turns = config.turns                      -- 
    local ad = config.ad                            --
    local eachDays = config.eachDays                -- 几号开
    local toOpenDay = openDay - config.openDay 

    local endDay = days + eachDays  -- 几号结束 
    
    local actStart = false

    if days > 0 and #turns > 0 then
        local nowMidnight = Util.getDayStartTime(now)
        local d = os.date("*t",now)
        local monthDay = d.day
        -- 生效期
        if toOpenDay >= 0 and monthDay >= config.eachDays and monthDay < endDay then
            local subDays = monthDay - config.eachDays
            local handleBeginTs = nil
            handleBeginTs = nowMidnight - subDays * DAY_SEC

            config.realStartTime = handleBeginTs
            config.realEndTime = handleBeginTs + days * DAY_SEC - 3600 -- 活动23点结束
            if now >= config.realStartTime and now < config.realEndTime then
                config.actId = turns[1] or 0
                config.adIcon = ad[1] or 0
                -- print("handleAbs7 act is started!!",Config.SVR_INDEX,msg.funcID,config.actId)
                actStart = true
            end
        end
    else
        assert(nil, "handleAbs ABS_LOOP_TYPE7 days or turns err !!!" .. funcID)
    end
    if actStart then
        for _, human in pairs(ObjHuman.onlineUuid) do
            print("aaaa actStart")
            sendIcons(human)
        end 
    end
end

-- 初始化abs活动 开启的时间
function handleAbs()
    local openDay = CommonDB.getServerOpenDay()
    if openDay == nil then return end
    
    local mergeDay = CommonDB.getServerMergeDay()
    local now = os.time()
    for yyID, YYInfo in pairs(ID2YYInfo) do
        for i = 1, #YYInfo.config.funcs do
            local funcID = YYInfo.config.funcs[i]
            if isAbsfunc(funcID) then
                local config = getFuncConfig(funcID)
                if not config then
                    assert(nil, "handleAbs config is nil !!!" .. funcID)
                end

                handleAbsInit(openDay, now, config, funcID)
                
            end
        end
    end
end

-- panel id -> id
local PANELID_2_ACTID = nil
local function getActIDByPanelID(panelID)
    if not PANELID_2_ACTID then
        PANELID_2_ACTID = { }
        for id, config in pairs(YunYingExcel.config) do
            if inServerIndex(config.serverIndex) then
               PANELID_2_ACTID[config.panelID] = id
            end
        end
    end
    return PANELID_2_ACTID[panelID]
end

function getOpenLvByPanelID(panelID)
    return PANELID2OPENLV[panelID] or 0
end

-- 是否开启活动，内部使用
local function isBaseOpen(YYInfo, human)
    if not YYInfo then return end
    if human.db.lv < YYInfo.openLv then return end
    if not YYInfo.moduleList then return end
    for k, v in pairs(YYInfo.moduleList) do
        local funcConfig = getFuncConfig(k)
        if v.isOpen and v.isOpen(human, YYInfo, funcConfig) == true then
            return true
        end
    end
end

-- 未开放提示
local function sendNoOpen(human, noSend)
    if noSend then return end
    Broadcast.sendErr(human, Lang.YUNYING_ERR_TIME)
end

-- 是否开启
function isOpen(YYInfo, human, noSend)
    if not YYInfo then
        return sendNoOpen(human, noSend)
    end
    if not isBaseOpen(YYInfo, human) then
        return sendNoOpen(human, noSend)
    end
    return true
end

-- 是否显示红点
function isRed(YYInfo, human)
    if not YYInfo then return false end
    if not YYInfo.moduleList then return false end

    for k, v in pairs(YYInfo.moduleList) do
        local funcConfig = getFuncConfig(k)
        -- 开启了才判断红点
        if not v.isOpen or v.isOpen(human, YYInfo, funcConfig) == true then
            if v.isRed and v.isRed(human, YYInfo, funcConfig) == true then
                return true
            end
        end
    end
    return false
end

-- 获得图标 主要是节日活动和绝对时间活动每周的图标都不一样
function getIcon(YYInfo, human)
    if not YYInfo then return false end
    if not YYInfo.moduleList then return false end
    if YYInfo.config.pos ~= YUNYING_POS_TYPE1 then return false end

    for k, v in pairs(YYInfo.moduleList) do
        local funcConfig = getFuncConfig(k)
        if v.getIcon then
            return v.getIcon(human, YYInfo, funcConfig)
        end
    end
end

-- 缓存红点
function setCacheRed(human, yyID, red)
    human.yunyings[yyID] = red
end

-- 
function getCacheRed(human, yyID)
    return human.yunyings and human.yunyings[yyID]
end

function getLeftTime(YYInfo, human)
    if not YYInfo then return 0 end
    if not YYInfo.moduleList then return 0 end
    local leftTime = 0
    for k, v in pairs(YYInfo.moduleList) do
        local funcConfig = getFuncConfig(k)
        if v.getLeftTime and funcConfig.actId ~= 0 then
            local rest =  v.getLeftTime(human, YYInfo, funcConfig)
            leftTime = leftTime < rest and rest or leftTime
        end
    end
    return leftTime
end

-- 封装结构体
local function fontIcon(net, YYInfo, human)
    local config = YYInfo.config
    local red = isRed(YYInfo, human)
    net.id = YYInfo.yyID
    net.red = red and 1 or 0
    net.leftTime = getLeftTime(YYInfo, human) or 0
    net.icon = getIcon(YYInfo, human)
    if net.icon == nil or net.icon == 0 then
        net.icon = config.icon
    end
    net.sortID = config.sortID
    net.panelID = config.panelID
    net.pos = config.pos or 0
    setCacheRed(human, YYInfo.yyID, red)

end

-- 运营活动列表
function sendIcons(human)
    if human.version and human.version == "minigame_ts_ios" then
        return
    end

    human.yunyings = { }
    local msgRet = Msg.gc.GC_YUNYING_LIST
    msgRet.list[0] = 0
    local maxLen = #msgRet.list
    for _, YYInfo in pairs(ID2YYInfo) do
        if isOpen(YYInfo, human, true) and
            YYInfo.config.pos == YUNYING_POS_TYPE1 then
            print("[sendIcons] 发送的活动ID = "..YYInfo.yyID)
            if msgRet.list[0] >= maxLen then
                break
            end
            msgRet.list[0] = msgRet.list[0] + 1
            fontIcon(msgRet.list[msgRet.list[0]], YYInfo, human)
        end
    end

    Msg.send(msgRet, human.fd)
end

-- 刷新图标
function updateIcon(YYInfo, human, nocheckred)
    if not YYInfo then return end
    if YYInfo.config.pos ~= YUNYING_POS_TYPE1 then return end

    if isOpen(YYInfo, human, true) then
        if nocheckred or(getCacheRed(human, YYInfo.yyID) ~= isRed(YYInfo, human)) then
            sendIconUpdate(YYInfo.yyID, human)
        end
    else
        if nocheckred or getCacheRed(human, YYInfo.yyID) ~= nil then
            sendIconDel(YYInfo.yyID, human)
        end
    end
end

-- 添加或者改变
function sendIconUpdate(yyID, human)
    if not human.yunyings then return end
    -- 未初始不发

    local YYInfo = ID2YYInfo[yyID]
    if not YYInfo then return end
    if YYInfo.config.pos ~= YUNYING_POS_TYPE1 then return end

    local msgRet = Msg.gc.GC_YUNYING_UPDATE
    if human then
        fontIcon(msgRet.data, YYInfo, human)
        Msg.send(msgRet, human.fd)
    else
        for _, human in pairs(ObjHuman.onlineUuid) do
            if human.fd then
                fontIcon(msgRet.data, YYInfo, human)
                Msg.send(msgRet, human.fd)
            end
        end
    end
end

-- 删除
function sendIconDel(yyID, human)
    if not human.yunyings then return end
    -- 未初始不发
    local YYInfo = ID2YYInfo[yyID]
    if not YYInfo then return end
    if YYInfo.config.pos ~= YUNYING_POS_TYPE1 then return end

    local msgRet = Msg.gc.GC_YUNYING_DEL
    msgRet.id = yyID
    if human then
        Msg.send(msgRet, human.fd)
        setCacheRed(human, YYInfo.yyID)
    else
        for _, human in pairs(ObjHuman.onlineUuid) do
            if human.fd then
                Msg.send(msgRet, human.fd)
                setCacheRed(human, YYInfo.yyID)
            end
        end
    end
end

-- 活动组信息
function sendGroupList(human, panelID)
    -- 获取panel运营ID
    local actID = getActIDByPanelID(panelID)
    local YYInfo = nil
    
    -- 如果通过config.panelID找不到，则通过funcConfig.panelID查找
    if (not actID or actID < 1) and panelID ~= PanelDefine.PANEL_ID_3101 then
        -- 遍历所有config，查找包含该panelID的funcConfig
        for yyID, config in pairs(YunYingExcel.config) do
            if inServerIndex(config.serverIndex) then
                for i = 1, #config.funcs do
                    local funcID = config.funcs[i]
                    local funcConfig = getFuncConfig(funcID)
                    if funcConfig and funcConfig.panelID == panelID then
                        actID = yyID
                        break
                    end
                end
                if actID then break end
            end
        end
    end
    
    if not actID or actID < 1 then
        -- print("[sendGroupList] not found actID for panelID="..panelID)
        return
    end
    
    -- 通过运营ID获取运营信息
    YYInfo = ID2YYInfo[actID]
    if not YYInfo then
        -- print("[sendGroupList] YYInfo not found for actID="..actID..", panelID="..panelID)
        return
    end
    
    if not isOpen(YYInfo, human, true) then
        -- print("[sendGroupList] YYInfo not open for actID="..actID..", panelID="..panelID)
        return
    end

    local msgRet = Msg.gc.GC_YUNYING_GROUP_LIST
    msgRet.panelID = panelID
    msgRet.list[0] = 0

    -- 判断是否是主面板请求（主面板的 panelID 等于 config.panelID）
    local isMainPanel = (panelID == YYInfo.config.panelID)

    for i = 1, #YYInfo.config.funcs do
        local funcID = YYInfo.config.funcs[i]
        local funcConfig = getFuncConfig(funcID)
        
        if not funcConfig then
            -- print("[sendGroupList] funcConfig is nil for funcID="..funcID)
            goto continue
        end
        
        -- 如果是主面板请求，返回所有 funcs；否则只返回 panelID 匹配的 funcs
        if not isMainPanel and funcConfig.panelID ~= panelID then
            goto continue
        end

        -- print("[sendGroupList] processing funcID="..funcID..", panelID="..funcConfig.panelID..", requestPanelID="..panelID..", isMainPanel="..tostring(isMainPanel))
        -- print("[sendGroupList] YYInfo.moduleList[funcID]="..tostring(YYInfo.moduleList[funcID]))

        local state = false
        local endTime = nil
        local startTime = nil
        local leftTime = nil

        if human.db.lv >= funcConfig.openLv then
            if YYInfo.moduleList[funcID] ~= nil and
                YYInfo.moduleList[funcID].isOpen ~= nil then
                state, endTime, startTime = YYInfo.moduleList[funcID].isOpen(human, YYInfo, funcConfig)
                -- 如果 isOpen 返回 nil，则 state 为 nil，需要转换为 false
                if state == nil then
                    state = false
                end
                if not state then
                    -- print("[sendGroupList] funcID="..funcID.." isOpen returned false/nil, panelID="..funcConfig.panelID)
                else
                    -- print("[sendGroupList] funcID="..funcID.." isOpen returned true, panelID="..funcConfig.panelID)
                end
                if endTime then
                   leftTime = endTime - os.time()
                end
            else
                -- print("[sendGroupList] funcID="..funcID.." moduleList is nil or isOpen is nil, setting state=true")
                state = true
            end
        else
            -- print("[sendGroupList] player lv="..human.db.lv.." < openLv="..funcConfig.openLv.." for funcID="..funcID)
        end

        if state then
            msgRet.list[0] = msgRet.list[0] + 1
            if YYInfo.moduleList[funcID] ~= nil and
                YYInfo.moduleList[funcID].getLeftTime ~= nil then
                leftTime = YYInfo.moduleList[funcID].getLeftTime(human, YYInfo, funcConfig)
            end

            local net = msgRet.list[msgRet.list[0]]
            net.id = funcID
            net.icon = funcConfig.icon
            net.red = 0
            net.leftTime = leftTime or 0
            net.endTime = endTime or 0
            net.startTime = startTime or 0
            net.name = funcConfig.actName or ""
            if YYInfo.moduleList[funcID] and YYInfo.moduleList[funcID].isRed and YYInfo.moduleList[funcID].isRed(human, YYInfo, funcConfig) == true then
                net.red = 1
            end
            net.panelID = funcConfig.panelID
            net.effect = funcConfig.effect
            net.param = funcID
            -- print("[sendGroupList] added funcID="..funcID.." to list, panelID="..panelID)
        end
        
        ::continue::
    end
    
    -- print("[sendGroupList] sending list with count="..msgRet.list[0]..", panelID="..panelID)
    Msg.send(msgRet, human.fd)
end

-- 刷新标签页红点
function sendGroupUpdate(YYInfo, human, subPanelID, param)
    if not YYInfo then   print("   not  YYInfo   param  ", param, " panelID ", subPanelID) return end

    local msgRet = Msg.gc.GC_YUNYING_GROUP_UPDATE
    msgRet.panelID = YYInfo.config.panelID
    local state = false
    local endTime = nil
    local startTime = nil
    local id = nil
    local len = 0

    for i = 1, #YYInfo.config.funcs do
        local funcID = YYInfo.config.funcs[i]
        local funcConfig = getFuncConfig(funcID)
        if (not param and funcConfig.panelID == subPanelID) or 
            (param and funcConfig.param == param and funcConfig.panelID == subPanelID) then    -- 同一个 面板的 多期活动
            if YYInfo.moduleList[funcID] ~= nil and
                YYInfo.moduleList[funcID].isOpen ~= nil then
                state, endTime, startTime = YYInfo.moduleList[funcID].isOpen(human, YYInfo, funcConfig)
            else
                state = true
            end
            if not state then return end
            local leftTime = nil
            if YYInfo.moduleList[funcID] ~= nil and
                YYInfo.moduleList[funcID].getLeftTime ~= nil then
                leftTime = YYInfo.moduleList[funcID].getLeftTime(human, YYInfo, funcConfig)
            end
            len = len + 1
            msgRet.data.id = funcID
            msgRet.data.icon = funcConfig.icon
            msgRet.data.name = funcConfig.actName or ""
            msgRet.data.red = 0
            msgRet.data.leftTime = leftTime or 0
            msgRet.data.endTime = endTime or 0
            msgRet.data.startTime = startTime or 0
            if YYInfo.moduleList[funcID] and YYInfo.moduleList[funcID].isRed and YYInfo.moduleList[funcID].isRed(human, YYInfo, funcConfig) == true then
                msgRet.data.red = 1
            end
            msgRet.data.panelID = funcConfig.panelID
            msgRet.data.effect = funcConfig.effect
            msgRet.data.param = funcID
            break
        end
    end
    if len == 0 then return end
    Msg.send(msgRet, human.fd)
end

-- 推送开放等级
function sendOpenLv(human, panelID)
    local openLv = getOpenLvByPanelID(panelID)
    if not openLv then return end

    local msgRet = Msg.gc.GC_YUNYING_OPEN_LV
    msgRet.openLv = openLv
    msgRet.panelID = panelID
    Msg.send(msgRet, human.fd)
end

-- 一次性广告面板

function sendFirstBanner(human)
    local funcID = YunYingDefine.YUNYING_ID_101
    local moduleFn = getYYFuncInfo(funcID)
    if not moduleFn then return end

    local funcConfig = YunYingExcel.func[funcID]
    if not funcConfig then return end

    if not moduleFn.isOpen(human, moduleFn.YYInfo[funcID], funcConfig) then return end

    local dialogLv = SysParameter.getSysParameter(SysParameter.PARAMETER_14)
    local firstPanel = nil
    if human.db.lv >= dialogLv then
        if human.db.guide.firstPanel == nil then
            firstPanel = PanelDefine.PANEL_ID_3302
            human.db.guide.firstPanel = 1
        end
    end
    if not firstPanel then return end

    local msgRet = Msg.gc.GC_YUNYING_FIRST_BANNER_QUERY
    msgRet.panelID = firstPanel
    Msg.send(msgRet, human.fd)
end

-- 广告面板
local function bannerCmp(a, b) 
   return a[2] < b[2] 
end

local function makeBannerNet(net, bannerID, dot, banner)
    print("#### bannerID: ", bannerID)
   local config = BannerExcel.banner[bannerID]
   if not config then return end
   local jSonParam = {}
   net.icon = config.icon
   net.panelID = config.panelID
   local moduleFn = getYYFuncInfo(config.funcID[1])
   if moduleFn then
      jSonParam.yyID = moduleFn.yyID[config.funcID[1]]
      jSonParam.tsStart = banner[4]
      jSonParam.tsEnd = banner[5]
      jSonParam.leftTs = banner[6]
      jSonParam.ad = 0
      jSonParam.dot = dot
      jSonParam.param = banner[10]
      if moduleFn.makeBanner then
          moduleFn.makeBanner(jSonParam, banner[9])
      end
      local funcConfig = getFuncConfig(config.funcID[1])
      net.panelID = funcConfig.panelID
   end
   net.param = Json.Encode(jSonParam)
end


function sendBanner(human)
    if human.version and human.version == "minigame_ts_ios" then
        return
    end
    
    local nNowLv = human.db.lv
    local bannerList = { }
    local len = 0
    for k, _id in ipairs(BANNER_LIST_SERVER) do
        local config = BannerExcel.banner[_id]
        local lenth = #config.funcID 
        local dot = nil
        for i = 1,lenth do
           local moduleFn = getYYFuncInfo(config.funcID[i])
           if moduleFn and inServerIndex(config.serverIndex) then
               local YYInfo = moduleFn.YYInfo[config.funcID[i]]
               local funcConfig = getFuncConfig(moduleFn.funcID[config.funcID[i]])
               local active = nil
               if moduleFn.isActive and
                   not moduleFn.isActive(human, YYInfo, funcConfig) and nNowLv >= funcConfig.openLv then
                   if dot ~= true then
                       dot = moduleFn.isRed and moduleFn.isRed(human, YYInfo, funcConfig)
                   end
               end
           end
        end

        if _id == 4 or _id == 34 then
           dot = nil
        end
        
        local moduleFn = getYYFuncInfo(config.funcID[1])
        if moduleFn and inServerIndex(config.serverIndex) then
            local YYInfo = moduleFn.YYInfo[config.funcID[1]]
            local funcConfig = getFuncConfig(moduleFn.funcID[config.funcID[1]])
            local active = nil
            if moduleFn.isActive and
                not moduleFn.isActive(human, YYInfo, funcConfig) and nNowLv >= funcConfig.openLv then
                local leftTime, endTime, startTime = 0
                local state = false
                if isAbsfunc(moduleFn.funcID[config.funcID[1]]) then
                    state, endTime, startTime = moduleFn.isOpen(human, YYInfo, funcConfig)
                    if state then
                        leftTime = endTime - os.time()
                    end
                end

                len = len + 1
                bannerList[len] = { _id, config.sortID, dot, startTime, endTime, leftTime, state, YYInfo.yyID, funcConfig.funcID, funcConfig.param }
            end
        end
    end

    local bannerID = 1
    local dot = 0
    local sortID = 0
    if len > 0 then
        table.sort(bannerList, bannerCmp)
        sortID = bannerList[1][2]
    end
    
    local msgRet = Msg.gc.GC_BANNER_QUERY
    local count = 0
    for i = 1,len do
        if bannerList[i][2] == sortID then
            count = count + 1
            bannerID = bannerList[i][1]
            if not bannerList[i][3] then
                dot = 0
            else
                dot = 1
            end
            makeBannerNet(msgRet.bannerList[count], bannerID, dot, bannerList[i])
        end

        if count >= 9 then
            break
        end
    end

    if count == 0 then
        count = count + 1
        bannerID = 1
        dot = 0
        makeBannerNet(msgRet.bannerList[count], bannerID, dot, bannerList[1])
    end 

    msgRet.bannerList[0] = count
    Msg.send(msgRet, human.fd)
end

-- 登陆处理
function onLogin(human)
    AbsActLogic.onLogin(human)
    CycleActivityLogic.onLogin(human)
    for yyID, YYInfo in pairs(ID2YYInfo) do
        for i = 1, #YYInfo.config.funcs do
            local funcID = YYInfo.config.funcs[i]
            if YYInfo.moduleList[funcID] and YYInfo.moduleList[funcID].onLogin then
                YYInfo.moduleList[funcID].onLogin(human, funcID)
            end
        end
    end

    -- CycleActivityLogic.onLogin(human)
    sendIcons(human)
    sendBanner(human)
    sendFirstBanner(human)
end

-- 隔天处理
function updateDaily(human)
    for yyID, YYInfo in pairs(ID2YYInfo) do
        for i = 1, #YYInfo.config.funcs do
            local funcID = YYInfo.config.funcs[i]
            if YYInfo.moduleList[funcID] and YYInfo.moduleList[funcID].updateDaily then
                YYInfo.moduleList[funcID].updateDaily(human, funcID)
            end
        end
        updateIcon(YYInfo, human, true)
    end

    sendBanner(human)
end

-- 充值接口
function onCharge(human, price, buyID, buyNum)
    for yyID, YYInfo in pairs(ID2YYInfo) do
        for i = 1, #YYInfo.config.funcs do
            local funcID = YYInfo.config.funcs[i]
            if YYInfo.moduleList[funcID] and YYInfo.moduleList[funcID].onCharge then
                YYInfo.moduleList[funcID].onCharge(human, price, funcID, buyID, buyNum)
            end
        end
    end

    sendBanner(human)
end

-- 0点
function onZeroHuman(human)
    for yyID, YYInfo in pairs(ID2YYInfo) do
        for i = 1, #YYInfo.config.funcs do
            local funcID = YYInfo.config.funcs[i]
            if YYInfo.moduleList[funcID] and YYInfo.moduleList[funcID].onZero then
                YYInfo.moduleList[funcID].onZero(human, funcID)
            end
        end
    end
    sendIcons(human)
end

-- 0点
function onZero()
    for yyID, YYInfo in pairs(ID2YYInfo) do
        for i = 1, #YYInfo.config.funcs do
            local funcID = YYInfo.config.funcs[i]
            if YYInfo.moduleList[funcID] and YYInfo.moduleList[funcID].onZeroAll then
                YYInfo.moduleList[funcID].onZeroAll(funcID)
            end
        end
    end

    handleAbs()
end

-- 整点刷新
function onHour(hour)
    -- 0点onZero 处理了
    if 0 == hour then
        return
    end

    print("[YunYingLogic-onHour] 开启处理整点 hour = "..hour)
    for yyID, YYInfo in pairs(ID2YYInfo) do
        for i = 1, #YYInfo.config.funcs do
            local funcID = YYInfo.config.funcs[i]
            if YYInfo.moduleList[funcID] and YYInfo.moduleList[funcID].onHour then
                YYInfo.moduleList[funcID].onHour(hour)
            end
        end
    end
end

-- 升级回调
function onLevelUp(human, oldLv, newLv)
    for yyID, YYInfo in pairs(ID2YYInfo) do
        for i = 1, #YYInfo.config.funcs do
            local funcID = YYInfo.config.funcs[i]
            if YYInfo.moduleList[funcID] and YYInfo.moduleList[funcID].onLevelUp then
                YYInfo.moduleList[funcID].onLevelUp(human, oldLv, newLv, funcID)
            end
        end
    end

    for yyID, YYInfo in pairs(ID2YYInfo) do
        if oldLv < YYInfo.openLv and YYInfo.openLv <= newLv then
            if isOpen(YYInfo, human, true) then
                sendIconUpdate(yyID, human)
            end
        end
    end

    sendBanner(human)
end


-- 购买礼包的回调
function onBuy(human, buyConf, isFirst, cnt, buyNum)
    for yyID, YYInfo in pairs(ID2YYInfo) do
        for i = 1, #YYInfo.config.funcs do
            local funcID = YYInfo.config.funcs[i]
            if YYInfo.moduleList[funcID] and YYInfo.moduleList[funcID][buyConf.cmd] then
                YYInfo.moduleList[funcID][buyConf.cmd](human, funcID, buyConf, isFirst, cnt, buyNum)
            end
        end
    end
end

function CG_YUNYING_UPDATE(human, yyID)
    if not human.yunyings then return end
    -- 未初始不发
    local YYInfo = ID2YYInfo[yyID]
    if not YYInfo then return end

    updateIcon(YYInfo, human, true)
end


function onServerOpenTime()
    handleAbs()
    
	for _, human in pairs(ObjHuman.onlineUuid) do
        sendIcons(human)
    end
end


---
--各个模块回调
function onCallBack(human, cmd, parameter, bNoSend, parameter2)
    for yyID, YYInfo in pairs(ID2YYInfo) do
        for i = 1, #YYInfo.config.funcs do
            local funcID = YYInfo.config.funcs[i]
            local funcConfig = getFuncConfig(funcID)
            if YYInfo.moduleList[funcID] and YYInfo.moduleList[funcID][cmd] then
                local isStart = true
                if isAbsfunc(funcID) then
                   isStart = AbsActLogic.isStarted(human, funcID)
                end

                if isStart then
                   local result = YYInfo.moduleList[funcID][cmd](human, funcID, parameter, parameter2)
                   if result then
                      updateIcon(YYInfo, human)
                      sendGroupUpdate(YYInfo, human, funcConfig.panelID)
                   end
                   if bNoSend then
                      return result
                   end
                end
            end
        end
    end
    if bNoSend then
       return 0
    end
end
