-- 诸神圣域(普通服)
-- 玩法: 开服>=29天, 角色等级>=100级即可参与。一共49个排名，初始时全部为机器人，玩家挑战成功可占领位置，并获得对应排名的称号。
-- 玩家没上榜，可以挑战榜上任何排名，玩家上榜后，只能挑战比玩家高的排名。

local Config = require("Config")
local MonsterExcel = require("excel.monster")
local MailExcel = require("excel.mail")
local RoleExcel = require("excel.role")
local Lang = require("common.Lang")
local Util = require("common.Util")
local Msg = require("core.Msg")
local HeroGrid = require("hero.HeroGrid")
local InnerMsg = require("core.InnerMsg")
local ObjHuman = require("core.ObjHuman")
local Broadcast = require("broadcast.Broadcast")
local CombatLogic = require("combat.CombatLogic")
local CombatDefine = require("combat.CombatDefine")
local CombatPosLogic = require("combat.CombatPosLogic")
local CombatVideo = require("combat.CombatVideo")
local RoleDefine = require("role.RoleDefine")
local RoleLogic = require("role.RoleLogic")
local RoleHeadLogic = require("role.RoleHeadLogic")
local RoleAttr = require("role.RoleAttr")
local RoleDBLogic = require("role.RoleDBLogic")
local MailManager = require("mail.MailManager")
local RoleSystemLogic = require("roleSystem.RoleSystemLogic")
local RoleSystemDefine = require("roleSystem.RoleSystemDefine")
local GodsAreaConfig = require("excel.godsArea")
local MiddleCommonLogic = require("middle.MiddleCommonLogic")
local HeroExcel = require("excel.hero")
local Log = require("common.Log")
local Timer = require("core.Timer")
local CommonDB = require("common.CommonDB")
local RoleSystemExcel = require("excel.roleSystem")
local Grid = require("bag.Grid")
local MonsterGrid = require("monster.MonsterGrid")

-- 战败通知邮件Id
local DEFAULT_MIAL_ID = 7021
-- 发奖励通知邮件Id
local REWARD_MAIL_ID = 7020

local REWARD_MAIL_ID2 = 7022

local FAIL_TAG = "fail"
local SUCC_TAG = "succ"


local MONSTER_SRV_NAME = "1服"
local SRV_BASE_NUM = 810537



MailQueue = {
    uidArray = {},
    insertMaxNum = 100, -- 一次最多插入数据库的邮件数量
    repeatMaxTimes = 3, -- 第一次失败后重试次数
    repeatTb = {}
}


local function checkLv(nowLv)
    local ctrlCfg = RoleSystemExcel.roleSystem[RoleSystemDefine.ROLE_SYS_ID_1305]
    if ctrlCfg.lv > nowLv then
        return false
    end

    return true
end

local function checkSvrOpenDays()
    local openDay = CommonDB.getServerOpenDay()
    local ctrlCfg = RoleSystemExcel.roleSystem[RoleSystemDefine.ROLE_SYS_ID_1305]
    if ctrlCfg.openSvrDay > openDay then
        return false
    end

    return true
end



-- 单个英雄数据
local function getHeroInfo(human, targetHeroUuid)
    local HeroLogic = require("hero.HeroLogic")
    local heroGrid = HeroLogic.getHeroGridByUuid(human, targetHeroUuid)
    if heroGrid then
        local heroCfg = HeroExcel.hero[heroGrid.id]
        local heroInfo = {
            heroUuid = targetHeroUuid,
            heroStar = heroGrid.star,
            heroLevel = heroGrid.lv,
            heroCamp =  heroGrid.camp or heroCfg.camp,
            heroBody = heroCfg.body
        }

        return heroInfo
    end
end

-- 获取上阵英雄数据
local function getHeroListInfo(human, targetHeroUuid)
    local len = 0
    local heroArr = {}

    local heroList = CombatPosLogic.getCombatHeros(human, CombatDefine.COMBAT_TYPE32)
    if not next(heroList) then
        heroList = CombatPosLogic.getCombatHeros(human, CombatDefine.COMBAT_TYPE1)
    end

    for _, heroUuid in pairs(heroList) do
        if not targetHeroUuid or targetHeroUuid == heroUuid then
            len = len + 1
            heroArr[len] = getHeroInfo(human, heroUuid)
        end
    end

    if len == 0 then
        return
    end
    return heroArr
