--
-- human.db.tower.tili
-- human.db.tower.ts
-- human.db.tower.rewards
-- human.db.tower.lv
-- human.db.tower.usetime

local Lang = require("common.Lang")
local Util = require("common.Util")
local Msg = require("core.Msg")
local LuaMongo = _G.lua_mongo
local DB = require("common.DB")
local ObjHuman = require("core.ObjHuman")
local HuanjingTowerExcel = require("excel.huanjingTower")
local MonsterExcel = require("excel.monster")
local Broadcast = require("broadcast.Broadcast")
local CombatDefine = require("combat.CombatDefine")
local CombatLogic = require("combat.CombatLogic")
local CombatVideo = require("combat.CombatVideo")
local BagLogic = require("bag.BagLogic")
local Grid = require("bag.Grid")
local ItemDefine = require("bag.ItemDefine")
local RoleSystemLogic = require("roleSystem.RoleSystemLogic")
local RoleSystemDefine = require("roleSystem.RoleSystemDefine")
local BattleLogic = require("battle.BattleLogic")
local ChatPaoMaLogic = require("chat.ChatPaoMaLogic")
local RoleLogic = require("role.RoleLogic")
local BRoleLogic = require("billboard.BRoleLogic")
local BillboardDefine = require("billboard.BillboardDefine")
local Log = require("common.Log")
local TuiSongLiBao = require("present.TuiSongLiBao")
local HuanjingTowerDB = require("huanjingTower.HuanjingTowerDB")
local VipLogic = require("vip.VipLogic")
local DailyTaskLogic = require("dailyTask.DailyTaskLogic")
local LiLianLogic = require("dailyTask.LiLianLogic")
local HeroGrid = require("hero.HeroGrid")
local BillboardDB = require("billboard.BillboardDB")
local BillboardDefine = require("billboard.BillboardDefine")
local BuyLogic = require("topup.BuyLogic")
local ChengjiuLogic = require("chengjiu.ChengjiuLogic")
local ChengjiuDefine = require("chengjiu.ChengjiuDefine")
local JibanLogic = require("combat.JibanLogic")
local RoleDBLogic = require("role.RoleDBLogic")
local MengxinLogic = require("present.MengxinLogic")
local YunYingLogic = require("yunying.YunYingLogic")
local GiftLogic = require("topup.GiftLogic")
local WarOrder = require("shop.WarOrder")
local TriggerLogic = require("trigger.TriggerLogic")
local TriggerDefine = require("trigger.TriggerDefine")
local TalismanLogic = require("talisman.TalismanLogic")


TOWER_LV_HEAD_MAX = 15 -- 每层 储存 玩家头像数据
TILI_MAX_CNT = 10 -- 最大体力
BUY_TILI_ITEM_ID = 102 -- 购买体力花费的物品ID
BUY_TILI_ITEM_CNT = 20 -- 购买一次体力所需的钻石
TILI_RECOVER_TIME = 1800 -- 体力恢复时间

BUY_TILI_BUY_ZUANSHI = {20, 30, 40}
TILI_FREE = 2 -- 每天最大 免费次数

-- 用于弹窗触发类型 @ma 是否需要同意定义枚举
local EVAL_TOWER_EVENT = 2
local DEVIL_ORDER_TYPE = 2

-- 奖励状态
REWARD_STATUS_NONE = 0 -- 不可领
REWARD_STATUS_GET = 1 -- 可领
REWARD_STATUS_HADGET = 2 -- 已领

TOWER_TONGGUAN_TYPE = 1 -- 通关奖励
TOWER_KING_TYPE = 2 -- 通关王者奖励

-- 每日最多可通关层数
local MAX_DAILY_PASSLEVEL_NUM = 50


--秘宝加成
local function HJ_GetTalismanAdd(human)
	local dailyFreeTimes = TalismanLogic.getTalismanAdd(human, TalismanLogic.OTHER_EFFECT_TBL.HJ_DAILY_Free) or 0
	return dailyFreeTimes
end

-- 获取每日通关层数
local function getDailyPassLevelNum(human)
    local num = 0
    if human.db.tower and human.db.tower.dailyPassLevelNum then
        num = human.db.tower.dailyPassLevelNum
    end

    return num
end

-- 增加每日通关层数
local function addDailyPassLevelNum(human, addNum)
    if not addNum or addNum <= 0 then
        return
    end

    human.db.tower = human.db.tower or {}
    human.db.tower.dailyPassLevelNum = (human.db.tower.dailyPassLevelNum or 0) + addNum
end

-- 重置每日通关层数
local function resetDailyPassLevelNum(human)
    if not human.db.tower or not human.db.tower.dailyPassLevelNum then
        return
    end

    human.db.tower.dailyPassLevelNum = 0
end

-- 跨天时, 对每日通关层数的处理
local function dailyPassLevelHandle(human)
    resetDailyPassLevelNum(human)
    HuanjingTower_DailyPassLevelInfo_Query(human)
end


