-----------------------------------------------------------
-- 星空争霸/王者争霸
-----------------------------------------------------------
local MonsterExcel = require("excel.monster")
local ThroneExcel = require("excel.throne")
local MailExcel = require("excel.mail")
local RoleExcel = require("excel.role")
-- local Lang = require("common.Lang")
local Util = require("common.Util")
local Lang = require("common.Lang")
local Msg = require("core.Msg")
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 HeroGrid = require("hero.HeroGrid")
local JjcDB = require("jjc.JjcDB")
local RoleDefine = require("role.RoleDefine")
local RoleLogic = require("role.RoleLogic")
local RoleDBLogic = require("role.RoleDBLogic")
local RoleHeadLogic = require("role.RoleHeadLogic")
local RoleAttr = require("role.RoleAttr")
local MailManager = require("mail.MailManager")
local TheStarsDBLogic = require("theStars.TheStarsDBLogic")
local RoleSystemLogic = require("roleSystem.RoleSystemLogic")
local RoleSystemDefine = require("roleSystem.RoleSystemDefine")
-- local ChengjiuLogic = require("chengjiu.ChengjiuLogic")
-- local ChengjiuDefine = require("chengjiu.ChengjiuDefine")
local JjcLogic = require("jjc.JjcLogic")
local ItemExcel = require("excel.item").item
local MailDefine = require("mail.MailIdDefine")
local ChatPaoMaLogic = require("chat.ChatPaoMaLogic")
local HeroGrowUp = require("absAct.HeroGrowUp")
local HeroLogic = require("hero.HeroLogic")
local HeroExcel = require("excel.hero")

local FAIL_COMBAT_CD = 1200                   -- 失败后冷却CD 1200


local function getTargetHuman(playerUuid)
    local targetHuman = ObjHuman.onlineUuid[playerUuid]
    if not targetHuman then
        local db = RoleDBLogic.getDb(playerUuid)
        if db then
            targetHuman = {}
            targetHuman.db = db
        end
    end

    return targetHuman
end


function isOpen(human,sendErr)
    if not RoleSystemLogic.isOpen(human, RoleSystemDefine.ROLE_SYS_ID_1303,sendErr) then
        return
    end
    return true
end

-- 根据等级和id获取怪物组
function getMonsterOutID(id, lv)
	for i = 1, #ThroneExcel.guard do
		local configTemp = ThroneExcel.guard[i]
		if lv <= configTemp.lv then
			return configTemp.monsterOutID[id]
		end
	end
end

function theStarsQuery(human)
    if not isOpen(human,true) then return end
    
    -- 取王座信息
    local list = TheStarsDBLogic.getThroneList()
    
    -- 写入数据
    local msgRet = Msg.gc.GC_THE_STARS_QUERY
    msgRet.throneMsg[0] = #list

    for i, throne in ipairs(list) do
        local cf = ThroneExcel.throne[i]
        local throneNet =  msgRet.throneMsg[i] 
         
        if throne.uuid ~= nil then
            -- 王座有占领者
            local db = RoleDBLogic.getDb(throne.uuid, "name")
            throneNet.name = db and db.name or ""
            throneNet.bodyID = throne.body or 0
        else
            -- 王座虚位以待
            throneNet.name = Lang.IS_EMPTY           
            throneNet.bodyID = cf.monsterShow
        end

        throneNet.id = throne.id
        throneNet.vestId = throne._id

        local chconfig = ItemExcel[cf.chenghaoID]
        throneNet.chenghaoIcon = chconfig.icon
    end

    --Msg.trace(msgRet)
    Msg.send(msgRet,human.fd)
end

