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

import com.tyr.Settings;
import com.tyr.Tyr;
import com.tyr.UnitTracker;
import com.tyr.agents.Agent;

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


/**
 * This unit group manages all structures that produce units or upgrades.
 * Builds can override the decisions made by this unit group.
 * @author Simon
 *
 */
public class ProductionStructures extends UnitGroup
{
	/**
	 * This unit group manages all structures that produce units or upgrades.
	 * Builds can override the decisions made by this unit group.
	 * @param rejects The OutOfJob UnitGroup to which units are sent that are no longer needed.
	 */
	public ProductionStructures(OutOfJob rejects) 
	{
		super(rejects);
	}

	@Override
	public void onFrame(Game game, Player self, Tyr bot)
	{
		for(Agent myUnit : units)
		{
			if(bot.build.overrideStructureOrder(game, self, bot, myUnit))
				continue;
			
			if(myUnit.unit.getType() == UnitType.Terran_Engineering_Bay && !myUnit.unit.isUpgrading())
			{
				// Engineering bay researches infantry upgrades.
				if(bot.getAvailableMinerals() >= UpgradeType.Terran_Infantry_Weapons.mineralPrice()
						&& bot.getAvailableGas() >= UpgradeType.Terran_Infantry_Weapons.gasPrice())
					myUnit.unit.upgrade(UpgradeType.Terran_Infantry_Weapons);
				
				if(bot.getAvailableMinerals() >= UpgradeType.Terran_Infantry_Armor.mineralPrice()
						&& bot.getAvailableGas() >= UpgradeType.Terran_Infantry_Armor.gasPrice())
					myUnit.unit.upgrade(UpgradeType.Terran_Infantry_Armor);
			}
			
			if(myUnit.unit.getType() == UnitType.Terran_Machine_Shop && !myUnit.unit.isResearching())
			{
				// Machine shop gets us tank mode.
				if(bot.getAvailableMinerals() >= 150 && bot.getAvailableGas() >= 150)
					myUnit.unit.research(TechType.Tank_Siege_Mode);
			}
			
			if(myUnit.unit.getType() == UnitType.Terran_Factory && !myUnit.unit.isTraining())
			{
				// If the factory doesn't have a machine shop yet, have it build that, otherwise we can produce tanks.
				if(myUnit.unit.getAddon() == null 
						&& bot.getAvailableMinerals() >= 50 && bot.getAvailableGas() >= 50)
				{
					myUnit.unit.buildAddon(UnitType.Terran_Machine_Shop);
					UnitTracker.addAddOn(UnitType.Terran_Machine_Shop);
				}
				else if(!myUnit.unit.isTraining()
						&& bot.getAvailableMinerals() >= 150 && bot.getAvailableGas() >= 100
						&& (UnitTracker.count(UnitType.Terran_Siege_Tank_Tank_Mode) == 0 || 
						self.hasResearched(TechType.Tank_Siege_Mode) || self.isResearching(TechType.Tank_Siege_Mode) || bot.getAvailableGas() >= 250)
						)
					myUnit.unit.train(UnitType.Terran_Siege_Tank_Tank_Mode);
			}
			
			//if this is Command Center, make it train additional worker
			if(myUnit.unit.getType() == UnitType.Terran_Command_Center && !myUnit.unit.isTraining())
			{
				if(UnitTracker.count(UnitType.Terran_Academy) == 1 && bot.getAvailableMinerals() >= 50 && bot.getAvailableGas() >= 50)
				{
					myUnit.unit.buildAddon(UnitType.Terran_Comsat_Station);
				}
	          	if (bot.getAvailableMinerals() >= 50
	          			&& bot.workForce.units.size() + bot.builders.units.size() < Settings.getMaximumWorkers()
	          			&& UnitTracker.count(UnitType.Protoss_Probe) + UnitTracker.count(UnitType.Terran_SCV) + UnitTracker.count(UnitType.Zerg_Drone) < Settings.getMaximumWorkers() + 10   
	          			&& (self.supplyTotal() + UnitTracker.getSupplyConstructing() - self.supplyUsed() 
	          						> UnitTracker.count(UnitType.Terran_Barracks)*3 + UnitTracker.getCcCount() * 3
	          					|| bot.getAvailableMinerals() >= 150)) {
	          		myUnit.unit.train(UnitType.Terran_SCV);
	          	}
			}

            //if this is a Barracks, make it train a marine
          	if (myUnit.unit.getType() == UnitType.Terran_Barracks 
          			&& (bot.scout.opponentStrategy != ScoutGroup.cannons || bot.getAvailableMinerals() >= 300) 
          			&& !myUnit.unit.isTraining()
          			&& bot.getAvailableMinerals() >= 50
          			&& (self.supplyTotal() + UnitTracker.getSupplyConstructing() - self.supplyUsed() 
          						> UnitTracker.count(UnitType.Terran_Barracks)*3 + UnitTracker.getCcCount() * 3 
          					|| bot.getAvailableMinerals() >= 150)
          					) {
          		myUnit.unit.train(UnitType.Terran_Marine);
          	}
          	
          	// The starport will train wraiths.
          	if(myUnit.unit.getType() == UnitType.Terran_Starport
          			&& !myUnit.unit.isTraining()
          			&& bot.getAvailableMinerals() >= 150
          			&& bot.getAvailableGas() >= 100)
          		myUnit.unit.train(UnitType.Terran_Wraith);
          	

        	if (myUnit.unit.getType() == UnitType.Zerg_Hatchery || myUnit.unit.getType() == UnitType.Zerg_Hive || myUnit.unit.getType() == UnitType.Zerg_Lair  )
        	{
        		List<Unit>larvas = myUnit.unit.getLarva();
        		for(Unit larva : larvas)
        		{
        			if ( (self.supplyTotal() + UnitTracker.getSupplyConstructing() - self.supplyUsed() <= UnitTracker.getCcCount() * 3)
                  		  && (bot.getAvailableMinerals() >= 100)
                  		  && self.supplyTotal() + UnitTracker.getSupplyConstructing() < 400)
        			{
        				larva.train(UnitType.Zerg_Overlord);
        	          	System.out.println("Overlord in training.");
        				continue;
                	}
    	          	
        			//if this is a larva, make it train additional worker
        			if (bot.getAvailableMinerals() >= 50 && bot.workForce.units.size() >= 12 
        					&& UnitTracker.count(UnitType.Zerg_Spawning_Pool) > 0)
        			{
        				larva.train(UnitType.Zerg_Zergling);
        	          	System.out.println("Zerglings in training.");
        				continue;
        			}

        	         //if this is a larva, make it train additional worker
        	         if (bot.getAvailableMinerals() >= 50 && bot.workForce.units.size() < Settings.getMaximumWorkers()) {
        	          	larva.train(UnitType.Zerg_Drone);
        	          	System.out.println("Drone in training.");
        				continue;
        	         }
        	         else
        	         {
          	          	System.out.println("Minerals: " + bot.getAvailableMinerals());
         	          	System.out.println("Supply: " + self.supplyUsed());
        	         }
        		}
        	}
            
          //if this is a Nexus, make it train an additional worker
        	if (myUnit.unit.getType() == UnitType.Protoss_Nexus && !myUnit.unit.isTraining() && bot.getAvailableMinerals() >= 50 
        			&& bot.workForce.units.size() < Settings.getMaximumWorkers()) {
        		myUnit.unit.train(UnitType.Protoss_Probe);
        	}
            
          //if this is a Gateway, make it train zealots!
        	if (myUnit.unit.getType() == UnitType.Protoss_Gateway && !myUnit.unit.isTraining())
        	{
        		if (UnitTracker.count(UnitType.Protoss_Cybernetics_Core) >= 1
        				&& bot.getAvailableMinerals() >= 125 && bot.getAvailableGas() >= 50
        				&& UnitTracker.count(UnitType.Protoss_Dragoon) <= UnitTracker.count(UnitType.Protoss_Zealot))
        			myUnit.unit.train(UnitType.Protoss_Dragoon);
        		else if(bot.getAvailableMinerals() >= 100
        				&& (UnitTracker.count(UnitType.Protoss_Dragoon) >= UnitTracker.count(UnitType.Protoss_Zealot) || bot.getAvailableMinerals() >= 150))
        			myUnit.unit.train(UnitType.Protoss_Zealot);
        	}
		}
		
	}
	
