/*
* 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.DebugMessages;
import com.tyr.EnemyManager;
import com.tyr.EnemyPosition;
import com.tyr.Settings;
import com.tyr.Tyr;
import com.tyr.agents.Agent;

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


/**
 * This unit group manages a group of workers that have been pulled to defend an expansion.
 * @author Simon
 *
 */
public class LocalDefendingWorkers extends UnitGroup
{
	private boolean proxyCannon = false;
	
	/**
	 * The defended base.
	 */
	private MineralWorkers base;
	
	/**
	 * This unit group manages a group of workers that have been pulled to defend an expansion.
	 * @param rejects OutOfJob object to which units are sent that are no longer needed.
	 */
	public LocalDefendingWorkers(OutOfJob rejects, MineralWorkers base) 
	{
		super(rejects);
		this.base = base;
	}

	@Override
	public void onFrame(Game game, Player self, Tyr bot) 
	{
		Unit invader = base.invader;
		int invaderCount = base.invaderCount;
		
		// See whether the enemy has proxied a building.
		boolean proxy = false;
		for (EnemyPosition building : EnemyManager.getManager().enemyBuildingMemory)
		{
			if (building.distanceSq(Tyr.tileToPosition(self.getStartLocation())) <= Settings.getLargeInvasionDist() * Settings.getLargeInvasionDist())
			{
				proxy = true;
				if (building.type == UnitType.Protoss_Photon_Cannon && building.completed)
				{
					proxyCannon = true;
					break;
				}
			}
		}
		
		// If we are no longer being invaded, send the workers back to work.
		if(invader == null 
				|| invader.getDistance(base.resourceDepot) > 300 || proxyCannon)
		{
			for(Agent agent : units)
				base.add(agent);
			if (units.size() != 0)
				units = new ArrayList<Agent>();
			return;
		}
		
		// If we are already well defended we do not need to pull workers to defend.
		if (base.resourceDepot.getDistance(Tyr.tileToPosition(self.getStartLocation())) <= 100)
			return;
		
		// Determine how many workers we want to use to defend.
		int desiredDefenders = 0;
		int halfWorkers = (units.size() + base.size());
		if(invaderCount == 1 && !invader.getType().isFlyer() && !proxy)
		{
			if(invader.getType().isWorker())
				desiredDefenders = Math.min(1, halfWorkers);
			else
				desiredDefenders = Math.min(3, halfWorkers);
		}
		else if (invaderCount == 2 && !proxy)
			desiredDefenders = Math.min(5, halfWorkers);
		else
			desiredDefenders = halfWorkers;
		
		// Make sure we have the correct number of workers for the defense.
		while(units.size() < desiredDefenders)
			units.add(base.pop(invader.getPosition()));
		while(units.size() > desiredDefenders)
		{
			base.add(units.get(units.size()-1));
			units.remove(units.size()-1);
		}
		
		DebugMessages.addMessage("Desired workers: " + desiredDefenders + "Defending: " + units.size());
		
		// Send the workers to attack the invading units.
		if (game.getFrameCount() % 100 == 0 && invader != null)
			for(Agent worker : units)
				if(worker != null)
				{
					if(invaderCount > 1)
						worker.unit.attack(invader.getPosition());
					else
						worker.unit.attack(invader);
				}
	}

}
