-- 战斗逻辑(跨服)

local CombatExcel = require("excel.combat")
local Config = require("Config")
local Util = require("common.Util")
local CombatImpl = require("combat.CombatImpl")
local CombatDefine = require("combat.CombatDefine")
local CombatPosLogic = require("combat.CombatPosLogic")
local CombatPetCalc = require("combat.CombatPetCalc")
local JibanLogic = require("combat.JibanLogic")
local BeSkill = require("combat.BeSkill")
local CombatObj = require("combat.CombatObj")
local RoleDefine = require("role.RoleDefine")
local CombatLogic = require("combat.CombatLogic")

-- 初始combatInfo
local function initCombatInfo(human, combatType, mapID)
	local combatInfo = {}
	combatInfo.time = os.time() 	-- 战斗时间
	combatInfo.passTime = 0 	    -- 客户端经过的时间
	combatInfo.type = combatType 	-- 战斗类型
	combatInfo.mapID = mapID  		-- 地图
	combatInfo.posAttr = {}			-- 阵法属性
	combatInfo.jiban = {}			-- 阵法属性
	combatInfo.attacker = nil  		-- 攻方基础角色信息 roleBase
	combatInfo.defender = nil 		-- 守方基础角色信息 roleBase
	combatInfo.atkJiban = nil 		-- 攻方羁绊英雄
	combatInfo.defJiban = nil 		-- 守方羁绊英雄	
	combatInfo.isWin = nil 			-- 战斗结果
	combatInfo.result = nil 		-- 战斗帧
	combatInfo.skillUseList = nil 	-- 战斗技能
	combatInfo.cmdUseList = nil 	-- 战斗技能命令
	combatInfo.bufferUseList = nil 	-- 战斗buff
	combatInfo.objList = nil  		-- 战斗英雄列表
	combatInfo.helpList = nil  		-- 战斗魔兽列表
	combatInfo.elfList = nil  		-- 战斗精灵列表
	combatInfo.rewardItem = {} 		-- 奖励
	combatInfo.endParam = nil 		-- 额外参数
	combatInfo.isVideo = nil 		-- 是否录像	
	combatInfo.videoUuid = nil 		-- 录像uuid
	combatInfo.panelID = nil 		-- 返回界面（特殊）
	combatInfo.maxRound = nil 		-- 最大会合数
	combatInfo.fightMode = nil 		-- 战斗模式
	human.combat = combatInfo
	return combatInfo
end

local function getMapID(combatType)
    local mapID = nil
    local config = CombatExcel.combat[combatType]
    mapID = config.mapID == 0 and 1001 or config.mapID
    return mapID
end

--获取战斗最大回合数
local function getMaxRound(combatType)
	local config = CombatExcel.combat[combatType]
	if config and config.maxRound and config.maxRound > 0 then
		return config.maxRound
	end
	return CombatDefine.COMBAT_ROUND_MAX
end

--获取战斗模式
local function getFightMode(combatType)
	local config = CombatExcel.combat[combatType]
	if config.fightMode[1] == CombatDefine.FIGHT_MODE1 or config.fightMode[1] == CombatDefine.FIGHT_MODE3 then
		return config.fightMode
	end
end


local function setCombatInfo(formation,objList, side)
	for index = 1, CombatDefine.COMBAT_HERO_CNT do
		local obj = objList[index]
		if obj then
				-- 出战英雄站位
			if CombatPosLogic.checkPos(formation,index, side) then
				local pos = CombatDefine.SIDE2POS[side][index]
				obj.formationPos = index
				CombatImpl.setData(pos, obj)
			end
		end
	end
end

-- 设置辅助对象出战
local function setHelp(helpList, side)
	if not helpList then return end
	for k,v in pairs(helpList) do
		if k ==  CombatDefine.HELP_TYPE1 then
			CombatPetCalc.calcGrowArgs(v)
			CombatPetCalc.clacBuffArgs(v)
		end
		CombatImpl.setHelp(side,k,v)
	end
end

