local BattleConst = require "app/module/battle/battle_const"

local BattleUnitEntity = require "app/userdata/battle/team/battle_unit_entity"

local BattleTeamEntity = class("BattleTeamEntity", BaseData)

local MATCH_ATTACK_NAME = GConst.MATCH_ATTACK_NAME
local MATCH_DMG_ADDITION_NAME = BattleConst.MATCH_DMG_ADDITION_NAME
local MATCH_DEC_DMG_NAME = BattleConst.MATCH_DEC_DMG_NAME
local MATCH_DMG_DEC_NAME = BattleConst.MATCH_DMG_DEC_NAME
local MATCH_WEAKNESS_NAME = BattleConst.MATCH_WEAKNESS_NAME
local DEFAULT_FACTOR = BattleConst.DEFAULT_FACTOR
local BUFF_NAME = BattleConst.BUFF_NAME
local ATTR_NAME = BattleConst.ATTR_NAME
local PASSIVE_EVENT = BattleConst.PASSIVE_EVENT

function BattleTeamEntity:ctor()
	self.members = {}
	self.membersCount = 0
	self.counterAttackCount = 0 -- 反击次数
end

function BattleTeamEntity:init(side, data)
	self.side = side
	if self.baseAttr then
		for k, v in pairs(self.baseAttr) do
			self:setBaseAttrValue(k, 0)
		end
	else
		self.baseAttr = {}
	end
	if self.attr then
		for k, v in pairs(self.attr) do
			self:setAttrValue(k, 0)
		end
	else
		self.attr = {}
	end
	self.deadStatusTag = false
	self.isDead = false
	self.isRebirth = false
	self.stunCount = 0
	self.lethargyCount = 0
	self.frozenCount = 0
	self.limitAll = 0
	self.activeSkillLimit = 0
	self.shieldHp = 0
	self.undeadHp = 0
	if data then
		table.sort(data.units, function(a, b)
			if a.level == b.level then
				if a.qlt == b.qlt then
					return a.id < b.id
				else
					return a.qlt > b.qlt
				end
			else
				return a.level > b.level
			end
		end)
		self.mainHero = nil
		for i, unitData in ipairs(data.units) do
			local unit = BattleUnitEntity:create()
			unit:init(unitData, side, self)
			self:addBaseAttr(unitData.attr)
			self.members[unitData.matchType] = unit
			self.membersCount = self.membersCount + 1
			if self.mainHero == nil then
				unit:setIsMainUnit(true)
				self.mainHero = unit
			end
		end
	end
end

function BattleTeamEntity:addUnit(unitData)
	local unit = BattleUnitEntity:create()
	unit:init(unitData, self.side, self)
	self:addBaseAttr(unitData.attr)
	self.members[unitData.matchType] = unit
	self.membersCount = self.membersCount + 1
	if self.mainHero == nil then
		unit:setIsMainUnit(true)
		self.mainHero = unit
	end
	return unit
end

function BattleTeamEntity:getBaseAttrValue(name)
	if not self.baseAttr[name] then
		return
	end
	return GFunc.decryptNumber(self.baseAttr[name])
end

function BattleTeamEntity:setBaseAttrValue(name, value)
	value = value or 0
	self.baseAttr[name] = GFunc.encryptNumber(value)
end

function BattleTeamEntity:addBaseAttr(unitAttr)
	for k, v in pairs(unitAttr) do
		self:setBaseAttrValue(k, (self:getBaseAttrValue(k) or 0) + v)
		self:setAttrValue(k, (self:getAttrValue(k) or 0) + v)
	end
end

function BattleTeamEntity:getAttrValue(name, noDefault)
	if not self.attr[name] then
		if noDefault then
			return
		else
			return 0
		end
	end
	return GFunc.decryptNumber(self.attr[name])
end

function BattleTeamEntity:setAttrValue(name, value)
	value = value or 0
	self.attr[name] = GFunc.encryptNumber(value)
end

