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

import java.util.List;

import com.tyr.EnemyManager;
import com.tyr.Tyr;

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


/**
 * Orders an SCV to repair a bunker.
 * When the bunker is not in need of repair, the SCV will repair close damaged units and structures.
 * @author Simon
 *
 */
public class RepairBunker extends Command
{
	/**
	 * The bunker to be repaired.
	 */
	private Agent bunker;
	
	/**
	 * The unit we are currently repairing.
	 * The bunker is not registered here and this target is only chosen when the bunker is fully repaired.
	 */
	private Unit repairTarget;
	
	public RepairBunker(Agent agent, Agent bunker) 
	{
		super(agent);
		this.bunker = bunker;
	}

	@Override
	public void execute(Game game, Player self, Tyr bot) 
	{
		agent.drawCircle(Color.Purple);
		
		// If the bunker is damaged we repair it.
		if (bunker.unit.getHitPoints() < UnitType.Terran_Bunker.maxHitPoints())
		{
			if (!agent.unit.isRepairing())
				agent.unit.repair(bunker.unit);
			return;
		}
		
		// We only repair something other than the bunker if we are not being invaded.
		if (EnemyManager.getManager().getInvader() == null)
		{
			// If we already have a repairTarget, we repair that.
			if (repairTarget != null)
			{
				if(!repairTarget.exists()
						|| repairTarget.getHitPoints() <= 0
						|| repairTarget.getRemoveTimer() != 0
						|| bunker.distanceSquared(repairTarget) > 360*360 
						|| repairTarget.getHitPoints() >= repairTarget.getType().maxHitPoints()
						|| repairTarget.getPlayer() != self)
					repairTarget = null;
				else
					return;
			}
			
			// See if there is some other unit nearby that needs repairing.
			List<Unit> inRange = game.getUnitsInRadius(bunker.unit.getPosition(), 360);
			for(Unit unit : inRange)
			{
				if(unit.getPlayer() == self 
						&& (unit.getType().isBuilding() || unit.getType().isMechanical())
						&& unit.getHitPoints() < unit.getType().maxHitPoints()
						&& unit.isCompleted())
				{
					repairTarget = unit;
					agent.unit.repair(unit);
					return;
				}
			}
		}
		
		// If there is nothing to repair, the SCV will return to the bunker.
		if (agent.distanceSquared(bunker) >= 64*64)
			agent.unit.move(bunker.unit.getPosition());
	}

	@Override
	public boolean replace(Command command)
	{
		if (command.getClass() != RepairBunker.class)
			return true;
		return ((RepairBunker)command).bunker != bunker;
	}
	
}
