local BattleFormula = require "app/module/battle/helper/battle_formula"
local BattleConst = require "app/module/battle/battle_const"
local BattleHelper = require "app/module/battle/helper/battle_helper"
local BattleBuffSpecial = require "app/module/battle/helper/battle_buff_special"

local BattleBuffHandle = {}

local EFFECT_TYPE = BattleConst.EFFECT_TYPE
local BUFF_NAME = BattleConst.BUFF_NAME
local ATTR_NAME = BattleConst.ATTR_NAME
local DEFAULT_FACTOR = BattleConst.DEFAULT_FACTOR
local BUFF_NAME_TO_ATTR = BattleConst.BUFF_NAME_TO_ATTR

local function _doDotWork(unitComp, buffEffect, buff)
	local damage, hurtStatus = BattleFormula:getDamageOrCureResult(buffEffect.sender, buff, unitComp)
	if damage <= 0 then
		damage = -1
	else
		damage = -damage
	end
	unitComp:takeDamageOrCure(buffEffect.sender, damage, EFFECT_TYPE.DOT, hurtStatus, buff:getName())
end

local function _doHotWork(unitComp, buffEffect, buff)
	local cure, hurtStatus = BattleFormula:getDamageOrCureResult(buffEffect.sender, buff, unitComp)
	if cure < 0 then -- 加血不能是负数
		cure = 0
	end
	unitComp:takeDamageOrCure(buffEffect.sender, cure, EFFECT_TYPE.HOT, hurtStatus, buff:getName())
end

function BattleBuffHandle.doBuffWork(unitComp, buffEffect)
	local buff = buffEffect.buff
	local buffType = buff:getBuffType()
	if buffType == 4 then
		_doDotWork(unitComp, buffEffect, buff)
	elseif buffType == 6 then
		_doHotWork(unitComp, buffEffect, buff)
	elseif buffType == 7 then -- 特殊buff
		BattleBuffSpecial.specialBuffWork(unitComp, buffEffect, buff)
	end
	local fxList = buff:getFxTake()
	if fxList then
		for _, v in ipairs(fxList) do
			unitComp:playFx(v, 0)
		end
	end
end

function BattleBuffHandle.removeBuff(unitComp, buffEffect, noRecycle)
	local buff = buffEffect.buff
	local buffType = buff:getBuffType()
	local func = BattleBuffHandle.removeEffect[buffType]
	if func then
		func(buffEffect.sender, unitComp, buff, buffEffect)
	end
	if not noRecycle then
		BattleHelper:recycleBuffEffect(buffEffect)
	end
end

BattleBuffHandle.addAttribute = {
	[BUFF_NAME.ATKP_COLOR_ADD] = function(target, num)
		target.unitEntity:addAttr(ATTR_NAME.ATK, num, true)
		target.unitEntity:addAttr(ATTR_NAME.ATK_RED, num, true)
		target.unitEntity:addAttr(ATTR_NAME.ATK_YELLOW, num, true)
		target.unitEntity:addAttr(ATTR_NAME.ATK_GREEN, num, true)
		target.unitEntity:addAttr(ATTR_NAME.ATK_BLUE, num, true)
		target.unitEntity:addAttr(ATTR_NAME.ATK_PURPLE, num, true)
		return num
	end,
	[BUFF_NAME.NORMAL_ATTACK_DEC] = function(target, num)
		target.unitEntity:addAttr(ATTR_NAME.NORMAL_ATTACK_COUNT, -num, false)
		return -num
	end,
	[BUFF_NAME.NORMAL_ATTACK_ADD] = function(target, num)
		target.unitEntity:addAttr(ATTR_NAME.NORMAL_ATTACK_COUNT, num, false)
		return num
	end,
	[BUFF_NAME.HPP_ADD] = function(target, num)
		target:addMaxHp(num)
		return num
	end,
	[BUFF_NAME.DEATH_SUMMON] = function(target, num)
		if num < 0 then
			num = 0
		end
		target.unitEntity:setAttr(ATTR_NAME.DEATH_SUMMON, num)
		return num
	end
}