function BattleTeamEntity:addAttr(name, num, isPercent)
	local addNum = 0
	if isPercent then
		if self:getAttrValue(name, true) then
			-- 百分比加减属性的时候如果是减少属性,则先取正数做计算,在减去此结果, 否则在做整除运算的时候,正数和负数整除后的绝对值会不一致
			-- 例如150 // 100 = 1, -150 // 100 = -2, 导致添加和移除的时候计算的属性值不一样
			local attrValue = self:getAttrValue(name)
			if num < 0 then
				if self:getBaseAttrValue(name) then
					addNum = self:getBaseAttrValue(name) * -num // DEFAULT_FACTOR
					self:setAttrValue(name, attrValue - addNum)
				else
					addNum = attrValue * -num // DEFAULT_FACTOR
					self:setAttrValue(name, attrValue - addNum)
				end
				addNum = -addNum
			else
				if self:getBaseAttrValue(name) then
					addNum = self:getBaseAttrValue(name) * num // DEFAULT_FACTOR
					self:setAttrValue(name, attrValue + addNum)
				else
					addNum = attrValue * num // DEFAULT_FACTOR
					self:setAttrValue(name, attrValue + addNum)
				end
			end
		end
	else
		addNum = num
		local currNum = self:getAttrValue(name)
		self:setAttrValue(name, currNum + num)
	end
	return addNum
end

function BattleTeamEntity:getAllMembers()
	return self.members
end

function BattleTeamEntity:getMembersCount()
	return self.membersCount
end

function BattleTeamEntity:getHp()
	return self:getAttrValue(ATTR_NAME.HP)
end

function BattleTeamEntity:getMaxHp()
	return self:getAttrValue(ATTR_NAME.MAX_HP)
end

function BattleTeamEntity:getHpPercent(hp)
	local maxHp = self:getMaxHp()
	hp = hp or self:getHp()
	return hp / maxHp
end

function BattleTeamEntity:getAtk(matchType)
	return self:getAttrValue(MATCH_ATTACK_NAME[matchType])
end

function BattleTeamEntity:getDmgAddition(matchType)
	return self:getAttrValue(ATTR_NAME.DMG_ADDITION_ALL) + self:getAttrValue(MATCH_DMG_ADDITION_NAME[matchType])
end

function BattleTeamEntity:getDmgDec(matchType)
	return self:getAttrValue(ATTR_NAME.DMG_DEC_ALL) + self:getAttrValue(MATCH_DMG_DEC_NAME[matchType])
end

function BattleTeamEntity:getDecDmg(matchType)
	return self:getAttrValue(ATTR_NAME.DEC_DMG_ALL) + self:getAttrValue(MATCH_DEC_DMG_NAME[matchType])
end

function BattleTeamEntity:getWeakness(matchType)
	return self:getAttrValue(ATTR_NAME.WEAKNESS_ALL) + self:getAttrValue(MATCH_WEAKNESS_NAME[matchType])
end

function BattleTeamEntity:getCrittime(matchType)
	local matchCritTime = self:getAttrValue(GConst.MATCH_CRIT_TIME_NAME[matchType])
	return self:getAttrValue(ATTR_NAME.CRIT_TIME) + matchCritTime
end

function BattleTeamEntity:getCrit(matchType)
	local matchCrit = self:getAttrValue(GConst.MATCH_CRIT_NAME[matchType])
	return self:getAttrValue(ATTR_NAME.CRIT) + matchCrit
end

function BattleTeamEntity:getCureAddition(matchType)
	local matchAddtion = self:getAttrValue(GConst.MATCH_CURED_NAME[matchType])
	return self:getAttrValue(ATTR_NAME.CURE_ADDITION) + matchAddtion
end

function BattleTeamEntity:getCureDec()
	return self:getAttrValue(ATTR_NAME.CURE_DEC)
end

function BattleTeamEntity:getBeDmgToHeal()
	return self:getAttrValue(ATTR_NAME.BE_DMG_TO_HEAL)
end

function BattleTeamEntity:getBeSucked()
	return self:getAttrValue(ATTR_NAME.BE_SUCKED)
end

function BattleTeamEntity:getUndeadHp()
	return self.undeadHp
end

function BattleTeamEntity:setUndeadHp(hp)
	self.undeadHp = hp
end

function BattleTeamEntity:getNormalAttackAddCount()
	return self:getAttrValue(ATTR_NAME.NORMAL_ATTACK_COUNT)
