local IdleUnitComp = class("BattleUnitComp", LuaComponent)

local UNIT_STATE_INIT = 0
local UNIT_STATE_IDLE = 1
local UNIT_STATE_ATTACK = 2
local UNIT_STATE_DEAD = 3
local UNIT_STATE_BORN = 4
local ATTACK_COUNT = 4					-- 写死攻击4次
local INIT_POS_X = 150
local UNIT_FRONT_POS_X = 0
local MOVE_SPEED = 2000               	-- 战斗单位攻击时的移动速度

function IdleUnitComp:ctor()
end

function IdleUnitComp:init()
	self.isPlayHurt = 0
	self.body = self.baseObject:getChildByName("body")
	self.currState = UNIT_STATE_INIT
	self.isClear = false
end

function IdleUnitComp:initSkills(skillIds)
	self.normalSkills = {}
	local skillCfg = ConfigManager:getConfig("skill")
	if skillIds then
		for k, v in ipairs(skillIds) do
			if skillCfg[v] then
				table.insert(self.normalSkills, skillCfg[v])
			end
		end
	end
end

function IdleUnitComp:getModelId()
	return self.modelId
end

function IdleUnitComp:setActive(isActive)
	self.baseObject:setActive(isActive)
end

function IdleUnitComp:setTarget(target)
	self.target = target
end

function IdleUnitComp:prepare(side, modelId)
	self.side = side
	self.modelId = modelId
	self:initPosition()
end

function IdleUnitComp:initPosition()
	if self.side == 1 then
		self.baseObject:setLocalPosition(-INIT_POS_X, 0, 0)
		self.body:setLocalScaleX(1)
		self.direction = 1
	else
		self.baseObject:setLocalPosition(INIT_POS_X, 0, 0)
		self.body:setLocalScaleX(-1)
		self.direction = -1
	end
end

function IdleUnitComp:playAnimation(name, loop, forceRefresh)
	if name == GConst.BattleConst.SPINE_ANIMATION_NAME.HIT then
		self.isPlayHurt = 1
	else
		self.isPlayHurt = 0
	end
	self.baseObject:playAnimation(name, loop, forceRefresh)
end

function IdleUnitComp:playBorn()
	self.isPlayHurt = 0
	self.currState = UNIT_STATE_INIT
	self.isClear = false
	if self.side == 1 then
		self:changeState(UNIT_STATE_IDLE)
	else
		self:changeState(UNIT_STATE_BORN)
	end
end

function IdleUnitComp:updateBorn(dt)
	self.waitTime = self.waitTime - dt
	if self.waitTime < 0 then
		self:changeState(UNIT_STATE_IDLE)
	end
end

function IdleUnitComp:enterBornState()
	self.waitTime = self:getAnimationDuration(GConst.BattleConst.SPINE_ANIMATION_NAME.BORN)
	self:playAnimation(GConst.BattleConst.SPINE_ANIMATION_NAME.BORN, false, false)
end

function IdleUnitComp:changeState(state)
	if self.currState == state and not self:repeatCurrState() then
		return false
	end
	if self.currState == UNIT_STATE_DEAD then -- 死亡后只能去死亡状态
		if state ~= UNIT_STATE_DEAD then
			return false
		end
	end
	-- 离开当前状态
	-- if self.currState == UNIT_STATE_IDLE then
	-- elseif self.currState == UNIT_STATE_ATTACK then
	-- elseif self.currState == UNIT_STATE_DEAD then
	-- end
	-- 进入目标状态
	self.currState = state
	if state == UNIT_STATE_IDLE then
		self:enterIdleState()
	elseif state == UNIT_STATE_ATTACK then
		self:enterAttackState()
	elseif state == UNIT_STATE_DEAD then
		self:enterDeadState()
	elseif state == UNIT_STATE_BORN then
		self:enterBornState()
	end
	return true
end

function IdleUnitComp:repeatCurrState()
	if self.currState == UNIT_STATE_ATTACK then
		return true
	end
	return false
end