function theStarsThroneQuery(human, id, vestId)
    if not isOpen(human,true) then return end

    local cf = ThroneExcel.throne[id]
    if not cf then return end
    
    -- 取出王座数据
    local throne = TheStarsDBLogic.getThroneByVestId(vestId)
    if not throne or throne.id ~= id then
        return Broadcast.sendErr(human, Lang.THRONE_INFO_NOT_INIT) 
    end

    local msgRet = Msg.gc.GC_THE_STARS_THRONE_QUERY

    msgRet.needRank = cf.maxRank

    -- 取占领者信息
    msgRet.isKing = 0
    msgRet.roleData[0] = 0
    if throne.uuid then
        msgRet.roleData[0] = 1
        RoleLogic.getRoleBaseByUuid(throne.uuid, msgRet.roleData[1])
        if throne.uuid == human.db._id then
            msgRet.isKing = 1
        end
    end

    local list = TheStarsDBLogic.getThroneList()
    for i, v in ipairs(list) do
        if v.uuid ~= nil and v.uuid == human.db._id and msgRet.isKing == 0 then
            msgRet.isKing = 2
            break
        end
    end

    local chconfig = RoleExcel.chenghao[cf.chenghaoID]
    -- 取王座属性
    msgRet.attrs[0] = #chconfig.attrs
    for i = 1, msgRet.attrs[0] do
        local net = msgRet.attrs[i]
        net.key = chconfig.attrs[i][1]
        net.value = chconfig.attrs[i][2]
    end

    local jjcRank = JjcDB.getRank(human.db._id)
    msgRet.rank = jjcRank >= 0 and jjcRank or 0 

    msgRet.lv = throne.lv
    msgRet.nowEvolveCnt = throne.evolve or 0
    msgRet.monsterList[0] = 0

    if throne.uuid then
        local targetHuman = getTargetHuman(throne.uuid)
        if targetHuman then
            local len = 0
            local heroList = CombatPosLogic.getCombatHeros(targetHuman, CombatDefine.COMBAT_TYPE5)
            for i, heroUuid in ipairs(heroList or {}) do
                if i >= CombatDefine.COMBAT_HERO_CNT then -- 不显示援军
                    break
                end
                local heroGrid = HeroLogic.getHeroGridByUuid(targetHuman, heroUuid)
                if heroGrid then
                    len = len + 1
                    msgRet.monsterList[0] = len

                    local heroCfg = HeroExcel.hero[heroGrid.id]
                    msgRet.monsterList[len].body = heroGrid.body or heroCfg.body
                    msgRet.monsterList[len].lv = heroGrid.lv or 0
                    msgRet.monsterList[len].camp = heroCfg.camp
                end
            end
        end
    else
        local monsterOutID = getMonsterOutID(throne.id, throne.lv)
        local monsterOutConfig = MonsterExcel.monsterOut[monsterOutID]
        local count = #monsterOutConfig.member
        for i = 1,count do
            local monsterID = monsterOutConfig.member[i][1]
            local lv = monsterOutConfig.member[i][2]
            local mcf = MonsterExcel.monster[monsterID]
            msgRet.monsterList[i].body = mcf.body
            msgRet.monsterList[i].lv = throne.lv
            msgRet.monsterList[i].camp = mcf.camp
        end
        msgRet.monsterList[0] = count
    end

    Msg.send(msgRet, human.fd)
end

local function getFightCoolTime(human)
    if not human.db.throneTime then
        return 0
    end

    local sec = os.time() - human.db.throneTime
    return math.max(FAIL_COMBAT_CD - sec, 0)
end

local function getNewLvExp(id, lv, exp, evolveCnt)
	local starsCf = ThroneExcel.theStars[lv]
	exp = evolveCnt * starsCf.evolveExp + exp
    while exp >= starsCf.exp do
        lv = lv + 1 
        exp = exp - starsCf.exp
    end
    
    local cf = ThroneExcel.throne[id]
    lv = math.min(cf.maxLv, lv)
    
    return lv, exp
end

function checkCombatPos(human, args)
    if not isOpen(human,true) then return end 

    local id = tonumber(args[1] or 0)
    local evolveCnt = tonumber(args[2] or 0)
    local vestId = args[3]

	-- if evolveCnt < 1 then return end -- 升级次数小于1，怀疑有人作弊

    local cf = ThroneExcel.throne[id]
    if not cf then return end

    local throne = TheStarsDBLogic.getThroneByVestId(vestId)
    if not throne or throne.id ~= id then
        return -- 参数不对！
    end

    local leftTime = getFightCoolTime(human)
    if leftTime > 0 then
       return Broadcast.sendErr(human, Util.format(Lang.THRONE_CHALLENGE_TIME_INIT, math.ceil(leftTime / 60)))
    end

	if human.db._id == throne.uuid then --不能挑战自己
        return Broadcast.sendErr(human, Lang.THRONE_CANT_CHALLENGE_SELF)
    end

    local jjcRank = JjcDB.getRank(human.db._id)
    if jjcRank < cf.minRank or jjcRank > cf.maxRank then
        Broadcast.sendErr(human, Lang.JJC_RANK_NOT_ENOUGH) -- reyes todo temp
        return false
    end

    local lv = throne.lv
    local exp = throne.exp or 0
	lv, exp = getNewLvExp(id, lv, exp, evolveCnt)
    return true, cf, throne, lv, exp
