/*
* 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.unitgroups;

import java.util.ArrayList;

import com.tyr.Tyr;
import com.tyr.agents.Agent;
import com.tyr.agents.BunkerAgent;
import com.tyr.agents.None;
import com.tyr.agents.RepairBunker;

import bwapi.Color;
import bwapi.Game;
import bwapi.Player;


/**
 * This class manages all agents supporting a single bunker.
 * @author Simon
 *
 */
public class BunkerCrew extends UnitGroup
{
	/**
	 * The bunker we are supporting.
	 */
	public Agent bunker;
	
	/**
	 * The units inside the bunker.
	 */
	public ArrayList<Agent> defenders = new ArrayList<Agent>();
	
	/**
	 * The scvs repairing the bunker.
	 */
	private ArrayList<Agent> repairCrew = new ArrayList<Agent>();
	
	/**
	 * This class manages all agents supporting a single bunker.
	 * @param rejects OutOfJob object to which all units are sent that are no longer needed.
	 */
	public BunkerCrew(OutOfJob rejects)
	{
		super(rejects);
	}

	@Override
	public void onFrame(Game game, Player self, Tyr bot) 
	{
		// If the bunker is disabled, unload all units from it.
		// The bunker is set to null, so that the Bunkers unit group knows to remove this bunker crew.
		if(((BunkerAgent)bunker).disabled)
		{
			bunker.unit.unloadAll();
			bunker = null;
		}
		
		// If the bunker no longer exists, we free all other agents to do other tasks.
		if (bunker == null || bunker.isDead())
		{
			bunker = null;
			
			for(Agent def : defenders) rejects.add(def);
			defenders = new ArrayList<Agent>();

			for(Agent scv : repairCrew) rejects.add(scv);
			repairCrew = new ArrayList<Agent>();
			
			return;
		}
		
		// Any unit that is supposed to be inside the bunker but is not is ordered to go inside.
		for(Agent def : defenders)
		{
			def.drawCircle(Color.Purple);
			if(def.unit.isIdle() || ! def.unit.isMoving())
				bunker.unit.load(def.unit);
		}
	}
	
	/**
	 * Add an scv to the list of repairing scvs.
	 * @param scv The scv to be added to the list of repairing scvs.
	 */
	public void addRepairSCV(Agent scv)
	{
		repairCrew.add(scv);
		scv.order(new RepairBunker(scv, bunker));
	}
	
	/**
	 * Removes an scv from the list of repairing scvs and returns it.
	 * @return The removed scv.
	 */
	public Agent removeRepairSCV()
	{
		Agent result = repairCrew.get(repairCrew.size()-1);
		repairCrew.remove(repairCrew.size()-1);
		result.order(new None(result));
		return result;
	}
	
	/**
	 * The number of units currently tasked to repair the bunker.
	 * @return The number of units currently tasked to repair the bunker.
	 */
	public int repairingSCVCount()
	{
		return repairCrew.size();
	}
	
	/**
	 * Add a unit to the list of units inside the bunker.
	 * The unit will automatically be sent inside the bunker.
	 * @param def The unit to add to the bunker.
	 */
	public void addDefender(Agent def)
	{
		if (bunker != null)
		{
			def.order(new None(def));
			defenders.add(def);
			def.unit.stop();
			bunker.unit.load(def.unit);
		}
		else
			rejects.add(def);
	}

	@Override
	public void cleanup()
	{
		super.cleanup();
		for(int i=0; i<repairCrew.size(); i++)
		{
			Agent worker = repairCrew.get(i); 
			if(worker.isDead())
			{
				repairCrew.remove(i);
				rejects.add(worker);
				i--;
			}
		}
	}
}