function IdleUnitComp:playHurt()
	self.hurtTime = 0
	if self.currHitDuration == nil then
		self.currHitDuration = self:getAnimationDuration(GConst.BattleConst.SPINE_ANIMATION_NAME.HIT)
	end
	self:playAnimation(GConst.BattleConst.SPINE_ANIMATION_NAME.HIT, false, false)
end

function IdleUnitComp:updateHurt(dt)
	if self.isPlayHurt == 0 then
		return
	end
	if self.isPlayHurt == 1 then
		self.hurtTime = self.hurtTime + dt
		if self.hurtTime >= self.currHitDuration then
			self:playAnimation(GConst.BattleConst.SPINE_ANIMATION_NAME.IDLE, true, false)
			self.isPlayHurt = 0
		end
	end
end

function IdleUnitComp:updateIdle(dt)
	self:updateHurt(dt)
end

function IdleUnitComp:enterIdleState()
	self:playAnimation(GConst.BattleConst.SPINE_ANIMATION_NAME.IDLE, true, false)
end

function IdleUnitComp:doAttack(callback)
	self.baseObject:getTransform():SetAsLastSibling()
	self.actionOverCallback = callback
	self.attackCount = ATTACK_COUNT
	self:changeState(UNIT_STATE_ATTACK)
end

function IdleUnitComp:enterAttackState()
	self.attackOver = false
	self.attackTime = 0
	local skillInfo = self:getNormalSkill(true)
	if skillInfo.skill_position == GConst.BattleConst.SKILL_MOVE_TYPE.MOVE then
		self.isMove = true
		self:playAnimation(GConst.BattleConst.SPINE_ANIMATION_NAME.MOVE, true, false)
		self.positionX = self.baseObject:fastGetLocalPosition()
		if self.side == 1 then
			self.targetX = UNIT_FRONT_POS_X
			self.moveDirection = 1
		else
			self.targetX = -UNIT_FRONT_POS_X
			self.moveDirection = -1
		end
	else
		self.isMove = false
		local attackName = skillInfo.name_act
		self.currAttackDuration = self:getAnimationDuration(attackName)
		self.currAttackKeyTime = self:getAnimationKeyFrameTime(attackName)
		self:playAnimation(attackName, false, false)
	end
end

function IdleUnitComp:updateAttack(dt)
	if self.isMove then
		local addX = dt*MOVE_SPEED*self.moveDirection
		self.positionX = self.positionX + addX
		if (self.moveDirection > 0 and self.positionX >= self.targetX) or (self.moveDirection < 0 and self.positionX <= self.targetX) then
			self.isMove = false
			self.positionX = self.targetX
			if self.attackOver then -- 归位后该下一步了
				self:onAttackOver()
			else -- 到位置该攻击了
				self:doNextAttack()
			end
		end
		self.baseObject:setLocalPosition(self.positionX, 0, 0)
		return
	end
	self.attackTime = self.attackTime + dt
	if self.attackTime >= self.currAttackDuration then
		self.attackOver = true
		self.attackCount = self.attackCount - 1
		if self.attackCount <= 0 then
			local skillInfo = self:getNormalSkill()
			if skillInfo.skill_position == GConst.BattleConst.SKILL_MOVE_TYPE.MOVE then
				self:moveBackToInitPosition()
			else
				self:onAttackOver()
			end
			return
		else -- 继续攻击
			self:doNextAttack()
		end
	else
		if self.currAttackKeyTime > 0 and self.attackTime >= self.currAttackKeyTime then
			self.currAttackKeyTime = 0
			if self.attackCount == 1 then -- 最后一次攻击的话对方该死了
				self.target:changeState(UNIT_STATE_DEAD)
			else
				self.target:playHurt()
			end
		end
	end
end

function IdleUnitComp:moveBackToInitPosition()
	self.isMove = true
	self:playAnimation(GConst.BattleConst.SPINE_ANIMATION_NAME.MOVE, true, false)
	self.positionX = self.baseObject:fastGetLocalPosition()
	if self.side == 1 then
		self.targetX = -INIT_POS_X
		self.moveDirection = -1
	else
		self.targetX = INIT_POS_X
		self.moveDirection = 1
	end