function initSeverTower(nowLv)
    local towerDB = HuanjingTowerDB.query(#HuanjingTowerExcel.huanjingTower)
    if towerDB then
        return
    end
    local msg = {}
    nowLv = nowLv or 1
    for i = nowLv, #HuanjingTowerExcel.huanjingTower do
        local config = HuanjingTowerExcel.huanjingTower[i]
        if config then
            msg = {}
            msg.lv = i
            msg.combatVideo = {}
            msg.headNum = 0
            msg.headList = {}
            msg.roleNum = 0
            HuanjingTowerDB.addTower(msg)
        else
            break
        end
    end
end

-- 玩家修改 头像 后续处理
function changeHeadAfter(human)
    if not human.db.tower or not human.db.tower.lv then
        return
    end
    local data = HuanjingTowerDB.query(human.db.tower.lv)
    if checkTowerDBHaveByUuid(human.db._id, data) then
        local new = data.headList[human.db._id]
        new.head = human.db.head
        new.headFrame = human.db.headFrame
        HuanjingTowerDB.updateDB(data)
    end
end

-- 幻境之塔查询
function query(human)
    local flag, config = RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_1203)
    if flag ~= true then
        --return Broadcast.sendErr(human, Lang.HUANJINGTOWER_OPEN_NEED_LV)
        return Broadcast.sendErr(human, Util.format(Lang.COMMON_NEED_LEVEL, config.lv))
    end

    local msgRet = Msg.gc.GC_HUANGJINGTOWER_QUERY
    local buyCnt = getBuyCnt(human)
    msgRet.buyCost = BUY_TILI_BUY_ZUANSHI[buyCnt + 1] or BUY_TILI_BUY_ZUANSHI[1]
    msgRet.cnt = getCurCnt(human)
    msgRet.cntMax = getMaxCnt(human)
    local nowLv = 1
    if human.db.tower and human.db.tower.lv then
        nowLv = human.db.tower.lv + 1
    end

    msgRet.bEnd = 0
    local nConfLv = #HuanjingTowerExcel.huanjingTower
    if nConfLv < nowLv then
        msgRet.bEnd = 1
    end

    nowLv = math.min(nowLv, nConfLv)

    msgRet.mylv = nowLv
    local thisTowerConfig = HuanjingTowerExcel.huanjingTower[nowLv]
    if not thisTowerConfig then
        return
    end

    --- 等排行榜写完  读取前三

    msgRet.rank[0] = 0
    local board = BillboardDB.getBoard(BillboardDefine.TYPE_TOWER)
    if board then
        for k = 1, 3 do
            local rankData = board.rank2data[k]
            if rankData then
                msgRet.rank[0] = msgRet.rank[0] + 1
                local net = msgRet.rank[msgRet.rank[0]]
                if rankData and rankData.roleBase then
                    RoleLogic.makeRoleBase(rankData.roleBase, net.roleBase)
                else
                    local roleUuid = rankData and rankData.uuid or ""
                    RoleLogic.getRoleBaseByUuid(roleUuid, net.roleBase)
                end
                net.lv = rankData and rankData.value1 or 0
            end
        end
    end

    local cnt = 0
    local thisMax = nowLv + 28
    local thisMin = nowLv - 1

    if thisMin <= 0 then
        thisMin = 1
        thisMax = thisMin + 29
    elseif thisMax > #HuanjingTowerExcel.huanjingTower then
        thisMax = #HuanjingTowerExcel.huanjingTower
        thisMin = thisMax - 29
    end

    msgRet.canBuy = math.max(VipLogic.getPowerArgs(human, VipLogic.VIP_POWER3) - getBuyCnt(human), 0)
    msgRet.maxLv = #HuanjingTowerExcel.huanjingTower
    for i = thisMin, thisMax do
        local config = HuanjingTowerExcel.huanjingTower[i]
        cnt = cnt + 1
        msgRet.list[cnt].lv = i
        msgRet.list[cnt].head[0] = 0
        msgRet.list[cnt].reward[0] = 0
        msgRet.list[cnt].body = HeroGrid.getMonsterOutIDBody(config.monsterOutID)

        local data = HuanjingTowerDB.query(i)
        local have = data.roleNum
        have = have > 0 and have or 0
        have = have < 3 and have or 3

        for _, v in pairs(data.headList) do
            local head = v.head
            msgRet.list[cnt].head[0] = msgRet.list[cnt].head[0] + 1
            msgRet.list[cnt].head[msgRet.list[cnt].head[0]] = head
        end

        local len = 0
        if nowLv <= i then
            for j, h in ipairs(config.firstReward) do
                len = len + 1
                Grid.makeItem(msgRet.list[cnt].reward[len], h[1], h[2])
                msgRet.list[cnt].reward[0] = len
            end
        end
    end
    msgRet.list[0] = cnt
    msgRet.hasReward = isDotReward(human) and 1 or 0
    --	Msg.trace(msgRet)
    Msg.send(msgRet, human.fd)
end

function getRewardStatus(human, type, id, needLv)
    local lv = human.db.tower and human.db.tower.lv or 0
    if type == TOWER_KING_TYPE and (not human.db.tower or not human.db.tower.vip) then
        return REWARD_STATUS_NONE
    end

    if needLv > lv then
        return REWARD_STATUS_NONE
    end

    if isGetReward(human, type, id) then
        return isGetReward(human, type, id)
    end
    return REWARD_STATUS_NONE