end

function fight(human, args)
    local heroList = CombatPosLogic.getCombatHeros(human, CombatDefine.COMBAT_TYPE1)
    if #heroList < 1 then return Broadcast.sendErr(human, Lang.THESTAR_SET_HEROS) end

    local isok, cf, throne, lv, exp = checkCombatPos(human, args)
    if not isok then return end

    local monsterOutID = getMonsterOutID(throne.id, lv)
    cbParam = {}
    cbParam.newLv = lv
    cbParam.exp = exp
    cbParam.vestId = throne._id
    cbParam.id = throne.id    
    cbParam.evolveCnt = tonumber(args[2] or 0)

    
    args[#args+1] = throne.uuid
    
    CombatLogic.combatBegin(human, cf.mapID, args, CombatDefine.COMBAT_TYPE5, cbParam)
    
	HeroGrowUp.onCallback(human, HeroGrowUp.TASKTYPE13, 1)
end


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


function onFightEnd(human, result, type, cbParam, combatInfo)
    local config = ThroneExcel.throne[cbParam.id]
    local throne = TheStarsDBLogic.getThroneByVestId(cbParam.vestId)
    local evolveCnt = 0
    if not throne or not config then return end
    combatInfo.time = os.time()
    if result == CombatDefine.RESULT_WIN then      
        local time = os.time()
        local param2 = os.date("%Y/%m/%d %H:%M:%S")
        local param3 = nil 
        if cbParam.id == 1 then
            param3 = Lang.THE_STAR_KING
        elseif cbParam.id == 2 then
            param3 = Lang.THE_STAR_MASTER
        elseif cbParam.id == 3 then
            param3 = Lang.THE_STAR_MASTER
        else
            param3 = Lang.THE_STAR_BRAVE
        end
        if throne.uuid ~= nil then -- 干掉王座之前占领者的信息并发邮件
			RoleHeadLogic.unActive(throne.uuid, RoleHeadLogic.HEAD_TYPE_4, config.chenghaoID)
			
            local title = MailExcel.mail[MailDefine.MAIL_ID_CHENGHAO].title
            local content = Util.format(MailExcel.mail[MailDefine.MAIL_ID_CHENGHAO].content,human.db.name,param2,param3)
            local senderName = MailExcel.mail[MailDefine.MAIL_ID_CHENGHAO].senderName
            MailManager.add(MailManager.SYSTEM, throne.uuid, title, content, nil, senderName)
        end

        local body = human.db.body

        evolveCnt = cbParam.evolveCnt + (throne.evolve or 0)
        TheStarsDBLogic.setThroneRole(cbParam.id, human.db._id, body, cbParam.newLv, cbParam.exp, evolveCnt)
		RoleHeadLogic.active(human, RoleHeadLogic.HEAD_TYPE_4, config.chenghaoID)
        RoleHeadLogic.setHead(human, config.chenghaoID, RoleHeadLogic.HEAD_TYPE_4)
        ChatPaoMaLogic.broadcast(human, ChatPaoMaLogic.PAOMA_TYPE_BROAD_TYPE25, param3)	

        local chconfig = RoleExcel.chenghao[config.chenghaoID]
        local key1Value = chconfig.attrs[1][2]
        local key2Value = chconfig.attrs[2][2]
        combatInfo.endParam = ItemExcel[config.chenghaoID].icon.."|"..key1Value.."|"..key2Value

        -- 重新设置敌人名字
        -- combatInfo.defender.name = Util.format(Lang.THE_STARS_DEFINCER, cbParam.newLv)
        CombatVideo.saveThroneVideo(throne.id, combatInfo,cbParam.evolveCnt)
    else
        human.db.throneTime = os.time() -- 失败刷新CD
    end
end

function recordQuery(human,vestId)
    local throne = TheStarsDBLogic.getThroneByVestId(vestId)
    if not throne then print("  not  have " ) return end

    local recordList = CombatVideo.getCombatVideosByType(CombatVideo.VIDEOTYPE_THRONE, throne.id)
    local msgRet = Msg.gc.GC_THE_STARS_RECORD_QUERY
    msgRet.recordList[0] = 0
    for i = 1, #recordList do
        if msgRet.recordList[0] < #msgRet.recordList then
            msgRet.recordList[0] = msgRet.recordList[0] + 1
            local combatVideo = recordList[i]
            local combatInfo = combatVideo.combatInfo
            local net = msgRet.recordList[msgRet.recordList[0]]
            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
            net.evolveCnt = combatVideo.evolveCnt or 0
            local formationConfig = CombatPosLogic.getFormationConfig(combatInfo.atkFormation)
            net.formation = formationConfig.name
        end
    end
    Msg.send(msgRet,human.fd)
end

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

    local id = tonumber(args[1] or 0)
    local evolveCnt = tonumber(args[2] or 0)
    local vestId = args[3]
    local cf = ThroneExcel.throne[id]
    if not cf then return end

    local throne = TheStarsDBLogic.getThroneByVestId(vestId)
    if not throne or throne.id ~= id then
        return -- 参数不对！
    end
    if evolveCnt < 1 then return end

    local exp = throne.exp or 0
	local newLv = getNewLvExp(id, throne.lv, exp, evolveCnt)
    return getMonsterOutID(throne.id, newLv)
end

function getCombatObjList(human,side, args)
    -- if side ~= CombatDefine.ATTACK_SIDE then return end

    local h
    if side == CombatDefine.ATTACK_SIDE then
        h = human
    else
        local playerUuuid = args and args[#args]
        h = getTargetHuman(playerUuuid)
    end

    if not h then
        return
    end

    -- return CombatLogic.getHumanObjList(human, CombatDefine.COMBAT_TYPE1)

    return CombatLogic.getHumanObjList(h, CombatDefine.COMBAT_TYPE1)
end


local attrInput = {}
function getMonsterLvAttr(monsterIndex, throneID, evolveCnt)
	monsterIndex = tonumber(monsterIndex)
	throneID = tonumber(throneID)
	evolveCnt = tonumber(evolveCnt)

	if throneID == nil then
		return
	end
	
	local list = TheStarsDBLogic.getThroneList()
	if list[throneID] == nil then
		return
	end
	
	local throne = list[throneID]
	
	local lv = throne.lv or 0
	local exp = throne.exp or 0
	lv = getNewLvExp(throneID, lv, exp, evolveCnt)
	
	Util.cleanTable(attrInput)
	
	local monsterAttrID = nil
	local monsterAttrIDNext = nil
	local attrLvBegin = nil
	local attrLvEnd = nil
	local attrInputCnt = 0
	
	-- 为了节省配置表 王者试炼的怪物的属性只配置了1/101/201级的 中间的等级的怪物属性是根据等级 从上下两端动态算出来的
	for i = 1, #ThroneExcel.guard do
		if lv < ThroneExcel.guard[i].lv then
			monsterAttrID = ThroneExcel.guard[i-1].monsterAttrID[throneID]
			attrLvBegin = ThroneExcel.guard[i-1].lv
			monsterAttrIDNext = ThroneExcel.guard[i].monsterAttrID[throneID]
			attrLvEnd = ThroneExcel.guard[i].lv
			break
		end
	end

	if monsterAttrID == nil or monsterAttrIDNext == nil then
		return
	end

	local attrConf = MonsterExcel.monsterAttr[monsterAttrID]
	local attrConfNext = MonsterExcel.monsterAttr[monsterAttrIDNext]
	
	for i = 1, #attrConf.attrs do
		local key = attrConf.attrs[i][1]
		local val1 = attrConf.attrs[i][2]
		local val2 = nil
		
		for j = 1, #attrConfNext.attrs do
			if key == attrConfNext.attrs[j][1] then
				val2 = attrConfNext.attrs[j][2]
				break
			end
		end
		
		attrInputCnt = attrInputCnt + 1
		local valFinal = val1
		if val2 then
			valFinal = val1 + math.floor((val2-val1)/(attrLvEnd-attrLvBegin)*(lv-attrLvBegin))
		end
		
		attrInput[attrInputCnt] = {key, valFinal}
	end
	
	return lv, attrInput
end
 
 function fontActArgs(args, human)
	args[0] = 1
    local rank,score = JjcLogic.getActRank(human)
    args[1] = rank
end