-- 设置精灵出战
local function setElf(elfList, side)
	if not elfList or not next(elfList) then
		return
	end

	for index = 1, CombatDefine.COMBAT_ELF_CNT do
		local elfObj = elfList[index]
		if elfObj then
			local pos = CombatDefine.SIDE2ELFPOS[side][index]
			CombatImpl.setElf(pos, elfObj)
		end
	end
end


-- 为了战斗回放，某些数据需要保存
local function copyToCombatInfo(combatInfo)
	combatInfo.isWin = CombatImpl.result.isWin
	combatInfo.result = Util.copyTable(CombatImpl.result)
	combatInfo.result.round = CombatImpl.round
	combatInfo.skillUseList = Util.copyTable(CombatImpl.skillUseList)
	combatInfo.cmdUseList = Util.copyTable(CombatImpl.cmdUseList)
	combatInfo.bufferUseList = Util.copyTable(CombatImpl.bufferUseList)
	combatInfo.objList = Util.copyTable(CombatImpl.objList)	
	combatInfo.helpList = Util.copyTable(CombatImpl.helpList)
	combatInfo.elfList = Util.copyTable(CombatImpl.elfList)
	combatInfo.totalAtkCnt = CombatImpl.totalAtkCnt
end


-- 根据阵营和下标获取对战位置
local function getPos(side, index)
	if side == CombatDefine.ATTACK_SIDE then
		return index
	elseif side == CombatDefine.DEFEND_SIDE then
		return index + CombatDefine.COMBAT_HERO_CNT
	else
		assert()
	end
end

-- 在各种战前加成后，重新设置血量
local function recalcHpFightBegin(human, combatType, cbParam)
	for i = 1,CombatDefine.COMBAT_HERO_CNT do
		local atkPos = getPos(CombatDefine.ATTACK_SIDE, i)
		local atkObj = CombatImpl.objList[atkPos]
		if atkObj then
			if atkObj.isSysAttrChange then
                CombatObj.calcAttr(atkObj)
				-- -- 重新计算血量
				-- if combatType == CombatDefine.COMBAT_TYPE9 then
				-- 	DrillLogic.calcAttrAtk(human, i, atkObj, cbParam)
				-- elseif combatType == CombatDefine.COMBAT_TYPE17 then
				-- 	ValleyLogic.calcAttr(CombatDefine.ATTACK_SIDE, i, atkObj, cbParam)
				-- elseif combatType == CombatDefine.COMBAT_TYPE8 then
				-- 	LianyuLogic.recalcHpFightBegin(human, i, atkObj)
                -- end
			end
			atkObj.hpMax = CombatObj.getHpMax(atkObj)
			atkObj.hp = atkObj.hp or CombatObj.getHpMax(atkObj)
			atkObj.mp = atkObj.mp or atkObj.attr[RoleDefine.INIT_MP]
			atkObj.initHp = atkObj.hp
			atkObj.initMp = atkObj.mp
		end		
		local defPos = getPos(CombatDefine.DEFEND_SIDE, i)
		local defObj = CombatImpl.objList[defPos]
		if defObj then
			if defObj.isSysAttrChange then
                CombatObj.calcAttr(defObj)
				-- if combatType == CombatDefine.COMBAT_TYPE9 then
				-- 	DrillLogic.calcAttrDef(human, i, defObj, cbParam)
				-- elseif combatType == CombatDefine.COMBAT_TYPE17 then
				-- 	ValleyLogic.calcAttr(CombatDefine.DEFEND_SIDE, i, defObj, cbParam)
				-- end	
			end
			defObj.hpMax = CombatObj.getHpMax(defObj)
			defObj.hp = defObj.hp or CombatObj.getHpMax(defObj)
			defObj.mp = defObj.mp or defObj.attr[RoleDefine.INIT_MP]
			defObj.initHp = defObj.hp
			defObj.initMp = defObj.mp
		end
	end
end