end

--  通关奖励查询 or 冲塔王者 查询
function sendRewardQuery(human, type)
    local lv = human.db.tower and human.db.tower.lv or 0
    local msgRet = Msg.gc.GC_HUANGJINGTOWER_REWARD_QUERY
    msgRet.type = type
    msgRet.state = 1
    msgRet.kingNeed = HuanjingTowerExcel.towerKing[1].tower
    local config = HuanjingTowerExcel.tongGuan
    if type == 2 then
        config = HuanjingTowerExcel.towerKing
        msgRet.state = human.db.tower.vip and 1 or 0
    end
    msgRet.isEnd = 0
    msgRet.lvMax = 0
    msgRet.hasRed[0] = 0
    local len = 0
    for k, v in ipairs(config) do
        len = len + 1
        local net = msgRet.list[len]
        net.id = k
        net.status = getRewardStatus(human, type, k, v.tower)
        net.needLv = v.tower
        net.reward[0] = 0

        for j, h in ipairs(v.reward) do
            net.reward[0] = net.reward[0] + 1
            Grid.makeItem(net.reward[net.reward[0]], h[1], h[2])
        end
        if len >= 30 then
            msgRet.list[0] = len
            Msg.send(msgRet, human.fd)
            len = 0
        end
    end
    msgRet.list[0] = len
    msgRet.hasRed[0] = 0
    for i = 1, 2 do
        local isRed = isDotByType(human, i)
        if isRed then
            msgRet.hasRed[0] = msgRet.hasRed[0] + 1
            msgRet.hasRed[msgRet.hasRed[0]] = i
        end
    end
    msgRet.isEnd = 1
    msgRet.lvMax = lv
    --Msg.trace(msgRet)
    Msg.send(msgRet, human.fd)
end

-- 获取 奖励
function getReward(human, type, id)
    -- local config = HuanjingTowerExcel.tongGuan[id]
    -- local logStr = "tower_reward"
    -- if type == 2 then
    --     config = HuanjingTowerExcel.towerKing[id]
    --     logStr = "tower_king_reward"
    -- end

    local config = HuanjingTowerExcel.tongGuan
    local logStr = "tower_reward"
    if type == 2 then
        config = HuanjingTowerExcel.towerKing
        logStr = "tower_king_reward"
    end

    if not config then
        return
    end

    local tItem = {}
    for nID, v in ipairs(config) do
        local status = getRewardStatus(human, type, nID, v.tower)
        if REWARD_STATUS_GET == status then
            setGetReward(human, type, nID)
            for _, value in ipairs(v.reward) do
                if not tItem[value[1]] then
                    tItem[value[1]] = 0
                end

                tItem[value[1]] = tItem[value[1]] + value[2]
            end
        end
    end

    if nil == _G.next(tItem) then
        return
    end

    local tGoods = {}
    for nID, nNum in pairs(tItem) do
        table.insert(tGoods, {nID, nNum})
    end

    BagLogic.addItemList(human, tGoods, logStr)

    -- local status = getRewardStatus(human, type, id, config.tower)
    -- if status == REWARD_STATUS_NONE then
    --     return Broadcast.sendErr(human, Lang.YUNYING_GET_ERR_CONDITION)
    -- end
    -- if status == REWARD_STATUS_HADGET then
    --     return Broadcast.sendErr(human, Lang.YUNYING_GET_ERR_HADGET)
    -- end
    -- setGetReward(human, type, id)
    -- BagLogic.addItemList(human, config.reward, logStr)

    --- 此处 后续优化 不发送 sendRewardQuery
    --- GC_HUANGJINGTOWER_REWARD_GET 新增 type id 客户端 做处理更新界面  等客户端 有时间了改
    --sendRewardQuery(human, type)
    local msgRet = Msg.gc.GC_HUANGJINGTOWER_REWARD_GET
    msgRet.hasReward = isDotReward(human) and 1 or 0
    Msg.send(msgRet, human.fd)

    sendRewardQuery(human, type)

    RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1203)
    RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1201)
end

TOWER_KING_ALL_REWARD = nil
function unlockTowerKingQuery(human)
    if not human.db.tower then
        return
    end
    if human.db.tower.vip and human.db.tower.vip == 1 then
        return
    end

    local msgRet = Msg.gc.GC_HUANGJINGTOWER_KING_REWARD
    local config = HuanjingTowerExcel.towerKing[1]
    msgRet.reward[0] = config.activeReward

    for k, v in ipairs(config.activeReward) do
        Grid.makeItem(msgRet.reward[k], v[1], v[2])
    end

    if not TOWER_KING_ALL_REWARD then
        TOWER_KING_ALL_REWARD = {}
        local have = {}
        for k, v in ipairs(HuanjingTowerExcel.towerKing) do
            if have[v[1]] then
                local index = have[v[1]]
                TOWER_KING_ALL_REWARD[index].itemCnt = TOWER_KING_ALL_REWARD[index].itemCnt + v[2]
            else
                local tolal = TOWER_KING_ALL_REWARD[0] + 1
                TOWER_KING_ALL_REWARD[tolal] = {}
                TOWER_KING_ALL_REWARD[tolal].itemID = v[1]
                TOWER_KING_ALL_REWARD[tolal].itemCnt = v[2]
                TOWER_KING_ALL_REWARD[0] = tolal

                have[v[1]] = tolal
            end
        end
    end

    msgRet.allItem[0] = #TOWER_KING_ALL_REWARD
    for k, v in ipairs(TOWER_KING_ALL_REWARD) do
        Grid.makeItem(msgRet.allItem[k], v.itemID, v.itemCnt)
    end

    BuyLogic.fontBuyItem(human, msgRet.buyItem, config.buyID)
    Msg.send(msgRet, human.fd)
