dofile("Scripts/utils.lua");
dofile("Scripts/Init/units.lua");
dofile("Scripts/Init/vehicle2.lua");

health2leave = 32; -- when unit's health is lesser then this value(%,0-100), unit will unload crew

min_distance = 48; -- if move target is closer that this value(in meters) - unit won't move to target
leading_move_distance = 24; -- distance of one AI's unit attack movement
main_gun = 0;

under_fire = false;
escape_move_distance = 44; -- distance of one AI's unit retreat movement

-- microAI  mode: out_of_range, fire, move
mai_behaviour = "normal"; -- normal, defensive, agressive
mai_action = "defense"; -- defense, attack, retreat
mai_fire_state = "idle"; -- idle, firing
mai_fire_order = ""; -- fire
mai_move_state = "idle"; -- idle, moving
mai_move_order = ""; -- move

mai_target = nil;

ashes = 0;
ashes_max = 0.32;
ashes_step = 0.004;

locator_turret = -1;
locator_engine = -1;
locator_cargo = -1;
locator_body = -1;

check_state_timeout = 20;
fire_timeout = 40;
move_timeout = 10;
mai_timeout = 40;
mai_orderer_timeout = 10;
eventman_timeout = 30;
mai_log_timeout = 20;

function Initialize()
	BasicInit();
	V2Init();
end

function Main()
	AIparts:Run();
end