local function _takeEffectDirectHurt(unitComp, buff, target, buffEffect)
	local damage, hurtStatus = BattleFormula:getDamageOrCureResult(unitComp, buff, target)
	if damage <= 0 then
		damage = -1
	else
		damage = -damage
	end
	target:takeDamageOrCure(unitComp, damage, EFFECT_TYPE.DIRECT, hurtStatus, buff:getName())
	return damage
end

local function _takeEffectDot(unitComp, buff, target, buffEffect)
	return true
end

local function _takeEffectDirectCure(unitComp, buff, target, buffEffect)
	local cure, hurtStatus = BattleFormula:getDamageOrCureResult(unitComp, buff, target)
	if cure < 0 then -- 加血不能是负数
		cure = 0
	end
	target:takeDamageOrCure(unitComp, cure, EFFECT_TYPE.HEAL, hurtStatus, buff:getName())
	return cure
end

local function _takeEffectHot(unitComp, buff, target, buffEffect)
	return true
end

local function _takeEffectAttr(unitComp, buff, target, buffEffect)
	local buffName = buff:getName()
	local attr = BUFF_NAME_TO_ATTR[buffName]
	if attr then
		return target.unitEntity:addAttr(attr[1], buff:getEffectNum(), attr[2])
	else
		local func = BattleBuffHandle.addAttribute[buffName]
		if func then
			return func(target, buff:getEffectNum())
		end
	end
	return nil
end

local function _takeEffectControl(unitComp, buff, target, buffEffect)
	target.unitEntity:addLimit(buff:getName(), buffEffect)
	return true
end

BattleBuffHandle.addShield = {
	-- 反弹目标伤害的200%，直接写死
	[BUFF_NAME.SHIELD_REBOUND_200] = function(unitComp, buff, target, buffEffect)
		local shieldNum = target.unitEntity:getMaxHp() * buff:getEffectNum() // DEFAULT_FACTOR
		target:addShield(shieldNum, buffEffect)
		target.unitEntity:addAttr(ATTR_NAME.SHIELD_REBOUND, 20000, false)
		return shieldNum
	end,
	-- 反弹目标伤害的400%，直接写死
	[BUFF_NAME.SHIELD_REBOUND_400] = function(unitComp, buff, target, buffEffect)
		local shieldNum = target.unitEntity:getMaxHp() * buff:getEffectNum() // DEFAULT_FACTOR
		target:addShield(shieldNum, buffEffect)
		target.unitEntity:addAttr(ATTR_NAME.SHIELD_REBOUND, 40000, false)
		return shieldNum
	end,
	-- 反弹目标伤害的400%，直接写死
	[BUFF_NAME.SHIELD_ICE_REBOUND_400] = function(unitComp, buff, target, buffEffect)
		local shieldNum = target.unitEntity:getMaxHp() * buff:getEffectNum() // DEFAULT_FACTOR
		target:addShield(shieldNum, buffEffect)
		target.unitEntity:addAttr(ATTR_NAME.SHIELD_REBOUND, 40000, false)
		return shieldNum
	end,
	-- 反弹目标伤害的200%，直接写死
	[BUFF_NAME.SHIELD_ICE_REBOUND_200] = function(unitComp, buff, target, buffEffect)
		local shieldNum = target.unitEntity:getMaxHp() * buff:getEffectNum() // DEFAULT_FACTOR
		target:addShield(shieldNum, buffEffect)
		target.unitEntity:addAttr(ATTR_NAME.SHIELD_REBOUND, 20000, false)
		return shieldNum
	end,
	-- 反弹目标伤害的100%，直接写死
	[BUFF_NAME.SHIELD_REBOUND_100] = function(unitComp, buff, target, buffEffect)
		local shieldNum = target.unitEntity:getMaxHp() * buff:getEffectNum() // DEFAULT_FACTOR
		target:addShield(shieldNum, buffEffect)
		target.unitEntity:addAttr(ATTR_NAME.SHIELD_REBOUND, 10000, false)
		return shieldNum
	end,
	-- 海洋护盾
	[BUFF_NAME.OCEAN_SHIELD] = function(unitComp, buff, target, buffEffect)
		local shieldNum = target.unitEntity:getMaxHp() * buff:getEffectNum() // DEFAULT_FACTOR
		target:addShield(shieldNum, buffEffect)
		target.unitEntity:addAttr(ATTR_NAME.IMMUNE_REDUCTION_BENEFIT, 1, false)
		target:removeBuffByDecr(BattleConst.BUFF_DECR_TYPE.REDUCE_GAIN)
		return shieldNum
	end,
}

