/*
* Tyr is an AI for StarCraft: Broodwar, 
* 
* Please visit https://github.com/SimonPrins/Tyr for further information.
* 
* Copyright 2015 Simon Prins
*
* This file is part of Tyr.
* Tyr is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
* Tyr is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* You should have received a copy of the GNU General Public License
* along with Tyr.  If not, see http://www.gnu.org/licenses/.
*/


package com.tyr.tasks;

import java.util.ArrayList;

import com.tyr.EnemyManager;
import com.tyr.Tyr;
import com.tyr.agents.Agent;
import com.tyr.buildingplacement.SpaceManager;

import bwapi.Game;
import bwapi.Player;
import bwapi.Position;
import bwapi.Unit;
import bwapi.UnitType;


/**
 * This solution send a science vessel to explore the natural.
 * @author Simon
 *
 */
public class ExploreScienceSolution extends Solution 
{
	/**
	 * The science vessel used to explore.
	 */
	private Agent vessel;
	
	/**
	 * The tanks used to clear out enemies.
	 */
	private ArrayList<Agent> tanks = new ArrayList<Agent>(); 
	
	/**
	 * The target where we are attacking.
	 */
	private Position target;
	
	/**
	 * Have we replaced the target with a second target?
	 */
	private boolean secondTarget;
	
	/**
	 * Have we reached the final target?
	 */
	public static boolean done;
	
	/**
	 * This solution send a science vessel to explore the natural.
	 * @param task The task that is using this solution.
	 */
	public ExploreScienceSolution(Task task) 
	{
		super(task);
		
		target = SpaceManager.getNatural();
	}
	
	/**
	 * Set the new target for the attack.
	 * @param target The target where we are going to attack.
	 */
	public void setTarget(Position target)
	{
		this.target = target;
	}

	@Override
	public void onFrame(Game game, Player self, Tyr bot)
	{
		if (vessel != null && vessel.isDead())
			vessel = null;
		
		if (vessel != null 
			&& vessel.distanceSquared(target) <= 10000)
		{

			if (!secondTarget)
			{
				target = SpaceManager.getDefensePos(target);
				secondTarget = true;
			}
			else
				done = true;
		}
		
		Agent.clean(tanks);

		if (vessel != null)
		{
			boolean underAttack = vessel.unit.isUnderAttack();
			boolean enemyInRange = underAttack;
			
			for (Unit enemy : EnemyManager.getEnemyUnits())
			{
				if (enemyInRange)
					break;
				if (vessel.distanceSquared(enemy) <= vessel.unit.getType().sightRange() * vessel.unit.getType().sightRange())
					enemyInRange = true;
			}
			
			if (underAttack)
				vessel.unit.move(Tyr.tileToPosition(self.getStartLocation()));
			else if (enemyInRange)
				vessel.unit.holdPosition();
			else 
			{
				if (target != null)
					vessel.unit.move(target);
				
				for (Agent tank: tanks)
					if (tank.unit.getType() == UnitType.Terran_Siege_Tank_Tank_Mode)
						tank.unit.siege();
				
				return;
			}
		}
		else
		{
			for (Agent tank : tanks)
				if (tank.unit.getType() == UnitType.Terran_Siege_Tank_Tank_Mode)
					tank.unit.siege();
			return;
		}
		
		if (vessel != null)
		{
			int tankRange = UnitType.Terran_Siege_Tank_Siege_Mode.groundWeapon().maxRange();
			tankRange *= tankRange;
			
			for (Agent tank : tanks)
			{
				boolean enemyInRange = false;
				for (Unit enemy : EnemyManager.getEnemyUnits())
				{
					if (enemy.getType().isFlyer() || enemy.getType().isFlyingBuilding())
						continue;
					
					if (tank.distanceSquared(enemy) <= tankRange)
					{
						enemyInRange = true;
						break;
					}
				}
	
				if (tank.unit.getType() == UnitType.Terran_Siege_Tank_Tank_Mode)
				{
					if (enemyInRange)
						tank.unit.siege();
					else if (target != null)
						tank.unit.move(target);
				}
				else if (!enemyInRange)
					tank.unit.unsiege();
			}
		}
	}

	/**
	 * Set the science vessel.
	 * @param vessel The science vessel.
	 */
	public void setVessel(Agent vessel)
	{
		this.vessel = vessel;
	}

	/**
	 * Add a tank to the list of tanks.
	 * @param vessel The tank to be added.
	 */
	public void addTank(Agent tank)
	{
		this.tanks.add(tank);
	}
	
	/**
	 * Does the solution have a science vessel?
	 * @return
	 */
	public boolean hasVessel()
	{
		return vessel != null;
	}
	
	/**
	 * How many tanks does the solution have.
	 * @return The number of tanks.
	 */
	public int tankCount()
	{
		return tanks.size();
	}
}