end

-- 生成展示数据
local function generateShowInfo(human)
    local showInfo = {
        name = human.db.name,
        level = human.db.lv,
        uid = human.db._id,
        serverId = Config.SVR_INDEX,
        power = human.db.zhandouli,
    }

    showInfo.head = RoleHeadLogic.getRoleAppearance(human, RoleHeadLogic.HEAD_TYPE_1)
    showInfo.headFrame = RoleHeadLogic.getRoleAppearance(human, RoleHeadLogic.HEAD_TYPE_2)
    showInfo.body = RoleHeadLogic.getRoleAppearance(human, RoleHeadLogic.HEAD_TYPE_3)
    showInfo.heroList = getHeroListInfo(human)


    return showInfo
end

local function calcMOnsterPower(monsterOutID)
    local power = 0
    local objList = MonsterGrid.createMonsterObjListByMonsterOutID(monsterOutID)
    if not objList then
        return power
    end

    for _, monster in ipairs(objList) do
        power = power + (monster.power or 0)
    end

    return power
end

local function getPlayerSrvIdx(human)
    local newUniqueTag = human.db.newUniqueTag
    local tbl = Util.split(newUniqueTag, "|")
    return tbl[2]
end

local function getRankReward(rank)
    local rewardCfg = GodsAreaConfig.reward
    if not rank then
        return rewardCfg[#rewardCfg].awardList
    end


    for k,v in ipairs(GodsAreaConfig.reward) do
        if rank >= v.rankArea[1] and rank <= v.rankArea[2] then
            return v.awardList
        end
    end
end

local function getCorrectUuidArray(uid2RankTb)
    local DataCache = require("core.DataCache")
    local playerUidList = DataCache.Get_PlayerUuidList()

    local len = 0
    local uidArray = {}

    for uid, rank in pairs(uid2RankTb or {}) do
        len = len + 1
        uidArray[len] = {uid, rank}
    end

    for uid, lv in pairs(playerUidList or {}) do
        if not uid2RankTb or not uid2RankTb[uid] then
            if checkLv(lv) then
                len = len + 1
                uidArray[len] = {uid}
            end
        end
    end

    if len == 0 then
        return
    end

    return uidArray
end

local function writeLog(logStr)
    Log.write(Log.LOGID_OSS_GODSAREA_MAIL, logStr)
end

local function sendMail(mailId, receiverUuid, itemArray, arg)
    if not mailId or not receiverUuid then
        return
    end

    local mailCfg = MailExcel.mail[mailId]
    local content = mailCfg.content
    if arg then
        content = Util.format(content, arg)
    end
    MailManager.add(MailManager.SYSTEM, receiverUuid, mailCfg.title, content, itemArray, mailCfg.senderName or "GM")
end






-- local function timed_clear_videoCache(playerUid)
--     local human = ObjHuman.onlineUuid[playerUid]
--     if not human then
--         return
--     end

--     human.GodsAreaVideoArray = nil
-- end


-- GM,清理所有诸神圣域的称号
function GM_ClearChenghao(human)
    for _, rankCfg in ipairs(GodsAreaConfig.rankList) do
        RoleHeadLogic.unActive(human.db._id, RoleHeadLogic.HEAD_TYPE_4, rankCfg.chenghaoID)
    end
end

function isOpen(human)
    return RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_1305)
end

-- 获取角色身上属于本系统功能特有的称号ID
function GetPlayingMethonChenghao(human)
    local chenghaoList = RoleHeadLogic.GetRoleAdornInfo(human, RoleHeadLogic.HEAD_TYPE_4)
    if not chenghaoList then
        return
    end

    for _, rankCfg in ipairs(GodsAreaConfig.rankList) do
        if chenghaoList[rankCfg.chenghaoID] then
            return rankCfg.chenghaoID
        end
    end
end