--[[
function EventMan()
end

function CheckState()
	if mai_move_state == "moving" and unit.IsStopped() then
		mai_move_state = "idle";
	end
	if mai_fire_state == "firing" then
		if unit.IsGunIdle(main_gun) then
			mai_fire_state = "idle";
		else
		end
	end
end

function MicroAILog() end

function MicroAIOrderer()
	if mai_fire_state == "idle" then
		if mai_action == "attack" then
			if object.RandomInt(100) > 1 then mai_fire_order = "fire"; end
		elseif mai_action == "defense" then
			if object.RandomInt(100) > 1 then mai_fire_order = "fire"; end
		elseif mai_action == "retreat" then
			if object.RandomInt(100) > 1 then mai_fire_order = "fire"; end
		else ScreenError("(Tank) Unknown MAI Action: " .. mai_action);
		end
	elseif mai_fire_state == "firing" then
	else ScreenError("(Tank) Unknown MAI State!");
	end

	if mai_move_state == "idle" then
		if mai_action == "attack" then
			if object.RandomInt(100) > 16 then mai_move_order = "move"; end
		elseif mai_action == "defense" then
			if object.RandomInt(100) > 64 then mai_move_order = "move"; end
		elseif mai_action == "retreat" then
			if object.RandomInt(100) > 32 then mai_move_order = "move"; end
		else ScreenError("(Tank) Unknown MAI Action: " .. mai_action);
		end
	elseif mai_move_state == "moving" then
	else ScreenError("(Tank) Unknown MAI State!");
	end
end

function MicroAI()
	enemies_list = unit.GetEnemyList(0);
	enemy_soldiers = 0;
	enemy_cannons = 0;
	enemy_tanks = 0;
	allied_list = unit.GetAllyList(0);
	allied_soldiers = 0;
	allied_cannons = 0;
	allied_tanks = 0;
	for index,enemy in pairs(enemies_list) do
		unit_class = object.GetObjectClass(enemy);
		if unit_class == "Soldier" then enemy_soldiers = enemy_soldiers + 1;
		elseif unit_class == "Tank" then enemy_tanks = enemy_tanks + 1;
		elseif unit_class == "Cannon" then enemy_cannons = enemy_cannons + 1;
		end
	end
	for index,ally in pairs(allied_list) do
		unit_class = object.GetObjectClass(enemy);
		if unit_class == "Soldier" then allied_soldiers = allied_soldiers + 1;
		elseif unit_class == "Tank" then allied_tanks = allied_tanks + 1;
		elseif unit_class == "Cannon" then allied_cannons = allied_cannons + 1;
		end
	end
	if mai_behaviour == "normal" then
		if ((allied_tanks + allied_cannons) > (enemy_tanks + enemy_cannons) * 2) then mai_action = "attack";
		elseif ((allied_tanks + allied_cannons) >= (enemy_tanks + enemy_cannons)) then mai_action = "attack";
		elseif ((allied_tanks + allied_cannons)*2 > (enemy_tanks + enemy_cannons)) then
			if (allied_soldiers > enemy_soldiers*3) then	mai_action = "attack";
			else mai_action = "defense";
			end
		else mai_action = "retreat";
		end
	elseif mai_behaviour == "agressive" then
		if ((allied_tanks + allied_cannons) > (enemy_tanks + enemy_cannons) * 2) then mai_action = "attack";
		elseif ((allied_tanks + allied_cannons) >= (enemy_tanks + enemy_cannons)) then mai_action = "attack";
		elseif ((allied_tanks + allied_cannons)*2 > (enemy_tanks + enemy_cannons)) then
			if (allied_soldiers > enemy_soldiers*3) then mai_action = "attack";
			else mai_action = "defense";
			end
		else mai_action = "defense";
		end	else ScreenError("Unknown MAI Behaviour!");
	end
end

function Fire()
	if hold_fire or not unit.IsGunIdle(main_gun) then return end

	local best_target, target_type, target_cost, target_dist;

	local best_value = 0;
	local enemies = unit.GetEnemyList(0);

	for _,target in pairs(enemies) do
		target_type = object.GetTargetType(target);
		target_cost = object.desc.Armament.TargetPriorities[target_type];
		target_dist = unit.GetTargetDistance(target);
-- log("target type"..target_type..", value="..target_cost);
		if target_dist < object.desc.AlarmRange and target_cost > best_value then
			best_value = target_cost;
			best_target = target
		end
	end
	if best_target then unit.AttackObject(best_target) end
end

function Move()
	if (not hold_move) and mai_move_order == "move" and mai_move_state == "idle" then
		mai_move_state = "moving";
		mai_move_order = "";
		local enemies = unit.GetEnemyList(0);
		local best_value;
		local best_target;
		for _,target in pairs(enemies) do
			local unit_class = object.GetObjectClass(target);
			local target_distance = unit.GetTargetDistance(target, main_gun);
			local move_angle = unit.GetMoveAngle(target);

			if unit_class == "Tank" then value = target_distance * (1 - move_angle * 0.5);
			elseif unit_class == "Soldier" then value = 2 * target_distance * (1 - move_angle * 0.5);
			else value = target_distance * (1 - move_angle * 0.5);
			end

			if not best_value or (value < best_value) then
				best_value = value;
				best_target = target;
			end
		end
		under_fire = false;
	end
end
--]]

--[[
micro_ai.UnitInit = micro_ai.Init;
micro_ai.Init = function(self)
	self:UnitInit();
	if self.check_fire then
		self.weapon = nil;
		self.check1 = unit.GetAmmo1() > 0 and unit.IsGunIdle(0);
		self.check2 = unit.GetAmmo2() > 0 and unit.IsGunIdle(1);
	end
end

micro_ai.CheckFire = function(self, target, target_class)
	local target_type = object.GetTargetType(target);
	local target_priority = object.desc.Armament.TargetPriorities[target_type];
	if target_priority <= 0 then return end;
	
	local target_distance = unit.GetTargetDistance(target);
	if target_distance > object.desc.AlarmRange then return end;

	local target_id = object.GetObjectId(target);
	local prev_target = 1;
	if target_id == self.prev_target then prev_target = 0.5 end;
	local value = target_priority * object.GetTargetCost(target) / target_distance;

	if value > (self.fire_value or 0) then
		self.fire_target = target;
		self.fire_value = value;
	end
end

micro_ai.DoFire = function(self)
	if not self.fire_target then return end;
	unit.AttackObject(self.fire_target);
	self.prev_target = object.GetObjectId(self.fire_target);
	self.fire_target = nil;
end
--]]

function MicroAI()
	micro_ai:Run();
end