end

-- 解锁通关王者
function unlockTowerKing(human)
    if not human.db.tower then
        return
    end

    local config = HuanjingTowerExcel.towerKing[1]
    local kingNeed = config.tower

    if human.db.tower.lv < kingNeed then
        return
    end

    human.db.tower.vip = 1

    BagLogic.addItemList(human, config.activeReward, "tower_king_unlock")
    sendRewardQuery(human, TOWER_KING_TYPE)
end

function getSaoDangState(human, lv)
    local nowLv = 1
    if human.db.tower and human.db.tower.lv then
        nowLv = human.db.tower.lv + 1
    end

    if nowLv > lv then
        return 1
    end
    return 0
end

-- 战斗查询
function fightQuery(human, lv)
    local huanjingTowerConfig = HuanjingTowerExcel.huanjingTower[lv]
    if not huanjingTowerConfig then
        return
    end

    local buyCnt = getBuyCnt(human)

    local msgRet = Msg.gc.GC_HUANGJINGTOWER_FIGHT_QUERY
    msgRet.lv = lv
    msgRet.zhandouli = huanjingTowerConfig.zhandouli
    msgRet.isSaoDang = getSaoDangState(human, lv)
    msgRet.buyCost = BUY_TILI_BUY_ZUANSHI[buyCnt + 1] or BUY_TILI_BUY_ZUANSHI[1]
    msgRet.canBuy = math.max(VipLogic.getPowerArgs(human, VipLogic.VIP_POWER3) - getBuyCnt(human), 0)
    local monsterOutID = huanjingTowerConfig.monsterOutID
    local monsterOutConfig = MonsterExcel.monsterOut[monsterOutID]
    if not monsterOutConfig then
        assert()
    end

    local cnt = 0
    for key, member in ipairs(monsterOutConfig.member) do
        local value = member[1]
        if value ~= 0 then
            cnt = cnt + 1
            local tempMonsterConfig = MonsterExcel.monster[value]
            if not tempMonsterConfig then
                assert()
            end
            local other = {}
            other.lv = member[2]
            HeroGrid.makeHeroSimpleByMonsterID(msgRet.monsterList[cnt], value, other)
        end
    end
    msgRet.monsterList[0] = cnt

    for key, value in ipairs(huanjingTowerConfig.reward) do
        Grid.makeItem(msgRet.rewardList[key], value[1], value[2])
    end
    msgRet.rewardList[0] = #huanjingTowerConfig.reward
    msgRet.fristReward[0] = 0
    local myLv = human.db.tower and human.db.tower.lv or 0
    if myLv < lv then
        for j, h in ipairs(huanjingTowerConfig.firstReward) do
            Grid.makeItem(msgRet.fristReward[j], h[1], h[2])
        end
        msgRet.fristReward[0] = #huanjingTowerConfig.firstReward
    end

    Msg.send(msgRet, human.fd)
end

-- 扫荡挑战
function saodangDO(human, lv)
    local cnt = getCurCnt(human)

    if cnt < 1 then
        buyTiliDo(human)
        cnt = getCurCnt(human)
        if cnt < 1 then
            return
        end
    end
    local config = HuanjingTowerExcel.huanjingTower[lv]
    if not config then
        return
    end
    local myLv = human.db.tower and human.db.tower.lv or 0

    if myLv < lv then
        return
    end

    -- 增加次数
    addTili(human, 1)

    -- 发放奖励
    BagLogic.addItemList(human, config.reward, "tower_win_reward")
    DailyTaskLogic.recordDailyTaskFinishCnt(human, DailyTaskLogic.DAILY_TASK_ID_5, 1)
    YunYingLogic.onCallBack(human, "onHuangjingTower",1)   

    query(human)
    fightQuery(human, lv)
    RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1203)
    RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1201)
end