-- 玩家更新展示信息
-- showType: 1-改名, 2-升级 3-头像, 4-头像框，5-形象
function UpdateShowData(human, showType)
    if not isOpen(human) then
        return
    end

    if not GetPlayingMethonChenghao(human) then
        return
    end

    if showType < 1 or showType > 5 then
        return
    end

    local playerInfo = {}
    if showType == 1 then
        playerInfo.name = human.db.name
    elseif showType == 2 then
        playerInfo.level = human.db.lv
    elseif showType == 3 then
        playerInfo.head = RoleHeadLogic.getRoleAppearance(human, RoleHeadLogic.HEAD_TYPE_1)
    elseif showType == 4 then
        playerInfo.headFrame = RoleHeadLogic.getRoleAppearance(human, RoleHeadLogic.HEAD_TYPE_2)
    elseif showType == 5 then
        playerInfo.body = RoleHeadLogic.getRoleAppearance(human, RoleHeadLogic.HEAD_TYPE_3)
    end

    UpdatePlayerBaseInfo(human, playerInfo)
end

-- 更新玩家英雄数据
-- 参数heroUuid, opType 都没有时标识更新全部英雄数据
-- opType: 操作类型, 0-删除, 1-更新单个英雄数据, 2- 更新所有英雄数据
function UpdateHeroData(human, heroUuid, opType)
    if not isOpen(human) then
        return
    end

    if not GetPlayingMethonChenghao(human) then
        return
    end

    local heroInfoList = {opType = 1}
    if opType and opType == 0 then
        heroInfoList.opType = 0
        heroInfoList.removeHeroUuid = heroUuid
    else
        if not opType and not heroUuid then
            heroInfoList.opType = 2
        end

        heroInfoList.heroList = getHeroListInfo(human, heroUuid)
        if not heroInfoList.heroList then
            return
        end
    end

    UpdatePlayerHeroInfo(human, heroInfoList)
end


function MailQueue:add(playerInfo)
    table.insert(self.uidArray, playerInfo)
end

function MailQueue:clear()
    Util.cleanTable(self.uidArray)
    Util.cleanTable(self.repeatTb)
end