BattleBuffHandle.removeShield = {
	[BUFF_NAME.SHIELD_REBOUND_200] = function(buffSender, target, buff, buffEffect)
		target.unitEntity:addAttr(ATTR_NAME.SHIELD_REBOUND, -20000, false)
		target:removeShield(buffEffect)
	end,
	[BUFF_NAME.SHIELD_REBOUND_400] = function(buffSender, target, buff, buffEffect)
		target.unitEntity:addAttr(ATTR_NAME.SHIELD_REBOUND, -40000, false)
		target:removeShield(buffEffect)
	end,
	[BUFF_NAME.SHIELD_ICE_REBOUND_400] = function(buffSender, target, buff, buffEffect)
		target.unitEntity:addAttr(ATTR_NAME.SHIELD_REBOUND, -40000, false)
		target:removeShield(buffEffect)
	end,
	[BUFF_NAME.SHIELD_ICE_REBOUND_200] = function(buffSender, target, buff, buffEffect)
		target.unitEntity:addAttr(ATTR_NAME.SHIELD_REBOUND, -20000, false)
		target:removeShield(buffEffect)
	end,
	[BUFF_NAME.SHIELD_REBOUND_100] = function(buffSender, target, buff, buffEffect)
		target.unitEntity:addAttr(ATTR_NAME.SHIELD_REBOUND, -10000, false)
		target:removeShield(buffEffect)
	end,
	-- 海洋护盾
	[BUFF_NAME.OCEAN_SHIELD] = function(buffSender, target, buff, buffEffect)
		target:removeShield(buffEffect)
		target.unitEntity:addAttr(ATTR_NAME.IMMUNE_REDUCTION_BENEFIT, -1, false)
	end,
}

local function _takeEffectShield(unitComp, buff, target, buffEffect)
	local func = BattleBuffHandle.addShield[buff:getName()]
	if func then
		return func(unitComp, buff, target, buffEffect)
	else
		local shieldNum = target.unitEntity:getMaxHp() * buff:getEffectNum() // DEFAULT_FACTOR
		target:addShield(shieldNum, buffEffect)
		return shieldNum
	end
end

-- buff添加时的效果
BattleBuffHandle.takeBuffEffect = {
	[1] = _takeEffectAttr,
	[2] = _takeEffectShield,
	[3] = _takeEffectDirectHurt,
	[4] = _takeEffectDot,
	[5] = _takeEffectDirectCure,
	[6] = _takeEffectHot,
	[7] = BattleBuffSpecial.specialBuffOn,
	[8] = _takeEffectControl,
}

-- 还原改变的属性
local function _removeEffectAttr(buffSender, target, buff, buffEffect)
	local buffName = buff:getName()
	local attr = BUFF_NAME_TO_ATTR[buffName]
	if attr then
		if buffEffect then
			target.unitEntity:addAttr(attr[1], -buffEffect.result, false)
		else
			target.unitEntity:addAttr(attr[1], -buff:getEffectNum(), attr[2])
		end
	else
		local func = BattleBuffHandle.addAttribute[buffName]
		if func then
			return func(target, -buff:getEffectNum())
		end
	end
end

local function _removeEffectShield(buffSender, target, buff, buffEffect)
	local func = BattleBuffHandle.removeShield[buff:getName()]
	if func then
		func(buffSender, target, buff, buffEffect)
	else
		target:removeShield(buffEffect)
	end
end

local function _removeEffectControl(buffSender, target, buff, buffEffect)
	target.unitEntity:removeLimit(buff:getName())
end

-- buff移除时的效果
BattleBuffHandle.removeEffect = {
	[1] = _removeEffectAttr,
	[2] = _removeEffectShield,
	[7] = BattleBuffSpecial.specialBuffOff,
	[8] = _removeEffectControl,
}

return BattleBuffHandle