--种族试炼
--db
--[=[
    key 为种族类型
    human.db.RacialTrial = {
        [1] = {
            lv = nil,               --已经通关的层数
            dailyAwardCnt = nil,    --每日可领取奖励次数/每日可通关次数
        },
        [2] = {
            lv = nil,
            dailyAwardCnt = nil,
        }
    }
]=]--

local Msg = require("core.Msg")
local Util = require("common.Util")
local BagLogic = require("bag.BagLogic")
local CombatDefine = require("combat.CombatDefine")
local CombatLogic = require("combat.CombatLogic")
local HeroLogic = require("hero.HeroLogic")
local HeroConfig = require("excel.hero")
local Grid = require("bag.Grid")
local MonsterGrid = require("monster.MonsterGrid")
local Lang = require("common.Lang")
local Broadcast = require("broadcast.Broadcast")
local RoleSystemDefine = require("roleSystem.RoleSystemDefine")
local TriggerDefine = require("trigger.TriggerDefine")
local TriggerLogic = require("trigger.TriggerLogic")

--开启玩法的等级要求
local openCondLevel =  0
--每日最多可领奖次数
local dailyAwardTimes = 0
--种族试炼关卡数据,key为种族，value为该种族的关卡配置
-- local racialCfg = {
--     --[camp] = {},
--     --[camp] = {},
-- }

--日志Tag
local RACIALTRIALLOG = "racialTrial"


--种族 - 关卡开启时间映射表
--1-妖族， 2-人族， 3-兽族，4-仙、魔族
local RACIAL_OPENTIME = {
    [1] = {1,5,7},
    [2] = {2,5,7},
    [3] = {3,6,7},
    [4] = {4,6,7},
}

--战斗类型 - 种族映射表
local COMBATTYPE_CAMP = {
    [CombatDefine.COMBAT_TYPE25] = 1,
    [CombatDefine.COMBAT_TYPE26] = 2,
    [CombatDefine.COMBAT_TYPE27] = 3,
    [CombatDefine.COMBAT_TYPE28] = {4,5},
}

local function updateCondValue()
    local cfg = require("excel.shilianTower")
    if not cfg then
        return
    end
    local condCfg = cfg.main[1]
    openCondLevel = condCfg.openlv
    dailyAwardTimes = condCfg.maxrewardnum
end

--生成配置
-- local function generateCfg()
--     local cfg = require("excel.shilianTower")
--     if not cfg then
--         return
--     end

--     local stageCfg = cfg.shilianTower
--     racialCfg = { [1] = {}, [2] = {}, [3] = {}, [4] = {}}
--     local n1,n2,n3,n4 = 0,0,0,0
--     for _, v in ipairs(stageCfg) do
--         if v.raceID == 101 then
--             n1 = n1 + 1
--             racialCfg[1][n1] = v
--         elseif v.raceID == 102 then
--             n2 = n2 + 1
--             racialCfg[2][n2] = v
--         elseif v.raceID == 103 then
--             n3 = n3 + 1
--             racialCfg[3][n3] = v
--         elseif v.raceID == 104 then
--             n4 = n4 + 1
--             racialCfg[4][n4] = v
--         end
--     end
-- end

--通过种族类型获取配置
local function getCfgByCamp(human, camp)
    local cfgVec = require("excel.shilianTower").shilianTower
    if not cfgVec then
        return Broadcast.sendErr(human, Lang.COMMON_COMFIG_ERROR)
    end

    local config = {}
    local targetId = 0
    if camp == 1 then
        targetId = 101
    elseif camp == 2 then
        targetId = 102
    elseif camp == 3 then
        targetId = 103
    elseif camp == 4 then
        targetId = 104
    else
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end
    
    local len = #config
    for _, v in ipairs(cfgVec) do
        if v.raceID == targetId then
            len = len + 1
            config[len] = v
        end
    end

    if len == 0 then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end
    return config
end

--初始化数据
local function initData(human, camp)
    human.db.RacialTrial = human.db.RacialTrial or {}
    human.db.RacialTrial[camp] = {
        lv = 0,
        dailyAwardCnt = dailyAwardTimes
    }

end