	@Override
	public int takeAgent(Agent agent)
	{
		if (!agent.unit.getType().isBuilding())
			return -1;
		if((agent.unit.getType().canProduce() 
    			|| agent.unit.getType() == UnitType.Terran_Engineering_Bay
    			|| agent.unit.getType() == UnitType.Terran_Machine_Shop
    			|| agent.unit.getType() == UnitType.Terran_Science_Facility
    			|| agent.unit.getType() == UnitType.Terran_Physics_Lab
    			|| agent.unit.getType() == UnitType.Terran_Armory
    			|| agent.unit.getType() == UnitType.Terran_Academy
    			|| agent.unit.getType() == UnitType.Terran_Control_Tower
    			|| agent.unit.getType() == UnitType.Protoss_Forge
    			|| agent.unit.getType() == UnitType.Protoss_Cybernetics_Core
    	    	|| agent.unit.getType() == UnitType.Protoss_Citadel_of_Adun
    	    	|| agent.unit.getType() == UnitType.Protoss_Templar_Archives
    			|| agent.unit.getType() == UnitType.Protoss_Fleet_Beacon
    			|| agent.unit.getType() == UnitType.Protoss_Arbiter_Tribunal
    			) && agent.unit.isCompleted())
    		return 1;
		else
			return -1;
	}
}