-- 一键扫荡
function oneClickSaodang(human)
    local cnt = getCurCnt(human)
    local buyCnt = getBuyCnt(human)
    local maxBuyCnt = VipLogic.getPowerArgs(human, VipLogic.VIP_POWER3)
    if cnt < 1 and buyCnt >= maxBuyCnt then
        return
    end

    local myLv = human.db.tower and human.db.tower.lv or 0
    if myLv < 1 then
        return
    end

    local config = HuanjingTowerExcel.huanjingTower[myLv]
    if not config then
        return
    end

    -- 先买次数
    local nCanBuyNum = maxBuyCnt - buyCnt
    if nCanBuyNum > 0 then
        local needZuanshi, nBuyCnt = 0, buyCnt
        for i = 1, nCanBuyNum, 1 do
            needZuanshi = needZuanshi + BUY_TILI_ITEM_CNT + nBuyCnt * 10
            nBuyCnt = nBuyCnt + 1
        end

        print("[oneClickSaodang] nCanBuyNum = "..nCanBuyNum..", needZuanshi = "..needZuanshi)
       
        if not ObjHuman.checkRMB(human, needZuanshi) then
            return Broadcast.sendErr(human, Lang.COMMON_NO_ZUANSHI)
        end
        ObjHuman.decZuanshi(human, -needZuanshi, "tower_buy_liti")

        addBuyCnt(human, nCanBuyNum)
    end

    local nNowCnt = getCurCnt(human)
    local tItem = {}
    for _, v in ipairs(config.reward) do
        local nGoodID = v[1]
        local nGoodNum = v[2] * nNowCnt

        table.insert(tItem, {nGoodID, nGoodNum})
    end

    if nil ~= _G.next(tItem) then
        addTili(human, nNowCnt)
        BagLogic.addItemList(human, tItem, "tower_win_reward")

        DailyTaskLogic.recordDailyTaskFinishCnt(human, DailyTaskLogic.DAILY_TASK_ID_5, nNowCnt)
        YunYingLogic.onCallBack(human, "onHuangjingTower",nNowCnt)

        query(human)
        fightQuery(human, myLv)
        RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1203)
        RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1201)
    end
end

-- 挑战
function fight(human, args)
    local currentPassLevelNum = getDailyPassLevelNum(human)
    if currentPassLevelNum >= MAX_DAILY_PASSLEVEL_NUM then
        return Broadcast.sendErr(human, Lang.COMMON_DAILY_PASSLEVEL_LIMIT)
    end

    local changeLv = tonumber(args[1] or 0)
    if changeLv > #HuanjingTowerExcel.huanjingTower then
        return
    end
    local isok, lv, config, count = checkCombatPos(human, args)
    if not isok then
        return
    end

    -- 调用战斗接口
    CombatLogic.combatBegin(human, config.mapID, args, CombatDefine.COMBAT_TYPE6, lv)
end

-- 获取当前地图ID
function getMapID(human, args)
    local isok, lv, config = checkCombatPos(human, args)
    if not isok then
        return
    end
    return config.mapID
end

-- 检查 战斗录像是否需要保存
function checkUpdeType(db, combatTime, zhandouli)
    local timeUp = combatTime
    local zhanliUp = zhandouli

    if db.combatVideo and db.combatVideo[1] and combatTime >= db.combatVideo[1].time then
        timeUp = 0
    end

    if db.combatVideo and db.combatVideo[2] and zhandouli >= db.combatVideo[2].zhandouli then
        zhanliUp = 0
    end
    return timeUp, zhanliUp
end

local function challengeWinHandle(human)
    addDailyPassLevelNum(human, 1)
    HuanjingTower_DailyPassLevelInfo_Query(human)
end


-- 挑战结束
function onFightEnd(human, result, fightTypeID, param, combatInfo, args)
    local rewardItem = combatInfo.rewardItem
    if fightTypeID ~= CombatDefine.COMBAT_TYPE6 then
        return
    end

    local huanjingTowerConfig = HuanjingTowerExcel.huanjingTower[param]
    if not huanjingTowerConfig then
        return
    end

    local oldLv = human.db.tower and human.db.tower.lv or 0
    -- 改db
    updateResult(human, result, combatInfo, param)

    local count = tonumber(args[2] or 0)
    combatInfo.endParam = tostring(count)

    -- 给奖励
    if CombatDefine.RESULT_WIN == result then
        local rewardList = {}
        for _, value in ipairs(huanjingTowerConfig.reward) do
            local itemID = value[1]
            local itemCnt = value[2]
            rewardList[itemID] = rewardList[itemID] or 0
            rewardList[itemID] = rewardList[itemID] + itemCnt
            BagLogic.addItem(human, itemID, itemCnt, "tower_win_reward")
            combatInfo.rewardItem[#combatInfo.rewardItem + 1] = {itemID, itemCnt}
        end

        oldLv = oldLv or 0
        if oldLv < param then
            for _, value in ipairs(huanjingTowerConfig.firstReward) do
                local itemID = value[1]
                local itemCnt = value[2]
                rewardList[itemID] = rewardList[itemID] or 0
                rewardList[itemID] = rewardList[itemID] + itemCnt
                BagLogic.addItem(human, itemID, itemCnt, "tower_win_reward")
                combatInfo.rewardItem[#combatInfo.rewardItem + 1] = {itemID, itemCnt}
            end
            GiftLogic.trigger(human,EVAL_TOWER_EVENT,{id = param})
            WarOrder.trigger(human,DEVIL_ORDER_TYPE)
        end

        --TODO:记录恶魔之塔
        --Log.write(Log.LOGID_OSS_BATTLE_DEMONTOWER, human.db._id, human.db.account, human.db.name, human.db.tower.lv)
        Log.write(Log.LOGID_OSS_BATTLE_DEMONTOWER, human.db._id, human.db.newUniqueTag, human.db.name, human.db.tower.lv)

        -- 挑战成功，则保存战斗信息
        combatInfo.defender.name = Util.format(Lang.COMBAT_TOWER_NAME, param)

        ChengjiuLogic.onCallback(human, ChengjiuDefine.CJ_TASK_TYPE_9, param)
        MengxinLogic.onCallBack(human, MengxinLogic.MX_TASK_TYPE_2, param)
        JibanLogic.onCallback(human, 3, param)
        DailyTaskLogic.recordDailyTaskFinishCnt(human, DailyTaskLogic.DAILY_TASK_ID_5, 1)
        YunYingLogic.onCallBack(human, "onHuangjingTower",1)

        challengeWinHandle(human)
    end
    LiLianLogic.onCallbackByCombat(human, combatInfo)
    RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1203)
    RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1201)