--检测上阵英雄
function checkUpdatePos(human, msg)
    local combatType = msg.type
    local condi_camp  = COMBATTYPE_CAMP[combatType]
    if not condi_camp then
        return false
    end
    local heroList = Util.split(msg.heroList, ",")
    for i = 1, CombatDefine.COMBAT_HERO_CNT do
        local uuid = heroList[i] or ""
        if uuid ~= "0" and uuid ~= "" then
            local heroGrid = HeroLogic.getHeroGridByUuid(human, uuid)
            if not heroGrid then
                return false
            end

            --种族检测
            local heroCfg = HeroConfig.hero[heroGrid.id]
            if type(condi_camp) == "table" then
                local bl = false
                for _, camp in ipairs(condi_camp) do
                    if camp == heroCfg.camp then
                        bl = true
                        break
                    end
                end
                if not bl then
                    return false
                end
            else
                if condi_camp ~= heroCfg.camp then
                    return false
                end
            end
        end

    end
    return true
end

--红点检测
function isDot(human,config)
    if human.db.lv < config.dotLv then
        return false
    end

    local wday = Util.getWeekDay()
    --转成大家熟悉的表示法
    if wday == 1 then
        wday = 7
    else
        wday = wday - 1
    end

    --入口的红点
    if config.id == RoleSystemDefine.ROLE_SYS_ID_1210 then
        --如果当天一个试炼都没有开启，则入口也不显示红点
        local bl = false
        for _, v in ipairs(RACIAL_OPENTIME) do
            for _, v2 in ipairs(v) do
                if v2 == wday then
                    bl = true
                    break
                end
            end
            if bl then
                break
            end
        end

        if not bl then
            return false
        end

        if human.db.RacialTrial then
            local num = 0
            for camp, v in pairs(human.db.RacialTrial) do
                --local campCfg = racialCfg[camp]
                local campCfg = getCfgByCamp(human, camp)
                if v.dailyAwardCnt <= 0 or v.lv >= #campCfg then
                    num = num + 1
                end
            end
            if num >= #RACIAL_OPENTIME then
                return false
            end
        end
    else
        --具体某个种族关卡的红点
        local camp = 0
        if config.id == RoleSystemDefine.ROLE_SYS_ID_1211 then
            camp = 1
        elseif config.id == RoleSystemDefine.ROLE_SYS_ID_1212 then
            camp = 2
        elseif config.id == RoleSystemDefine.ROLE_SYS_ID_1213 then
            camp = 3
        elseif config.id == RoleSystemDefine.ROLE_SYS_ID_1214 then
            camp = 4
        else
            return false
        end

        --开启判断
        local bl = false
        local openDays = RACIAL_OPENTIME[camp]
        for _, v in ipairs(openDays) do
            if v == wday then
                bl = true
                break
            end
        end
        if not bl then
            return false
        end

        --当日奖励次数和最大关卡判断
        if human.db.RacialTrial and human.db.RacialTrial[camp] then
            local dailyAwardCnt = human.db.RacialTrial[camp].dailyAwardCnt
            local lv = human.db.RacialTrial[camp].lv
            --local campCfg = racialCfg[camp]
            local campCfg = getCfgByCamp(human, camp)
            if dailyAwardCnt <= 0 or lv >= #campCfg then
                return false
            end
        end
    end

    return true
end

--0点更新
function updateDaily(human)
    updateCondValue()
    if human.db.lv < openCondLevel then
        return
    end

    -- if not next(racialCfg) then
    --     generateCfg()
    -- end

    --重置每日领奖次数/每日通关次数
    if human.db and human.db.RacialTrial then
        for _, v in pairs(human.db.RacialTrial) do
            v.dailyAwardCnt = dailyAwardTimes
        end
    end
end


function onLogin(human)
    updateCondValue()
end

--GM 修改某个种族的关卡, levelCnt表示要往前/后打多少关，但是不增加每日领奖次数
function GmSetlevel(human, camp, levelCnt)
    if not camp or not levelCnt then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    local singleRacialCfg = getCfgByCamp(human, camp)
    --local singleRacialCfg = racialCfg[camp]
    if not singleRacialCfg then
        return Broadcast.sendErr(human, Lang.COMMON_COMFIG_ERROR)
    end

    if not human.db.RacialTrial or not human.db.RacialTrial[camp] then
        initData(human, camp)
    end

    local racialTrialData = human.db.RacialTrial[camp]
    if levelCnt > 0 then
        local startIdx = racialTrialData.lv
        if startIdx + levelCnt > #singleRacialCfg then
            levelCnt = #singleRacialCfg - startIdx
        end
        local endIdx = startIdx + levelCnt
        for i= startIdx+1, endIdx do
            local rewardCfg = singleRacialCfg[i].reward
            for _,v in ipairs(rewardCfg) do
                BagLogic.addItem(human, v[1], v[2], RACIALTRIALLOG)
            end
        end
    end
    racialTrialData.lv = math.max(racialTrialData.lv + levelCnt, 0)