function MailQueue:insertDB()
    local defaultRank = 999
    local maxNum = math.min(self.insertMaxNum, #self.uidArray)
    local defaultAward = getRankReward(defaultRank)

    for i=1, maxNum do
        local resTag = SUCC_TAG
        local playerInfo = table.remove(self.uidArray)
        local uid = playerInfo[1]
        local rank = playerInfo[2]
        local awardArray = defaultAward
        local mailId = REWARD_MAIL_ID2
        if rank then
            mailId = REWARD_MAIL_ID
            awardArray = getRankReward(rank)
        end

        local ok, err = pcall(sendMail, mailId, uid, awardArray, rank)
        if not ok then
            if not self.repeatTb[uid] or self.repeatTb[uid] < self.repeatMaxTimes then -- 插入失败后，最多重新插入3次
                MailQueue:add(playerInfo)
                self.repeatTb[uid] = (self.repeatTb[uid] or 0) + 1
            end

            resTag = FAIL_TAG
        end

        local str = string.format("发放奖励结果: %s, 玩家uid: %s, 排名: %d, 失败次数: %d, errInfo: %s",
        resTag, uid, rank or defaultRank, self.repeatTb[uid] or 0, err)
        writeLog(str)
    end

    if #self.uidArray > 0 then
        Timer.addLater(3, MailQueue.insertDB, MailQueue)
    end
end




-- 查询排行榜信息
function Query_RankList(human)
    if not isOpen(human) then
        return Broadcast.sendErr(human, Lang.COMMOM_NOT_ENABLED)
    end

    local msgData = InnerMsg.lw.LW_GODSATREA_QUERY_RANKLIST
    msgData.playerUid = human.db._id
    msgData.sourceServerId = Config.SVR_INDEX
    InnerMsg.sendMsg(0, msgData)
end

-- 查看某个玩家具体信息
function Query_PlayerInfo(human, targetRank, targetUid)
    if not isOpen(human) then
        return Broadcast.sendErr(human, Lang.COMMOM_NOT_ENABLED)
    end

    if targetRank <= 0 or targetRank > #GodsAreaConfig.rankList then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    local msgData = InnerMsg.lw.LW_GODSATREA_QUERY_PLAYER_INFO
    msgData.sourceServerId = Config.SVR_INDEX
    msgData.targetRank = targetRank
    msgData.targetUid = targetUid
    msgData.playerUid = human.db._id

    InnerMsg.sendMsg(0, msgData)
end

-- 向跨服查询能否挑战某个排名
function Query_Challenge(human, defenseRank, defenseUid)
    if defenseRank <= 0 or defenseRank > #GodsAreaConfig.rankList then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    local msgData = InnerMsg.lw.LW_GODSATREA_CHALLENGE_QUERY
    msgData.sourceServerId = Config.SVR_INDEX
    msgData.defenseRank = defenseRank
    msgData.defenseUid = defenseUid
    msgData.attackerUid = human.db._id

    InnerMsg.sendMsg(0, msgData)
end

-- 通知跨服，挑战胜利
function Challenge_Win(human)
    local challengeInfo = human.godsArea_CombatInfo

    local msgData = InnerMsg.lw.LW_GODSATREA_WIN
    msgData.sourceServerId = Config.SVR_INDEX
    msgData.defenseRank = challengeInfo.defenseRank
    msgData.defenseUid = challengeInfo.defenseUid
    msgData.attackerUid = human.db._id
    msgData.attackInfo = {}

    local chenghaoId = GetPlayingMethonChenghao(human)
    if not chenghaoId then -- 没有排名时挑战成功, 则把展示数据发给跨服。如果有时许问题，则每次挑战都发给跨服
        msgData.attackInfo = generateShowInfo(human)
    end

    InnerMsg.sendMsg(0, msgData)
end

-- 查看某个名次的战斗录像
function Query_CombatVideo(human, targetRank)
    if not isOpen(human) then
        return Broadcast.sendErr(human, Lang.COMMOM_NOT_ENABLED)
    end

    if targetRank <= 0 or targetRank > #GodsAreaConfig.rankList then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    local msgData = InnerMsg.lw.LW_GODSATREA_QUERY_RANK_VIDEO
    msgData.playerUid = human.db._id
    msgData.targetRank = targetRank
    msgData.sourceServerId = Config.SVR_INDEX

    InnerMsg.sendMsg(0, msgData)
end

-- 通知跨服, 更新玩家角色数据
function UpdatePlayerBaseInfo(human, newPlayerInfo)
    local msgData = InnerMsg.lw.LW_GODSATREA_UPDATE_PLAYER_BASE_INFO
    msgData.playerUid = human.db._id
    msgData.playerInfo = newPlayerInfo or {}

    InnerMsg.sendMsg(0, msgData)
end

-- 通知跨服, 更新玩家英雄数据
function UpdatePlayerHeroInfo(human, newPlayerInfo)
    local msgData = InnerMsg.lw.LW_GODSATREA_UPDATE_PLAYER_HERO_INFO
    msgData.playerUid = human.db._id
    msgData.power = human.db.zhandouli
    msgData.heroInfo = newPlayerInfo or {}

    InnerMsg.sendMsg(0, msgData)
end

-- 客户端请求排行榜奖励
function Query_RankReward(human)
    local msgRet = Msg.gc.GC_GODSAREA_GET_RANK_REWARD
    local rewardList = msgRet.rewardList
    rewardList[0] = 0

    for k,v in ipairs(GodsAreaConfig.reward) do
        rewardList[0] = k
        rewardList[k].rankLeft = v.rankArea[1]
        rewardList[k].rankRight = v.rankArea[2]

        local itemList = rewardList[k].itemList
        itemList[0] = 0
        for idx, itemCfg in ipairs(v.awardList) do
            itemList[0] = idx
            Grid.makeItem(itemList[idx], itemCfg[1], itemCfg[2])
        end
    end

    Msg.send(msgRet, human.fd)
end





-- 收到跨服发送的排行数据
function NS_Send_RankList(playerUid, myRank, rankList)
    local human = ObjHuman.onlineUuid[playerUid]
    if not human then
        return
    end

    local srvIdx = getPlayerSrvIdx(human)
    local msgRet = Msg.gc.GC_GODSAREA_QUERY_RANKLIST
    msgRet.myRank.body = RoleHeadLogic.getRoleAppearance(human, RoleHeadLogic.HEAD_TYPE_3)
    msgRet.myRank.name = human.db.name
    msgRet.myRank.uid = playerUid
    msgRet.myRank.rank = myRank
    msgRet.myRank.power = human.db.zhandouli or 0
    msgRet.myRank.serverName = srvIdx .. "服"
    msgRet.myRank.head = RoleHeadLogic.getRoleAppearance(human, RoleHeadLogic.HEAD_TYPE_1)
    msgRet.myRank.headFrame = RoleHeadLogic.getRoleAppearance(human, RoleHeadLogic.HEAD_TYPE_2)

    msgRet.attrs[0] = 0
    if myRank ~= 0 then
        local rankCfg = GodsAreaConfig.rankList[myRank]
        local chenghaoCfg = RoleExcel.chenghao[rankCfg.chenghaoID]

        for k, v in ipairs(chenghaoCfg.attrs) do
            msgRet.attrs[0] = k
            msgRet.attrs[k].key = v[1]
            msgRet.attrs[k].value = v[2]
        end
    end


    local msgRankList = msgRet.rankList
    msgRankList[0] = 0

    for rank, playerInfo in ipairs(rankList) do
        msgRankList[0] = rank
        msgRankList[rank].body = playerInfo.body
        msgRankList[rank].name = playerInfo.name
        msgRankList[rank].rank = rank
        msgRankList[rank].head = playerInfo.head
        msgRankList[rank].headFrame = playerInfo.headFrame

        if playerInfo.uid then -- 真实玩家
            msgRankList[rank].uid = playerInfo.uid
            msgRankList[rank].power = playerInfo.power or 999999
            local playerServerIdx  = math.max((playerInfo.serverId or 0) - SRV_BASE_NUM, 1)
            msgRankList[rank].serverName = playerServerIdx .. "服"
        else
            local npcCfg = GodsAreaConfig.rankList[rank]
            local monsterOutID = npcCfg.monsterOutID
            msgRankList[rank].uid = tostring(monsterOutID)
            msgRankList[rank].power = calcMOnsterPower(monsterOutID)
            msgRankList[rank].serverName = MONSTER_SRV_NAME
        end
    end

    Msg.send(msgRet, human.fd)
end

-- 收到跨服发送的玩家数据
function NS_Send_PlayerInfo(playerUid, res, playerInfo)
    local human = ObjHuman.onlineUuid[playerUid]
    if not human then
        return
    end

    if res == -1 then
        return Broadcast.sendErr(human, Lang.DATA_ERR)
    end

    if res == -2 then
        return Broadcast.sendErr(human, Lang.DATA_OLD)
    end

    local msgRet = Msg.gc.GC_GODSAREA_GET_PLAYER_INFO
    msgRet.name = playerInfo.name
    msgRet.lv = playerInfo.lv
    msgRet.head = playerInfo.head
    msgRet.headFrame = playerInfo.headFrame


    local rankCfg = GodsAreaConfig.rankList[playerInfo.rank]
    local chenghaoCfg = RoleExcel.chenghao[rankCfg.chenghaoID]


    msgRet.attrs[0] = 0
    for k, v in ipairs(chenghaoCfg.attrs) do
        msgRet.attrs[0] = k
        msgRet.attrs[k].key = v[1]
        msgRet.attrs[k].value = v[2]
    end

    local len = 0
    msgRet.defendObjList[0] = 0
    if playerInfo.defendObjList then
        for idx, heroInfo in pairs(playerInfo.defendObjList) do
            len = len + 1
            msgRet.defendObjList[len].body = heroInfo.heroBody or 0
            msgRet.defendObjList[len].camp = heroInfo.heroCamp or 0
            msgRet.defendObjList[len].lv = heroInfo.heroLevel or 0
            msgRet.defendObjList[len].star = heroInfo.heroStar or 0
        end
        msgRet.defendObjList[0] = len
    else
        local monsterOutConfig = MonsterExcel.monsterOut[rankCfg.monsterOutID]
        for idx, monsterInfo in ipairs(monsterOutConfig.member) do
            msgRet.defendObjList[0] = idx

            local monsterID = monsterInfo[1]
            local mcf = MonsterExcel.monster[monsterID]
            msgRet.defendObjList[idx].body = mcf.body
            msgRet.defendObjList[idx].camp = mcf.camp
            msgRet.defendObjList[idx].lv = monsterInfo[2]
            msgRet.defendObjList[idx].star = mcf.star
        end
    end

    msgRet.rank = playerInfo.rank
    msgRet.uid = playerInfo.uid or tostring(rankCfg.monsterOutID)

    Msg.send(msgRet, human.fd)
end

-- 跨服通知能否挑战的结果
function Query_Challenge_Result(playerUid, res, defenseServerId, defenseRank, defenseUid, defenseName)
    local human = ObjHuman.onlineUuid[playerUid]
    if not human then
        return
    end

    if res == -1 then
        return Broadcast.sendErr(human, Lang.DATA_ERR)
    end

    if res == -2 then
        return Broadcast.sendErr(human, Lang.DATA_OLD)
    end

    if res == -3 then
        return Broadcast.sendErr(human, Lang.CHALLENGE_STRONG_ONE)
    end

    if res == 1 then
        Broadcast.sendErr(human, Lang.CHALLENGING_SELF)
    end

    if res == 2 then
        Broadcast.sendErr(human, Lang.CHALLENGING_TARGET)
    end

    human.godsArea_CombatInfo = {
        defenseRank = defenseRank,
        defenseUid = defenseUid,
        defenseName = defenseName,
    }


    if tonumber(defenseUid) then -- 被挑战方是机器人
        CombatLogic.combatBegin(human, nil, {human.db._id, defenseRank }, CombatDefine.COMBAT_TYPE32)
    else
        local msg = {
            combatType = CombatDefine.COMBAT_TYPE32,
            nServerIndex = defenseServerId,
            param = defenseUid
        }
        MiddleCommonLogic.MiddleCommonLogic_CombatBegin_LW(human, msg)
    end
end

-- 收到跨服通知, 更换新的称号
function NS_Change_Chenghao(playerUid, newRank, isWinner, enemyName)
    local human = ObjHuman.onlineUuid[playerUid]
    if not human then
        local db = RoleDBLogic.getDb(playerUid)
        if not db then
            return
        end

        human = {}
        human.db = db
    end

    -- 删除原有的称号
    local chenghaoId = GetPlayingMethonChenghao(human)
    if chenghaoId then
        -- RoleHeadLogic.unActive(playerUid, RoleHeadLogic.HEAD_TYPE_4, chenghaoId)
        if human.db.chenghaoList and human.db.chenghaoList[chenghaoId] then
            human.db.chenghaoList[chenghaoId] = nil
        end

        if human.db.chenghao and human.db.chenghao == chenghaoId then
            human.db.chenghao = nil
        end
    end

    -- 获得称号
    local rankCfg = GodsAreaConfig.rankList[newRank]
    if rankCfg then
        RoleHeadLogic.active(human, RoleHeadLogic.HEAD_TYPE_4, rankCfg.chenghaoID)
    end

    -- 如果是失败方, 发邮件通知
    if isWinner == 0 then
        sendMail(DEFAULT_MIAL_ID, human.db._id, nil, enemyName)
    end

    ObjHuman.save(human)

    -- 如果在线, 更新战力
    if ObjHuman.onlineUuid[playerUid] then
        RoleAttr.cleanHeroAttrCache(human)
        RoleAttr.doCalc(human)
        ObjHuman.sendAttr(human, RoleDefine.ZHANDOULI)
    end
end

-- 跨服返回录像数据
function NS_Query_CombatVideo(isFinish, playerUid, videoData)
    local human = ObjHuman.onlineUuid[playerUid]
    if not human then
        return
    end


    if next(videoData) then
        if not human.GodsAreaVideoArray then
            human.GodsAreaVideoArray = {}
            -- Timer.addLater(3, timed_clear_videoCache, playerUid)
        end

        human.GodsAreaVideoArray[#human.GodsAreaVideoArray+1] = videoData

        if isFinish == 0 then
            return
        end
    end


    local msgRet = Msg.gc.GC_GODSAREA_QUERY_COMBATVIDEO
    msgRet.videoList[0] = 0
    local videoCnt = human.GodsAreaVideoArray and #human.GodsAreaVideoArray or 0

    for i = 1, videoCnt do
        if msgRet.videoList[0] < #msgRet.videoList then
            msgRet.videoList[0] = i
            local combatVideo = human.GodsAreaVideoArray[i]
            local combatInfo = combatVideo.combatInfo
            local net = msgRet.videoList[i]
            RoleLogic.makeRoleBase(combatInfo.attacker, net.atkData)

            net.heroList[0] = 0
            for _,pos in ipairs(CombatDefine.SIDE2POS[CombatDefine.ATTACK_SIDE]) do
                local grid = combatInfo.objList and combatInfo.objList[pos]
                if grid and grid.id ~= 0 then
                    net.heroList[0] = net.heroList[0] + 1
                    local index = net.heroList[0]
                    HeroGrid.makeHeroInfo(net.heroList[index], grid)
                end
            end

            net.videoUuid = combatVideo._id
            net.time = combatInfo.time
            net.result = combatInfo.isWin == true and 1 or 0
            local formationConfig = CombatPosLogic.getFormationConfig(combatInfo.atkFormation)
            net.formation = formationConfig.name
        end
    end

    human.GodsAreaVideoArray = nil

    Msg.send(msgRet, human.fd)
end

--收到通知，给玩家发奖
function NS_SendReward(uid2RankTb)

    if not checkSvrOpenDays() then
        return
    end

    local correctUuidArray = getCorrectUuidArray(uid2RankTb)
    if not correctUuidArray then
        return
    end

    MailQueue:clear()

    for _, playerInfo in ipairs(correctUuidArray) do
        MailQueue:add(playerInfo)
    end

    MailQueue:insertDB()
end

-- 收到跨服通知，更新玩家基础数据
function NS_UpdatePlayerBaseInfo(playerUid)
    local human = ObjHuman.onlineUuid[playerUid]
    if not human then
        local db = RoleDBLogic.getDb(playerUid)
        if not db then
            return
        end

        human = {}
        human.db = db
    end

    local msgData = InnerMsg.lw.LW_GODSATREA_UPDATE_PLAYER_BASE_INFO
    msgData.playerUid = human.db._id
    msgData.playerInfo = generateShowInfo(human)
    msgData.playerInfo.heroList = nil

    InnerMsg.sendMsg(0, msgData)
end




function getCombatObjList(human, side, args, combatType)
    if side == CombatDefine.ATTACK_SIDE and not human then return end

    if side == CombatDefine.DEFEND_SIDE and human then
        return
    end

    if not human then
        local uuid = args[1]
        local db = RoleDBLogic.getDb(uuid)
        if not db then
            return
        end
        human = {}
        human.db = db
    end

    local heroList = CombatPosLogic.getCombatHeros(human, combatType)
    if next(heroList) then
        return CombatLogic.getHumanObjList(human, combatType)
    else
        return CombatLogic.getHumanObjList(human, CombatDefine.COMBAT_TYPE1)
    end
end

function getCombatMonsterOutID(human, side, args)
    if side ~= CombatDefine.DEFEND_SIDE then return end

    local rank = args[2]
    local rankCfg = GodsAreaConfig.rankList[rank]
    return rankCfg.monsterOutID
end

function onFightEnd(human, result, type, cbParam, combatInfo)
    local godsArea_CombatInfo = human.godsArea_CombatInfo
    if not godsArea_CombatInfo then
        return Broadcast.sendErr(human, Lang.DATA_ERR)
    end

    if result == CombatDefine.RESULT_WIN then
        Challenge_Win(human)
    end

    combatInfo.time = os.time()
    combatInfo.defender.name = godsArea_CombatInfo.defenseName
    CombatVideo.NS_Video_Save(CombatVideo.VIDEOTYPE_GODSAREA, combatInfo, {rank = godsArea_CombatInfo.defenseRank})
end
