minTimeTillFirstAttack = 0.0
maxTimeTillFirstAttack = 1.0

minAttackTimeAfterSuccessfulHit = 0.1
maxAttackTimeAfterSuccessfulHit = 1.0

minIdleTime = 0.5
maxIdleTime = 3.0

minSeekTime = 1.0
maxSeekTime = 2.0

minSeekSpeedMod = 0.8
maxSeekSpeedMod = 1.0

minTimeToAvoid = 2.0
maxTimeToAvoid = 5.0

minReach = 2
maxReach = 40

minAttackTimeAfterTakingDamage = 0.3
maxAttackTimeAfterTakingDamage = 0.8

chanceOfIdle = 0.3
changeOfRushAttack = 0.1

function init(dot_desc)

	minTimeTillFirstAttack = 0.0
	maxTimeTillFirstAttack = 1.0

	minAttackTimeAfterSuccessfulHit = 0.1
	maxAttackTimeAfterSuccessfulHit = 1.0

	minAttackTimeAfterTakingDamage = 0.3
	maxAttackTimeAfterTakingDamage = 0.8

	minIdleTime = 0.2
	maxIdleTime = 3.0

	minSeekTime = 1.0
	maxSeekTime = 2.0

	minSeekSpeedMod = 0.8
	maxSeekSpeedMod = 1.0

	minTimeToAvoid = 2.0
	maxTimeToAvoid = 5.0

	minReach = 2
	maxReach = 40

	chanceOfIdle = 0.3
	changeOfRushAttack = 0.1

end

function rand_time(min_time, max_time)

	return min_time + math.random() * (max_time - min_time)
end

function tick(bot)

	this_bot = bot

    local state = bot.State

--    CCLuaLog("state is ".. state)
	
	if (_G["tick_"..state] ~= nil) then
		 _G["tick_"..state](bot)
	end
end

function begin_state(bot)
	local state = bot.State
	if (_G["begin_".. state] ~= nil) then
		_G["begin_".. state](bot)
	end
end

function end_state(bot)
	local state = bot.State
	if (_G["end_".. state] ~= nil) then
		_G["end_".. state](bot)
	end
end

function begin_Disabled(bot)

	target_pos = bot:getBasePosition()

	bot:setTargetPosition(target_pos);

end

function tick_Disabled(bot)

	-- DO NOTHING

end

function begin_Idle(bot)
	local target_pos

	if (bot.TargetActor ~= nil) then
		target_pos = bot.TargetActor:getBasePosition()
	else
		target_pos = bot:getBasePosition()
	end

	bot:setTargetPosition(target_pos);

	bot.TimeTillNewTarget = rand_time(minIdleTime , maxIdleTime);
	
--	CCLuaLog("BEGIN IDLE target is " .. bot.TargetPosition.x .. " " .. bot.TargetPosition.y)
end

function tick_Idle(bot)

	bot.TimeTillNewTarget = bot.TimeTillNewTarget - bot.Delta
	if (bot.TimeTillNewTarget < 0) then
		bot.State = "Seek"
	end

	bot:setTargetPosition(bot:getBasePosition())

	-- local fDistanceToActor = bot:getDistanceFromTargetActor()
	-- if (fDistanceToActor < 25) then
	-- 	bot.State = "Seek"	
	-- elseif (fDistanceToActor > 60) then
	-- 	bot.State = "Seek"
	-- end

end

function begin_Seek(bot)

	local offset = CCPoint(0,0)
	local reach = minReach + math.random() * math.random() * (maxReach - minReach);

--	CCLuaLog("reach is " .. reach)

	offset.x = offset.x + reach;
--	offset.y = offset.y + (1 - math.random() * 2) * reach * 0.25;

--	CCLuaLog("offset is " .. offset.x .."," .. offset.y)

	bot:setTargetOffset(offset)
	
	bot.SpeedMod = minSeekSpeedMod + math.random() * (maxSeekSpeedMod - minSeekSpeedMod)

	bot.TimeTillNewTarget = rand_time(minSeekTime, maxSeekTime);

	-- Bot is now in an attacking mode
	bot:setIsAttacking(true)
end