end

--GM 开启某个种族的试炼
function GmOpenTrial(human, camp)
    if not camp then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end
    local wdDays = RACIAL_OPENTIME[camp]
    if not wdDays then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    local wday = Util.getWeekDay()
    if wday == 1 then
        wday = 7
    else
        wday = wday - 1
    end
    wdDays[#wdDays+1] = wday
end

--增加某个种族试炼关卡的每次奖励次数/通关数
function GmAddDailyAwardCnt(human, camp, num)
    if not camp or not num then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    if not human.db.RacialTrial or not human.db.RacialTrial[camp] then
        initData(human, camp)
    end

    local racialTrialData = human.db.RacialTrial[camp]
    racialTrialData.dailyAwardCnt = math.max(racialTrialData.dailyAwardCnt + num, 0)
end


--------------------------------------------------战斗相关------------------------------------
function getCombatMonsterOutID(human, side, args, combatType)
    if side ~= CombatDefine.DEFEND_SIDE then
        return
    end

    local camp = COMBATTYPE_CAMP[combatType]
    if type(camp) == "table" then
        camp = camp[1]
    end
    if not camp then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    local nowLelvel = 0
    if human.db.RacialTrial and human.db.RacialTrial[camp] then
        nowLelvel =  human.db.RacialTrial[camp].lv
    end

    local configVec = getCfgByCamp(human, camp)
    local config = configVec[nowLelvel+1]
    --local config = racialCfg[camp][nowLelvel+1]

    if not config then
        return Broadcast.sendErr(human, Lang.COMMON_COMFIG_ERROR)
    end
    return config.monsterOutID, config.zhandouli
end

function fight(human, args, combatType)
    local camp = COMBATTYPE_CAMP[combatType]
    if type(camp) == "table" then
        camp = camp[1]
    end
    if not camp then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    if human.db.RacialTrial and human.db.RacialTrial[camp] then
        local data = human.db.RacialTrial[camp]

        --当日没有挑战次数了
        if data.dailyAwardCnt and data.dailyAwardCnt <= 0 then
            return
        end

        --已经到最高层
        --local campCfg = racialCfg[camp]
        local campCfg = getCfgByCamp(human, camp)
        if data.lv and data.lv >= #campCfg then
            return Broadcast.sendErr(human, Lang.COMMON_MAXLEVEL)
        end
    end

    CombatLogic.combatBegin(human, nil, nil, combatType)
end

--战斗结束，未将战斗数据下发客户端前的处理
function onFightEnd(human, result, combatType, param1, combatInfo)
    --没赢就不需要处理
    if CombatDefine.RESULT_WIN ~= result then
        return
    end

    local camp = COMBATTYPE_CAMP[combatType]
    if type(camp) == "table" then
        camp = camp[1]
    end
    if not camp then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    if not human.db.RacialTrial or not human.db.RacialTrial[camp] then
        --胜利才更新数据
        initData(human, camp)
    end


    local data = human.db.RacialTrial[camp]
    data.lv = data.lv + 1
    data.dailyAwardCnt =  data.dailyAwardCnt - 1

    --local singleRacialCfg = racialCfg[camp]
    local singleRacialCfg = getCfgByCamp(human, camp)
    local rewardCfg = singleRacialCfg[data.lv].reward
    if not rewardCfg then
        return Broadcast.sendErr(human, Lang.COMMON_COMFIG_ERROR)
    end

    --已经到最高层或者当日可挑战次数已用完则不能继续挑战
    combatInfo.endParam = "1"
    if data.lv >= #singleRacialCfg or data.dailyAwardCnt <= 0 then
        combatInfo.endParam = "0"
    end

    --发放奖励
    combatInfo.rewardItem = {}
    for i=1, #rewardCfg do
        local itemID = rewardCfg[i][1]
        local itemCnt = rewardCfg[i][2]
        combatInfo.rewardItem[i] = combatInfo.rewardItem[i] or {}
        combatInfo.rewardItem[i] = {itemID, itemCnt}
        BagLogic.addItem(human, itemID, itemCnt, RACIALTRIALLOG)
    end

   TriggerLogic.PublishEvent(TriggerDefine.ZHONGZU_LEVEL, human.db._id, camp, 1)
end

--------------------------------------------------Respone------------------------------------

--入口查询
function entranceQuery(human)
    if human.db.lv < openCondLevel then
        return Broadcast.sendErr(human, Lang.COMMOM_NOT_ENABLED)
    end

    local wday = Util.getWeekDay()
    --转成大家熟悉的表示法
    if wday == 1 then
        wday = 7
    else
        wday = wday - 1
    end

    local msgRet = Msg.gc.GC_RACIALTRIAL_ENTRANCE_QUERY
    msgRet.list[0] = #RACIAL_OPENTIME

    for k,v in ipairs(RACIAL_OPENTIME) do
        msgRet.list[k].isOpen = 0
        msgRet.list[k].camp = k
        for _, day in ipairs(v) do
            if wday == day then
                msgRet.list[k].isOpen = 1
                msgRet.list[k].openWdays[0] = 0
                break
            end
        end
        if msgRet.list[k].isOpen == 0 then
            msgRet.list[k].openWdays[0] = #v
            for idx, val in ipairs(v) do
                msgRet.list[k].openWdays[idx] = val
            end
        end
    end
    Msg.send(msgRet, human.fd)
end

--单个种族关卡数据查询
function stageQuery(human, camp_m)
    if not camp_m then
        return Broadcast.sendErr(human, Lang.COMMON_ARGUMENT_ERROR)
    end

    if human.db.lv < openCondLevel then
        return Broadcast.sendErr(human, Lang.COMMOM_NOT_ENABLED)
    end

    local nowLv = 0
    local dailyAwardCnt = dailyAwardTimes
    if human.db.RacialTrial and human.db.RacialTrial[camp_m] then
        nowLv = human.db.RacialTrial[camp_m].lv
        dailyAwardCnt = human.db.RacialTrial[camp_m].dailyAwardCnt
    end

    local msgRet = Msg.gc.GC_RACIALTRIAL_LEVEL_QUERY
    msgRet.data.dailyAwardCnt = dailyAwardCnt

    --正常显示(当前关卡-1  ~  当前关卡+5) 的关卡
    local startIdx = nowLv - 1
    local endIdx = nowLv + 5

    --0层和第一层的的处理
    if nowLv <= 0 or nowLv == 1 then
        startIdx = 1
        endIdx = startIdx + 5
    end

    --local singleRecailCfg = racialCfg[camp_m]
    local singleRacialCfg = getCfgByCamp(human, camp_m)
    local levelMaxCnt = #singleRacialCfg

    --已经打到最高层的处理
    if nowLv >= levelMaxCnt then
        startIdx = nowLv - 5
        endIdx = nowLv
    elseif levelMaxCnt - nowLv < 5 then
        --local subLevel = levelMaxCnt - nowLv
        local subLevel = nowLv + 5 - levelMaxCnt
        startIdx = startIdx - subLevel
        endIdx = levelMaxCnt
    end

    --当前关卡前面不够5层的处理
    -- if levelMaxCnt - nowLv < 5 then
    --     --local subLevel = levelMaxCnt - nowLv
    --     local subLevel = nowLv + 5 - levelMaxCnt
    --     startIdx = startIdx - subLevel
    --     endIdx = levelMaxCnt
    -- end

    local stageData = msgRet.data.stageData
    stageData[0] = 0
    local cnt = 0
    for i = startIdx, endIdx do
        local singleCfg = singleRacialCfg[i]
        if not singleCfg then
            return
        end
        cnt = cnt + 1
        if i <= nowLv then
            stageData[cnt].isPass = 1
        elseif i == nowLv + 1 and dailyAwardCnt > 0 then --只能一关一关的挑战
            stageData[cnt].isPass = 2
        elseif i == nowLv + 1 and dailyAwardCnt <= 0 then --当日没有奖励次数了，但是还是需要显示挑战button
            stageData[cnt].isPass = 3
        else
            stageData[cnt].isPass = 0
        end

        stageData[cnt].power = 0
        stageData[cnt].levelIdex = i

        --奖励
        stageData[cnt].reward[0] = #singleCfg.reward
        for k, v in ipairs(singleCfg.reward) do
            Grid.makeItem(stageData[cnt].reward[k], v[1], v[2])
        end

        --怪物数据
        local objList = MonsterGrid.createMonsterObjListByMonsterOutID(singleCfg.monsterOutID)
        if not objList then
            return
        end
        stageData[cnt].monsterData[0] = #objList

        local power = 0
        for idx, monster in ipairs(objList) do
            stageData[cnt].monsterData[idx] = {
                lv = monster.lv,
                body = monster.body,
                camp = monster.camp,
            }
            power = power + (monster.power or 0)
        end
        stageData[cnt].power = power
    end
    stageData[0] = cnt
    Msg.send(msgRet, human.fd)
end