local function onFightBegin(human, combatType, cbParam, param)
	-- local moduleFn = getModule(combatType)
	-- if moduleFn and moduleFn.onFightBegin then
	-- 	moduleFn.onFightBegin(human, cbParam, combatType, param)
	-- end
	
	BeSkill.onFightBegin()
	-- SkinLogic.onFightBegin(human) -- 处理皮肤属性, 这里原来逻辑也有问题，先不处理
	CombatPosLogic.onFightBegin(human)
	recalcHpFightBegin(human, combatType, cbParam)
	CombatLogic.ElfInheritHeroAttr()
end



function combatBegin(attackerInfo, defenderInfo, combatType, onFightEndFunc, extraArgs)
    CombatImpl.init(combatType)
    local mapID = getMapID(combatType)

    if not attackerInfo or not next(attackerInfo) then
        return
    end

    if not defenderInfo or not next(defenderInfo) then
        return
    end


	local defender, defHelp = defenderInfo.objList, defenderInfo.helpList
    local defRBase, defFormation, defJiban, defElfList = defenderInfo.roleBase, defenderInfo.formation, defenderInfo.jiBan, defenderInfo.elfList

	local attacker, atkHelp = attackerInfo.objList, attackerInfo.helpList
    local atkRBase, atkFormation, atkJiban, atkElfList = attackerInfo.roleBase, attackerInfo.formation, attackerInfo.jiBan,attackerInfo.elfList

	if not (attacker and next(attacker)) then
		return
	end

	if not defender or not next(defender) then
		return
	end


	local human = {}

    local combatInfo = initCombatInfo(human, combatType, mapID)
    combatInfo.attacker = atkRBase or {}
    combatInfo.atkHelp = atkHelp or {}
    combatInfo.atkFormation = atkFormation
    combatInfo.atkJiban = atkJiban
    combatInfo.defender = defRBase or {}
    combatInfo.defHelp = defHelp or {}
    combatInfo.defFormation = defFormation
	combatInfo.defJiban = defJiban
	combatInfo.posAttr[CombatDefine.ATTACK_SIDE] = CombatPosLogic.getPosAttr(attacker)
	combatInfo.posAttr[CombatDefine.DEFEND_SIDE] = CombatPosLogic.getPosAttr(defender)
	combatInfo.jiban[CombatDefine.ATTACK_SIDE] = JibanLogic.getJiban(attacker,atkJiban)
	combatInfo.jiban[CombatDefine.DEFEND_SIDE] = JibanLogic.getJiban(defender,defJiban) 
	combatInfo.maxRound = getMaxRound(combatType)
	combatInfo.fightMode = getFightMode(combatType)

	JibanLogic.setBeSkill(attacker,combatInfo.jiban[CombatDefine.ATTACK_SIDE])
	JibanLogic.setBeSkill(defender,combatInfo.jiban[CombatDefine.DEFEND_SIDE])

	
    local changePos = nil
    -- if combatType == CombatDefine.COMBAT_TYPE10 then
    --     for k,v in pairs(attacker) do
    --         changePos = k
    --         attacker[k] = nil
    --         attacker[5] = v
    --         break
    --     end
    -- end
	setCombatInfo(atkFormation, attacker, CombatDefine.ATTACK_SIDE)
	setCombatInfo(defFormation, defender, CombatDefine.DEFEND_SIDE)
	setHelp(atkHelp, CombatDefine.ATTACK_SIDE)
	setHelp(defHelp, CombatDefine.DEFEND_SIDE)
	setElf(atkElfList, CombatDefine.ATTACK_SIDE)
	setElf(defElfList, CombatDefine.DEFEND_SIDE)
	CombatImpl.setMaxRound(combatInfo.maxRound)
	CombatImpl.setFightMode(combatInfo.fightMode)


	onFightBegin(human, combatType, nil, {}, {})

	while CombatImpl.calcFrame() do end
    copyToCombatInfo(combatInfo)

    combatInfo.changePos = changePos
	local result = combatInfo.isWin and CombatDefine.RESULT_WIN or CombatDefine.RESULT_FAIL

    if onFightEndFunc then
        onFightEndFunc(result, combatType, combatInfo, extraArgs)
    end
end