/*
* 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 com.tyr.EnemyManager;
import com.tyr.OrderedExpands;
import com.tyr.PositionUtil;
import com.tyr.Tyr;
import com.tyr.agents.Agent;
import bwapi.Color;
import bwapi.Game;
import bwapi.Player;
import bwapi.Position;
import bwapi.Unit;
import bwapi.UnitType;

/**
 * This class implements a solution for constantly pushing the opponent.
 */
public class ClearMinesSolution extends Solution
{	
	private Agent observer;
	private Agent scout;
	
	/**
	 * The OrderedExpands object for our clockwise scouting observer.
	 */
	private OrderedExpands cwExpands = new OrderedExpands(true, false, true, true);
	
	/**
	 * This class implements a solution for constantly pushing the opponent.
	 * @param task The task that started this solution.
	 */
	public ClearMinesSolution(Task task) 
	{
		super(task);
	}
	
	@Override
	public void onFrame(Game game, Player self, Tyr bot)
	{
		if (observer != null && observer.isDead())
			observer = null;
		if (scout != null && scout.isDead())
			scout = null;
		
		
		Position cwPos = null;
		if (scout != null)
			cwPos = getTarget();
		if (cwPos != null)
		{
			if (scout != null)
			{
				for (Unit enemy : EnemyManager.getEnemyUnits())
					if (enemy.getType() == UnitType.Terran_Wraith
						&& scout.distanceSquared(enemy) <= 300 * 300)
					{
						scout.attack(enemy);
						game.drawLineMap(scout.unit.getX(), scout.unit.getY(), cwPos.getX(), cwPos.getY(), Color.Red);
						break;
					}
				
				boolean mine = false;
				if (cwPos != null)
				{
					for (Unit enemy : EnemyManager.getEnemyUnits())
						if (enemy.getType() == UnitType.Terran_Vulture_Spider_Mine 
							&& PositionUtil.distanceSq(enemy, cwPos) <= 200 * 200)
						{
							scout.attack(enemy);
							mine = true;
							game.drawLineMap(scout.unit.getX(), scout.unit.getY(), cwPos.getX(), cwPos.getY(), Color.Red);
							break;
						}
				}
				if (!mine)
				{
					scout.unit.move(cwPos);
					game.drawLineMap(scout.unit.getX(), scout.unit.getY(), cwPos.getX(), cwPos.getY(), Color.Green);
				}
			}
			if (observer != null)
			{
				observer.unit.move(cwPos);
				game.drawLineMap(observer.unit.getX(), observer.unit.getY(), cwPos.getX(), cwPos.getY(), Color.Green);
			}
		}
	}
	
	/**
	 * Add an agent to the attack group with the attacking agents.
	 * @param unit The agent to be added.
	 */
	public void add(Agent agent)
	{
		if (agent.unit.getType() == UnitType.Protoss_Observer)
			observer = agent;
		else if (agent.unit.getType() == UnitType.Protoss_Scout)
			scout = agent;
	}
	
	/**
	 * Gets us the next target to harass.
	 */
	private Position getTarget()
	{
		if (!cwExpands.tryInitialize())
			return null;

		final Position current = cwExpands.getPos();
		boolean mine = false;
		if (current != null)
		{
			for (Unit enemy : EnemyManager.getEnemyUnits())
				if (enemy.getType() == UnitType.Terran_Vulture_Spider_Mine 
					&& PositionUtil.distanceSq(enemy, current) <= 200 * 200)
				{
					mine = true;
					break;
				}
		}
		
		if (current == null ||
				(!mine && observer != null && observer.distanceSquared(current) <= 100 * 100))
			cwExpands.next();
		
		return cwExpands.getPos();
	}

	public boolean needsObserver()
	{
		return observer == null && scout != null;
	}

	public boolean needsScout()
	{
		return scout == null;
	}
}