end

function BattleTeamEntity:getThorns()
	return self:getAttrValue(ATTR_NAME.THORNS)
end

function BattleTeamEntity:getExpTime()
	return self:getAttrValue(ATTR_NAME.EXP_TIME)
end

function BattleTeamEntity:getFirstHand()
	return self:getAttrValue(ATTR_NAME.FIRST_HAND)
end

function BattleTeamEntity:getDeathSummon()
	return self:getAttrValue(ATTR_NAME.DEATH_SUMMON)
end

function BattleTeamEntity:addMaxHp(num)
	local hpBefore = self:getHp()
	local currPercent = hpBefore * DEFAULT_FACTOR // self:getMaxHp()
	self:setAttrValue(ATTR_NAME.MAX_HP, self:getMaxHp() + (self:getBaseAttrValue(ATTR_NAME.MAX_HP) or 0) * num // DEFAULT_FACTOR)
	self:setAttrValue(ATTR_NAME.HP, currPercent * self:getMaxHp() // DEFAULT_FACTOR)
	if self:getHp() <= 0 and hpBefore > 0 then
		self:setAttrValue(ATTR_NAME.HP, 1)
	end
end

function BattleTeamEntity:addLimit(name, buffEffect)
	if name == BUFF_NAME.STUN then
		self.stunCount = self.stunCount + 1
	elseif name == BUFF_NAME.LETHARGY then
		if buffEffect.result then
			return
		end
		self.lethargyCount = self.lethargyCount + 1
	elseif name == BUFF_NAME.FROZEN then
		if buffEffect.result then
			return
		end
		self.frozenCount = self.frozenCount + 1
	end
	self.limitAll = self.limitAll + 1
end

function BattleTeamEntity:removeLimit(name)
	if name == BUFF_NAME.STUN then
		self.stunCount = self.stunCount - 1
	elseif name == BUFF_NAME.LETHARGY then
		self.lethargyCount = self.lethargyCount - 1
	elseif name == BUFF_NAME.FROZEN then
		self.frozenCount = self.frozenCount - 1
	end
	self.limitAll = self.limitAll - 1
end

function BattleTeamEntity:getIsLimit()
	return self.limitAll > 0
end

function BattleTeamEntity:getActiveSkillLimit()
	return self.activeSkillLimit > 0
end

function BattleTeamEntity:addActiveSkillLimit(name)
	self.activeSkillLimit = self.activeSkillLimit + 1
end

function BattleTeamEntity:removeActiveSkillLimit(name)
	self.activeSkillLimit = self.activeSkillLimit - 1
end

function BattleTeamEntity:getIsStun()
	return self.stunCount > 0
end

function BattleTeamEntity:getIsLethargy()
	return self.lethargyCount > 0
end

function BattleTeamEntity:getIsFrozen()
	return self.frozenCount > 0
end

function BattleTeamEntity:addShield(num)
	self.shieldHp = self.shieldHp + num
end

function BattleTeamEntity:getShieldHp()
	return self.shieldHp
end

function BattleTeamEntity:getShieldRebound()
	return self:getAttrValue(ATTR_NAME.SHIELD_REBOUND)
end

function BattleTeamEntity:getBlock()
	return self:getAttrValue(ATTR_NAME.BLOCK)
end

function BattleTeamEntity:getCounterAttack()
	return self:getAttrValue(ATTR_NAME.COUNTER_ATTACK)
end

function BattleTeamEntity:getSkillHurtP(matchType)
	local skillHurtPName = GConst.MATCH_SKILL_HURTP_NAME[matchType]
	return self:getAttrValue(ATTR_NAME.SKILL_HURTP) + self:getAttrValue(skillHurtPName)
end

function BattleTeamEntity:getSkillHurtFixed(matchType)
	local skillHurtName = GConst.MATCH_SKILL_HURT_NAME[matchType]
	return self:getAttrValue(skillHurtName)
end


function BattleTeamEntity:getNormalSkillHurtP(matchType)
	local skillHurtName = GConst.MATCH_NORMAL_HURTP_NAME[matchType]
	return self:getAttrValue(skillHurtName)
end

function BattleTeamEntity:getNormalSkillHurtFixed(matchType)
	local skillHurtName = GConst.MATCH_NORMAL_HURT_NAME[matchType]
	return self:getAttrValue(skillHurtName)
end

function BattleTeamEntity:getAllHurtP(matchType)
	local allHurtPName = GConst.MATCH_ALL_HURTP_NAME[matchType]
	return self:getAttrValue(allHurtPName)
end

function BattleTeamEntity:getCanRebirth()
	return self:getAttrValue(ATTR_NAME.REBIRTH) > 0
end

function BattleTeamEntity:takeDamageOrCure(num, unitComp)
	if self.isDead then
		return 0
	end
	if num < 0 then -- 是伤害的话处理一下护盾
		num = self:handleShield(num)
		if num >= 0 then -- 这次伤害被抵消了
			return 0, true
		end
	end
	local hpBefore = self:getHp()
	self:setAttrValue(ATTR_NAME.HP, self:getHp() + num)
	local hurtEventNum = 0
	if self:getUndeadHp() > 0 and self:getHp() <= 0 then
		self:setAttrValue(ATTR_NAME.HP, self:getUndeadHp())
		num = self:getUndeadHp() - hpBefore
	end

	local hp = self:getHp()
	local maxhp = self:getMaxHp()
	if hp <= 0 then -- 死了
		hurtEventNum = -hpBefore
		self:setAttrValue(ATTR_NAME.HP, 0)
		unitComp:checkPassiveEvent(PASSIVE_EVENT.HP_LOWER_THAN, self, 0)
		self:die()
	elseif hp < maxhp then
		hurtEventNum = num
	else -- 满血了
		-- 这是加血
		hurtEventNum = maxhp - hpBefore
		self:setAttrValue(ATTR_NAME.HP, maxhp)
	end
	return hurtEventNum
end

function BattleTeamEntity:handleShield(damageNum)
	local invincibleShieldCount = self:getAttrValue(ATTR_NAME.INVINCIBLE_SHIELD)
	if invincibleShieldCount > 0 then
		self:setAttrValue(ATTR_NAME.INVINCIBLE_SHIELD, invincibleShieldCount - 1)
		return 0
	end

	self.shieldHp = self.shieldHp + damageNum
	if self.shieldHp >= 0 then
		return 0
	else
		damageNum = self.shieldHp
		self.shieldHp = 0
		return damageNum
	end
end

function BattleTeamEntity:getCounterAttackCount()
	return self.counterAttackCount or 0
end

function BattleTeamEntity:addCounterAttackCount(count)
	count = count or 1
	self.counterAttackCount = self.counterAttackCount + count
end

function BattleTeamEntity:clearCounterAttackCount()
	self.counterAttackCount = 0
end

function BattleTeamEntity:getRecordData(name)
	if self.recordData == nil then
		self.recordData = {}
	end
	return self.recordData[name]
end

function BattleTeamEntity:setRecordData(name, value)
	if self.recordData == nil then
		self.recordData = {}
	end
	self.recordData[name] = value
end

function BattleTeamEntity:clearRecordData()
	if self:getCanRebirth() then --有复活不清除
		return
	end

	if self.recordData then
		for k, v in pairs(self.recordData) do
			self.recordData[k] = nil
		end
	end
end

function BattleTeamEntity:die()
	if self.isDead then
		return
	end
	self.isDead = true
	self:clearRecordData()
end

function BattleTeamEntity:setIsRebirth()
	self.isRebirth = true
end

function BattleTeamEntity:getIsRebirth()
	return self.isRebirth
end

function BattleUnitEntity:tagDeadStatus()
	self.deadStatusTag = true
end

function BattleUnitEntity:getTagDeadStatus()
	return self.deadStatusTag
end

function BattleTeamEntity:rebirth()
	self.isRebirth = false
	self.isDead = false
	self.deadStatusTag = false
end
function BattleTeamEntity:getIsDead()
	if self:getIsRebirth() then
		return false
	end
	return self.isDead
end

--@region 自带rouge
function BattleTeamEntity:initRougeSkills()
	for k,v in pairs(self.members) do
		v:initRougeSkills()
	end
end
--@endregion

return BattleTeamEntity