function tick_Seek(bot)

	if (bot:isStanding() ~= true) then
		return;
	end

	bot.TimeTillNewTarget = bot.TimeTillNewTarget - bot.Delta
	if (bot.TimeTillNewTarget < 0) then
		local random_num = math.random()
		if (random_num < chanceOfIdle) then
			bot.State =  "Idle"
		elseif (random_num < chanceOfIdle + changeOfRushAttack) then

			if (bot:getTargetPositionLocked() ~= true) then
				bot:doAction(kFAT_HeavyAttack)
			end

		else
			bot.TimeTillNewTarget = rand_time(minSeekTime, maxSeekTime);
		end
		return
	end
		
	local pos = bot:getBasePosition()
	local target_pos = bot:getTargetActorPosition()
	local dir = ccpSub(pos, target_pos)
	
--	CCLuaLog("bot.SpeedMod is " .. bot.SpeedMod)
		
	local target_offset = bot:getTargetOffset();
	local offset = CCPoint(target_offset.x, target_offset.y);
		
	if (dir.x < 0) then
		offset.x = -offset.x
	end

	bot:setTargetPosition(CCPoint(target_pos.x + offset.x, target_pos.y + offset.y))
	
	if (bot:getTargetPositionLocked() ~= true) then
	    if (bot:hasReachedTarget() or bot:willAttackHitActor(kFAT_LightAttack, bot.TargetActor)) then
		    bot.State = "Attack"
		end
	end

	-- Wander off if target is floored
	if (bot.TargetActor ~= nil and bot.TargetActor:isFallingOrFloored()) then
	    bot.State = "Wander"
	end
end

function end_Seek( bot )

	-- Bot is now not in an attacking mode
	bot:setIsAttacking(false)

end

function begin_Wander(bot)

--	CCLuaLog("WANDERING!");

	-- Choose random position
	local wander_pos = bot:generateWanderPosition()

--	local distFromTarget = ccpLength(ccpSub(target, wander_pos))
--	CCLuaLog("Dist from target - "..distFromTarget)

--	if (distFromTarget < 50) then
		bot:setTargetPosition(wander_pos)
--	end
end

function tick_Wander(bot)

	if (bot:hasReachedTarget()) then
		bot.State = "Seek"

		-- TEMP TEST
		bot.State = "Idle"
	end

end

function begin_Attack(bot)

	if (bot.TimeTillAttack <= 0) then
		bot.TimeTillAttack = rand_time(minTimeTillFirstAttack, maxTimeTillFirstAttack)
	end

	local target_pos = bot:getBasePosition()
	bot:setTargetPosition(target_pos)

	-- Bot is now in an attacking mode
	bot:setIsAttacking(true)


--	CCLuaLog("BEGIN timetillattack is " .. bot.TimeTillAttack)
end

function tick_Attack(bot)

    bot.TimeTillAttack = bot.TimeTillAttack - bot.Delta;
    
    if (bot.TimeTillAttack < 0) then    
		local success = false

		bot.TimeTillAttack = rand_time(minTimeTillFirstAttack, maxTimeTillFirstAttack)

		local action_type = kFAT_LightAttack;

		-- Randomly try a heavy attack
		if (math.random() < 0.15) then
			action_type = kFAT_ForwardAttack
		end

		-- Check we'll probably hit something before attacking
		if (bot:willAttackHitActor(action_type, bot.TargetActor)) then
			success = true
            bot:doAction(action_type)
		end
   		   		
   		if (success == false) then
   			-- Failed to hit target, go back to seek and decide what to do next
    	 	bot.State = "Seek"
    	end
    end
end

function end_Attack( bot )

	-- Bot is now not in an attacking mode
	bot:setIsAttacking(false)

end

-- Bot has taken damage
function onTakeDamage(bot, bKO)

	if (bKO == true) then
		-- Falling over
	else
		-- Flinch
		bot.TimeTillAttack = rand_time(minAttackTimeAfterTakingDamage, maxAttackTimeAfterTakingDamage)
--		CCLuaLog("Took Damage - new attack delay is"..bot.TimeTillAttack)
	end

--	CCLuaLog("Bot has taken damage!")
	local game_manager = FistGameManager:getSharedFistGameManager()
	local hud = game_manager.HUD
	hud:showEnemyHealth(bot)

end

-- Holy crap we hit someone!
function onHitActor(bot)
	-- Wait a bit then STRIKE AGAIN
	bot.TimeTillAttack = rand_time(minAttackTimeAfterSuccessfulHit, maxAttackTimeAfterSuccessfulHit)
end
