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

import com.tyr.BWTAProxy;
import com.tyr.Tyr;
import com.tyr.agents.Agent;
import com.tyr.unitgroups.MineralWorkers;

import bwapi.Color;
import bwapi.Position;
import bwapi.TilePosition;
import bwapi.Unit;
import bwapi.UnitType;

/**
 * Build site locator for finding a placement for a missile turret.
 * @author Simon
 *
 */
public class TurretBuildSite extends BuildSiteLocator 
{
	/**
	 * The locations for building turrets.
	 */
	public TilePosition[] turretPositions = new TilePosition[2];
	
	/**
	 * The base for which we are building these turrets.
	 */
	public MineralWorkers base;
	
	/**
	 * Build site locator for finding a placement for a missile turret.
	 * @param base The base for which we will build a missile turret.
	 */
	public TurretBuildSite(MineralWorkers base)
	{
		this.base = base;
		this.getTurretPositions();
	}
	
	@Override
	public TilePosition findPlacement(UnitType building, TilePosition preferredTile, Agent worker)
	{
		if (building != UnitType.Terran_Missile_Turret)
			return null;
		
		if (!BWTAProxy.initialized)
			return null;
		
		// Go through the list of placements to determine a suitable one.
		for(TilePosition pos : turretPositions)
		{
			if (pos == null)
				continue;
			
			// If we can't build on this location we try the next location.
			if (!SpaceManager.canBuildHere(worker.unit, pos.getX(), pos.getY(), building, false, true, true))
				continue;
			
			for (BuildCommand com : Tyr.bot.buildCommands)
				if (com.building == UnitType.Terran_Missile_Turret
						&& ((com.position.getX() == pos.getX() && com.position.getY() == pos.getY())
						|| (pos.getX() - com.position.getX()) * (pos.getX() - com.position.getX()) + (pos.getY() - com.position.getY()) * (pos.getY() - com.position.getY()) <= 4))
					continue;
			
			return pos;
		}
		
		return null;
	}
	
	/**
	 * Determines viable placements for the missile turrets.
	 */
	private void getTurretPositions()
	{
		if (turretPositions[0] != null)
		{
			Tyr.game.drawBoxMap(turretPositions[0].getX()*32, turretPositions[0].getY()*32,
					turretPositions[0].getX()*32 + 64, turretPositions[0].getY()*32 + 64, Color.Orange);
			Tyr.game.drawBoxMap(turretPositions[1].getX()*32, turretPositions[1].getY()*32,
					turretPositions[1].getX()*32 + 64, turretPositions[1].getY()*32 + 64, Color.Orange);
			return;
		}
		Position avg = new Position(0, 0);
		for (Unit mineral : base.minerals)
			avg = new Position(avg.getX() + mineral.getX(), avg.getY() + mineral.getY());
		
		int count = base.minerals.size();
		if (base.gasWorkers != null && base.gasWorkers.geyser != null)
		{
			avg = new Position(avg.getX() + base.gasWorkers.geyser.getX() * 2, avg.getY() + base.gasWorkers.geyser.getY() * 2);
			count += 2;
		}
		avg = new Position(avg.getX() / count, avg.getY() / count);
		
		Position mid = base.resourceDepot.getPosition();
		Position dir = new Position(mid.getX() - avg.getX(), mid.getY() - avg.getY());
		int length = (int)Math.sqrt(dir.getX() * dir.getX() + dir.getY() * dir.getY());
		Position p1 = Tyr.tileToPosition(Tyr.positionToTile(new Position (mid.getX() + dir.getY()*150 / length, mid.getY() - dir.getX()*150 / length)));
		Position p2 = Tyr.tileToPosition(Tyr.positionToTile(new Position (mid.getX() - dir.getY()*150 / length, mid.getY() + dir.getX()*150 / length)));
		//Tyr.game.drawBoxMap(p1.getX() - 32, p1.getY() - 32, p1.getX() + 32, p1.getY() + 32, Color.Orange);
		//Tyr.game.drawBoxMap(p2.getX() - 32, p2.getY() - 32, p2.getX() + 32, p2.getY() + 32, Color.Orange);

		for(int i=0; i<6; i++)
		{
			if (i == 5)
			{
				Agent worker = Tyr.bot.workForce.pop();
				if (worker == null)
					break;
				p1 = Tyr.tileToPosition(new DefaultBuildSite().findPlacement(UnitType.Terran_Missile_Turret, Tyr.positionToTile(p1), worker));
				Tyr.bot.workForce.add(worker);
				break;
			}
			TilePosition temp = Tyr.positionToTile(p1);
			boolean success = true;
			for(int x=0; success && x<2; x++)
				for(int y=0; success && y<2; y++)
				{
					if (temp.getX() + x >= Tyr.bot.spaceManager.map.length || temp.getY() + y >= Tyr.bot.spaceManager.map[0].length)
					{
						success = false;
						System.out.println("p1 incorrect: " + temp.getX() + ", " + temp.getY());
					}
					else if (Tyr.bot.spaceManager.map[temp.getX() + x][temp.getY() + y] != 1)
						success = false;
				}
			if (success)
				break;
			Position newp1 = Tyr.tileToPosition(Tyr.positionToTile(new Position (mid.getX() + dir.getY()*150 / length + dir.getX() * 32 * (i+1)/length, 
					mid.getY() - dir.getX()*150 / length + dir.getY() * 32 * (i+1)/length)));
			temp = Tyr.positionToTile(newp1);
			if (temp.getX() < 0 || temp.getX() >= Tyr.game.mapWidth() - 2 || temp.getY() < 0 || temp.getY() >= Tyr.game.mapHeight() - 2)
				break;
			p1 = newp1;
		}
		
		for(int i=0; i<6; i++)
		{
			if (i == 5)
			{
				Agent worker = Tyr.bot.workForce.pop();
				if (worker == null)
					break;
				p2 = Tyr.tileToPosition(new DefaultBuildSite().findPlacement(UnitType.Terran_Missile_Turret, Tyr.positionToTile(p2), worker));
				Tyr.bot.workForce.add(worker);
				break;
			}
			TilePosition temp = Tyr.positionToTile(p2);
			boolean success = true;
			for(int x=0; success && x<2; x++)
				for(int y=0; success && y<2; y++)
				{
					if (temp.getX() + x >= Tyr.bot.spaceManager.map.length || temp.getY() + y >= Tyr.bot.spaceManager.map[0].length)
					{
						success = false;
						System.out.println("p2 incorrect: " + temp.getX() + ", " + temp.getY());
					}
					else if (Tyr.bot.spaceManager.map[temp.getX() + x][temp.getY() + y] != 1)
						success = false;
				}
			if (success)
				break;
			Position newp2 = Tyr.tileToPosition(Tyr.positionToTile(new Position (mid.getX() - dir.getY()*150 / length + dir.getX() * 32 * (i+1)/length, 
					mid.getY() + dir.getX()*150 / length + dir.getY() * 32 * (i+1)/length)));
			temp = Tyr.positionToTile(newp2);
			if (temp.getX() < 0 || temp.getX() >= Tyr.game.mapWidth() - 2 || temp.getY() < 0 || temp.getY() >= Tyr.game.mapHeight() - 2)
				break;
			p2 = newp2;
		}
		
		turretPositions[0] = Tyr.positionToTile(p1);
		turretPositions[1] = Tyr.positionToTile(p2);
	}
	
	@Override
	public boolean alreadyReserved()
	{
		return true;
	}
}