end

-- 获取该层 已存的 玩家头像数据条数
function getHeadNum(data)
    local len = 0
    if data.headList then
        for _, _ in pairs(data.headList) do
            len = len + 1
        end
    end
    return len
end

-- 检查该玩家在 该层塔 有 头像数据
function checkTowerDBHaveByUuid(uuid, data)
    if data.headList and data.headList[uuid] then
        return true
    end
    return false
end

-- 更新层数 头像
function towerHeadChange(human, oldLv, lv)
    if lv <= 1 then
        return
    end
    local data = HuanjingTowerDB.query(lv)
    local have = getHeadNum(data)

    if have < TOWER_LV_HEAD_MAX and not data.headList[human.db._id] then
        data.headList[human.db._id] = {}
        local new = data.headList[human.db._id]
        new.head = human.db.head
        new.headFrame = human.db.headFrame
        new.time = os.time()
        HuanjingTowerDB.updateDB(data)
    end

    if oldLv > 1 then
        local oldData = HuanjingTowerDB.query(oldLv)
        if checkTowerDBHaveByUuid(human.db._id, oldData) then
            oldData.headList[human.db._id] = nil
            HuanjingTowerDB.updateDB(oldData)
        end
    end
end

function queryFightData(human, towerId)
    local data = HuanjingTowerDB.query(towerId)
    if not data then
        return
    end

    local msgRet = Msg.gc.GC_HUANGJINGTOWER_QUERY_FIGHT_DATA
    msgRet.lv = towerId

    local len = 0
    for k, v in ipairs(data.combatVideo) do
        len = len + 1
        local net = msgRet.list[len]
        net.index = k
        net.zhanli = v.zhandouli
        net.time = v.time
        net.useTime = v.combatTime
        RoleLogic.getRoleBaseByUuid(v.uuid, net.roleBase)
    end
    msgRet.list[0] = len
    Msg.send(msgRet, human.fd)
end

function readFightVideo(human, towerId, index)
    local data = HuanjingTowerDB.query(towerId)
    if not data then
        return
    end
    if data.combatVideo and data.combatVideo[index] then
        local combatInfo = data.combatVideo[index].combatVideo
        combatInfo.isVideo = true
        --	combatInfo.videoUuid = videoUuid
        --	combatInfo.lookType = lookType
        human.combat = combatInfo
        CombatLogic.sendCombatData(human, combatInfo)
        CombatLogic.sendCombatFinish(human, combatInfo)
    end
end

-- 幻境之塔购买体力查询
function buyTiliQuery(human)
    local msgRet = Msg.gc.GC_HUANGJINGTOWER_BUY_TILI_QUERY
    local buyCnt = getBuyCnt(human)
    msgRet.needItemID = BUY_TILI_ITEM_ID
    msgRet.needItemCnt = BUY_TILI_ITEM_CNT + buyCnt * 10
    Msg.send(msgRet, human.fd)
end

-- 幻境之塔购买体力
function buyTiliDo(human, buyCnt)
    local buyCnt = getBuyCnt(human)
    local maxBuyCnt = VipLogic.getPowerArgs(human, VipLogic.VIP_POWER3)
    if buyCnt >= maxBuyCnt then
        return
    end
    local needZuanshi = BUY_TILI_ITEM_CNT + buyCnt * 10
    if not ObjHuman.checkRMB(human, needZuanshi) then
        return Broadcast.sendErr(human, Lang.COMMON_NO_ZUANSHI)
    end
    ObjHuman.decZuanshi(human, -needZuanshi, "tower_buy_liti")

    addBuyCnt(human, 1)
    local msgRet = Msg.gc.GC_HUANGJINGTOWER_BUY_TILI_DO
    local buyCnt = getBuyCnt(human)
    msgRet.buyCost = BUY_TILI_BUY_ZUANSHI[buyCnt + 1] or BUY_TILI_BUY_ZUANSHI[1]
    msgRet.cnt = getCurCnt(human)
    msgRet.canBuy = math.max(VipLogic.getPowerArgs(human, VipLogic.VIP_POWER3) - getBuyCnt(human), 0)
    Msg.send(msgRet, human.fd)
    --	query(human)
end

-- 每日通关信息查询
function HuanjingTower_DailyPassLevelInfo_Query(human)
    local msgRet = Msg.gc.GC_HUNAGJINGTOWER_DAILY_PASSLVEL_INFO_QUERY
    msgRet.currentPassLevelNum = getDailyPassLevelNum(human)
    msgRet.maxPassLevelNum = MAX_DAILY_PASSLEVEL_NUM
    Msg.send(msgRet, human.fd)
