/*
* 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 java.util.List;

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

import bwapi.Color;
import bwapi.Game;
import bwapi.Player;
import bwapi.Position;
import bwapi.Unit;
import bwapi.UnitType;
import bwta.Region;

/**
 * This class implements a solution for defending a single base.
 */
public class SmeltingSolution extends Solution
{
	private List<Agent> gatekeepers = new ArrayList<Agent>();
	private List<Agent> dragoons = new ArrayList<Agent>();
	private List<Agent> others = new ArrayList<Agent>();
	
	private int mode = CLOSED;

	private static final int CLOSED = 0;
	private static final int OPEN = 1;
	
	private Region defendedRegion;
	
	/**
	 * This class implements a solution for defending a single base.
	 * @param task The task that started this solution.
	 * @param defendedRegion The region which we will defend.
	 */
	public SmeltingSolution(Task task) 
	{
		super(task);
	}
	
	@Override
	public void onFrame(Game game, Player self, Tyr bot)
	{
		if (game.getFrameCount() >= 120 && BWTAProxy.initialized && defendedRegion == null)
			defendedRegion = BWTAProxy.getRegion(self.getStartLocation());
		
		Agent.clean(gatekeepers);
		Agent.clean(dragoons);
		Agent.clean(others);
		
		final List<Unit> enemies = new ArrayList<Unit>();
		for (Unit enemy : EnemyManager.getEnemyUnits())
			if (BWTAProxy.getRegion(enemy.getPosition()) == defendedRegion)
				enemies.add(enemy);
		
		if (enemies.isEmpty())
		{
			for (Agent dragoon : dragoons)
				dragoon.unit.move(Tyr.getStartLocation());
		}
		else
		{
			int enemyPos = 0;
			for (Agent dragoon : dragoons)
			{
				final Unit enemy = enemies.get(enemyPos);
				dragoon.attack(enemy);
				enemyPos = (enemyPos + 1) % enemies.size();
			}
		}
		
		for (Agent other : others)
			other.unit.move(Tyr.getStartLocation());
		
		if (mode == CLOSED)
			closed(enemies.size());
		else
			open(enemies.size());
	}
	
	private void closed(int enemyCount)
	{
		final Position exit = SpaceManager.getMainExit();
		if (exit != null)
		{
			for (Agent gatekeeper : gatekeepers)
			{
				if (gatekeeper.distanceSquared(exit) >= 100 * 100)
				{
					gatekeeper.unit.move(exit);
					gatekeeper.drawCircle(Color.Blue);
				}
				else if (gatekeeper.unit.isMoving())
				{
					gatekeeper.unit.holdPosition();
					gatekeeper.drawCircle(Color.White);
				}
			}
		}
		
		if (dragoons.size() >= 3 && enemyCount == 0)
			mode = OPEN;
	}
	
	public void open(int enemyCount)
	{
		for (Agent gatekeeper : gatekeepers)
			gatekeeper.unit.move(Tyr.getStartLocation());
		
		if (dragoons.size() < 3 || enemyCount >= 1)
			mode = CLOSED;
	}
	
	/**
	 * Add an agent to the list of defending units.
	 * @param unit The agent to be added.
	 */
	public void add(Agent agent)
	{
		if (agent.unit.getType() != UnitType.Protoss_Dragoon)
			others.add(agent);
		else if (gatekeepers.size() >= 2)
			dragoons.add(agent);
		else
			gatekeepers.add(agent);
	}

	/**
	 * Returns the number if agents sent out by this solution.
	 * @return Returns the number if agents sent out by this solution.
	 */
	public int size() 
	{
		return dragoons.size() + others.size() + gatekeepers.size();
	}
	
	public boolean done() 
	{
		return size() == 0;
	}

	public void removeUnits()
	{
		for (Agent agent : gatekeepers)
			Tyr.bot.homeGroup.add(agent);
		for (Agent agent : dragoons)
			Tyr.bot.homeGroup.add(agent);
		for (Agent agent : others)
			Tyr.bot.homeGroup.add(agent);
		gatekeepers = new ArrayList<>();
		dragoons = new ArrayList<>();
		others = new ArrayList<>();
		
	}
}