end

function IdleUnitComp:doNextAttack()
	self.attackTime = 0
	local skillInfo = self:getNormalSkill(true)
	local attackName = skillInfo.name_act
	self.currAttackDuration = self:getAnimationDuration(attackName)
	self.currAttackKeyTime = self:getAnimationKeyFrameTime(attackName)
	self:playAnimation(attackName, false, false)
end

function IdleUnitComp:onAttackOver()
	self:changeState(UNIT_STATE_IDLE)
	local callback = self.actionOverCallback
	self.actionOverCallback = nil
	if callback then
		callback()
	end
end

function IdleUnitComp:getAnimationDuration(aniName)
	if self.attackDurationMap == nil then
		self.attackDurationMap = {}
	end
	local duration = self.attackDurationMap[aniName]
	if duration == nil then
		duration = self.baseObject:getAnimationDuration(aniName)
		self.attackDurationMap[aniName] = duration
	end
	return duration or 0
end

function IdleUnitComp:getAnimationKeyFrameTime(animationName, index)
	index = index or 1
	if self.attackKeyFrameTimeMap == nil then
		self.attackKeyFrameTimeMap = {}
	end
	local timeList = self.attackKeyFrameTimeMap[animationName]
	if timeList == nil then
		timeList = self.baseObject:getAnimationKeyFrameTimes(animationName)
		if not timeList[1] then
			table.insert(timeList, 0.3)
		end
		self.attackKeyFrameTimeMap[animationName] = timeList
	end
	return timeList[index] or 0.3
end

function IdleUnitComp:getNormalSkill(reRandom)
	if self.normalSkills == nil then
		return nil
	end
	if not reRandom then
		return self.normalSkill
	end
	if self.normalSkillIndex == nil then
		self.normalSkillIndex = math.random(1, #self.normalSkills)
	else
		local temp = self.normalSkills[#self.normalSkills]
		self.normalSkills[#self.normalSkills] = self.normalSkills[self.normalSkillIndex]
		self.normalSkills[self.normalSkillIndex] = temp
		self.normalSkillIndex = math.random(1, #self.normalSkills - 1)
	end
	self.normalSkill = self.normalSkills[self.normalSkillIndex]
	return self.normalSkill
end

function IdleUnitComp:getBornTime()
	return self:getAnimationDuration(GConst.BattleConst.SPINE_ANIMATION_NAME.BORN)
end

function IdleUnitComp:playDead(callback)
	if self.isClear then
		if callback then
			callback()
		end
		return
	end
	self.deadOverCallback = callback
	self:changeState(UNIT_STATE_DEAD)
end

function IdleUnitComp:enterDeadState()
	local aniName = GConst.BattleConst.SPINE_ANIMATION_NAME.DEAD
	self.deadTime = self:getAnimationDuration(aniName) + 0.1
	self:playAnimation(aniName, false, false)
end

function IdleUnitComp:updateDead(dt)
	self.deadTime = self.deadTime - dt
	if self.deadTime <= 0 then
		self:clear()
		if self.deadOverCallback then
			local callback = self.deadOverCallback
			self.deadOverCallback = nil
			callback()
		end
	end
end

function IdleUnitComp:clear()
	if self.isClear then
		return
	end
	self.isClear = true
end

function IdleUnitComp:tick(dt)
	if self.isClear then
		return
	end
	if self.currState == UNIT_STATE_DEAD then
		self:updateDead(dt)
		return
	end
	if self.currState == UNIT_STATE_IDLE then
		self:updateIdle(dt)
		return
	end
	if self.currState == UNIT_STATE_ATTACK then
		self:updateAttack(dt)
	elseif self.currState == UNIT_STATE_BORN then
		self:updateBorn(dt)
	end
end

function IdleUnitComp:destroy()
	self.baseObject:destroy()
end

return IdleUnitComp