end

-- 挑战结果
function updateResult(human, result, combatInfo, param)
    -- 当前胜利关卡已通关
    if human.db.tower and human.db.tower.lv and human.db.tower.lv >= param then
        -- 增加挑战次数
        addTili(human, 1)
    end

    if result == CombatDefine.RESULT_WIN then
        human.db.tower = human.db.tower or {}
        human.db.tower.lv = human.db.tower.lv or 0
        local oldLv = human.db.tower.lv
        -- 当前胜利关卡未通关
        if oldLv < param then
            human.db.tower.lv = human.db.tower.lv + 1
            towerHeadChange(human, oldLv, human.db.tower.lv)

            TriggerLogic.PublishEvent(TriggerDefine.HUANJINGTOWER_PASS, human.db._id, 1)
        end
        human.db.tower.usetime = CombatLogic.getCombatUseTime(combatInfo)

        local data = HuanjingTowerDB.query(human.db.tower.lv)
        local zhandouli = combatInfo.attacker.zhandouli
        local timeUp, zhanliUp = checkUpdeType(data, human.db.tower.usetime, zhandouli) -- combatTime  , zhandouli

        local combatVideo = Util.copyTable(combatInfo)

        HuanjingTowerDB.addVideoToTower(
            data,
            human.db._id,
            os.time(),
            timeUp,
            zhanliUp,
            human.db.tower.usetime,
            zhandouli,
            combatVideo
        )
        HuanjingTowerDB.updateDB(data)

        -- 更新爬塔榜
        BRoleLogic.updateData(BillboardDefine.TYPE_TOWER, human.db)
    end
end

-- 更新动态数据
function updateDaily(human)
    if human.db.tower then
        human.db.tower.tili = 0
        human.db.tower.buyCnt = 0
        RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1203)
        RoleSystemLogic.onDot(human, RoleSystemDefine.ROLE_SYS_ID_1201)

        dailyPassLevelHandle(human)
    end
end

--处理无法完成新成就任务问题
function onLogin(human)
    if human.db.tower and human.db.tower.lv and human.db.tower.lv > 0 then
        ChengjiuLogic.onCallback(human, ChengjiuDefine.CJ_TASK_TYPE_9, human.db.tower.lv)
    end
end

function addBuyCnt(human, add)
    human.db.tower = human.db.tower or {}
    human.db.tower.buyCnt = human.db.tower.buyCnt or 0
    human.db.tower.buyCnt = human.db.tower.buyCnt + add
end

function addTili(human, add)
    human.db.tower = human.db.tower or {}
    human.db.tower.tili = human.db.tower.tili or 0
    human.db.tower.tili = human.db.tower.tili + add
end

-- 获取当前挑战次数
function getTili(human)
    if human.db.tower == nil or human.db.tower.tili == nil then
        return 0
    end
    return human.db.tower.tili
end

-- 获取购买次数
function getBuyCnt(human)
    if human.db.tower == nil or human.db.tower.buyCnt == nil then
        return 0
    end

    return human.db.tower.buyCnt
end

function getMaxCnt(human)
    local buyCnt = getBuyCnt(human)
    local dailyFreeTimes = HJ_GetTalismanAdd(human)
    return TILI_FREE + buyCnt + dailyFreeTimes
end

-- 获取剩余可挑战或者扫荡次数
function getCurCnt(human)
    local tili = getTili(human)
    local max = getMaxCnt(human)
    return max - tili
end

-- 读取 刷新玩家领取记录
function readUpdateGetDb(human, type)
    local db
    local getList
    if type == TOWER_TONGGUAN_TYPE and not human.towerTongGet then
        db = human.db.tower.tongGet
        human.towerTongGet = {}
        getList = human.towerTongGet
    elseif type == TOWER_KING_TYPE and not human.towerKingGet then
        db = human.db.tower.kingGet
        human.towerKingGet = {}
        getList = human.towerKingGet
    end

    if not db or db == "" then
        return
    end

    local list = Util.split(db, "|")
    for _, key in ipairs(list) do
        getList[tonumber(key)] = 1
    end
end

function isGetReward(human, type, id)
    if not human.db.tower then
        return
    end

    readUpdateGetDb(human, type)
    local db = {}
    if type == TOWER_TONGGUAN_TYPE then
        db = human.towerTongGet
    elseif type == TOWER_KING_TYPE then
        db = human.towerKingGet
    end
    if db and db[id] then
        return REWARD_STATUS_HADGET
    else
        return REWARD_STATUS_GET
    end
end

-- 领取奖励 存db
function setGetReward(human, type, id)
    human.db.tower = human.db.tower or {}
    readUpdateGetDb(human, type)

    if type == TOWER_TONGGUAN_TYPE then
        human.db.tower.tongGet = human.db.tower.tongGet or ""
        human.db.tower.tongGet = human.db.tower.tongGet .. id .. "|"
        human.towerTongGet[id] = 1
    elseif type == TOWER_KING_TYPE then
        human.db.tower.kingGet = human.db.tower.kingGet or ""
        human.db.tower.kingGet = human.db.tower.kingGet .. id .. "|"
        human.towerKingGet[id] = 1
    end
end

-- 检查是否有奖励可以领取
function checkHaveCanGetReward(human, type)
    if not human.db.tower or not human.db.tower.lv then
        return
    end
    local lv = human.db.tower.lv
    readUpdateGetDb(human, type)
    for k, config in ipairs(HuanjingTowerExcel.tongGuan) do
        if lv < config.tower then
            return
        end
        if isGetReward(human, type, k) == REWARD_STATUS_GET then
            return true, k
        end
    end
end

-- GM
function setTowerByGm(human, lv)
    if not lv or lv < 0 then
        return
    end
    local towerConfig = HuanjingTowerExcel.huanjingTower[lv]
    if not towerConfig then
        return
    end
    human.db.tower = human.db.tower or {}
    local oldLv = human.db.tower.lv or 0
    human.db.tower.lv = lv
    towerHeadChange(human, oldLv, lv)
    ChengjiuLogic.onCallback(human, ChengjiuDefine.CJ_TASK_TYPE_9, lv)
end

function isDot(human)
    if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_1203) then
        return
    end

    if getCurCnt(human) > 0 then
        return true
    end

    if not human.db.tower then
        return
    end
    local lv = human.db.tower.lv
    if not lv then
        return
    end
    if checkHaveCanGetReward(human, TOWER_TONGGUAN_TYPE) then
        return true
    end

    --[[	if human.db.tower.vip and human.db.tower.vip == 1 then
		local kingGetId = human.db.tower.kingGet or 0
		local config = HuanjingTowerExcel.towerKing[kingGetId + 1]
		if config and lv >= config.tower then
			return true 
		end
	end
	]]
    --
end

function isDotReward(human)
    if not human.db.tower then
        return
    end

    local lv = human.db.tower.lv
    if not lv then
        return
    end

    if checkHaveCanGetReward(human, TOWER_TONGGUAN_TYPE) then
        return true
    end

    --[[	if human.db.tower.vip and human.db.tower.vip == 1 then
		local kingGetId = human.db.tower.kingGet or 0
		local config = HuanjingTowerExcel.towerKing[kingGetId + 1]
		if config and lv >= config.tower then
			return true 
		end
	end
	]]
    --
end

function isDotByType(human, type)
    if not human.db.tower then
        return
    end

    local lv = human.db.tower.lv
    if not lv then
        return
    end

    if type == TOWER_TONGGUAN_TYPE then
        if checkHaveCanGetReward(human, TOWER_TONGGUAN_TYPE) then
            return true
        end
    elseif type == TOWER_KING_TYPE then
        if checkHaveCanGetReward(human, TOWER_KING_TYPE) then
            return true
        end
    end
end

local QueryRoleByTower = {}
function getAllHumanByLv(human, lv)
    local data = HuanjingTowerDB.query(lv)
    if not data then
        return
    end

    local msgRet = Msg.gc.GC_HUANGJINGTOWER_LV_ALLHUMAN
    local len = 0
    for uuid, _ in pairs(data.headList) do
        if len >= 10 then
            break
        end
        local db = RoleDBLogic.getDb(uuid, RoleLogic.FieldRoleBase)
        if db then
            len = len + 1
            RoleLogic.makeRoleBase(db, msgRet.role[len])
        end
    end

    msgRet.role[0] = len
    Msg.send(msgRet, human.fd)
end

--对外接口, 获取当前层数
function getTowerLevel(human)
    local lv = 0
    if human.db.tower then
        lv = human.db.tower.lv or 0
    end
    return lv
end

--------------------------------------------- combat ----------------------------------------------
function getCombatMonsterOutID(human, side, args)
    if side ~= CombatDefine.DEFEND_SIDE then
        return
    end
    local lv = tonumber(args[1] or 0)
    --	local lv = (human.db.tower and human.db.tower.lv or 0) + 1
    local config = HuanjingTowerExcel.huanjingTower[lv]
    if not config then
        return
    end
    return config.monsterOutID, config.zhandouli
end

function checkCombatPos(human, args)
    local lv = tonumber(args[1] or 0)
    local count = tonumber(args[2] or 0)
    local config = HuanjingTowerExcel.huanjingTower[lv]
    if not config then
        return
    end

    -- 判断挑战等级  不可越级挑战
    if lv > (human.db.tower and human.db.tower.lv or 0) + 1 then
        return Broadcast.sendErr(human, Lang.COPY_FIGHT_ERR_PREID)
    end

    -- 判断是否为 挑战已经通关的等级   已通关的关卡需要消耗次数
    if lv < (human.db.tower and human.db.tower.lv or 0) + 1 then
        local cnt = getCurCnt(human)
        if cnt < 1 then
            buyTiliDo(human)
            cnt = getCurCnt(human)
            if cnt < 1 then
                return Broadcast.sendErr(human, Lang.HUANJINGTOWER_NO_TILI_CNT)
            end
        end
    end
    -- 挑战不消耗次数
    --	if getCurCnt(human) < 1 then
    --	return Broadcast.sendErr(human, Lang.HUANJINGTOWER_NO_TILI_CNT)
    --	end
    return true, lv, config, count
end
