#include "Scouting.h"

//@TODO this is fugly
TilePosition Scouting::getScoutingLocation()
{
	TilePosition location = TilePosition(0, 0);

	int count = 0;
	// check start locations first
	int lastChecked = 180*60*24; // a game probably won't go on three hours
	int index = -1;

	// give priority to scouting the next likely enemy base and then their bases
	if (!Macro::enemyIDs.empty())
	{
		if (!Macro::players.at(Macro::enemyIDs.front()).bases.empty())
		{
			CBase nextExpand = Util::getNextExpand(Macro::enemyIDs.front());
			for (size_t i = 0; i < Macro::locations.size(); i++)
			{
				if (nextExpand.tilePosition == Macro::locations.at(i).tilePosition)
				{
					if (!locationScouted(Macro::locations.at(i))
						&& Macro::locations.at(i).lastScouted < lastChecked
						&& Macro::locations.at(i).lastScouted > Broodwar->getFrameCount() - (30 * 24))
					{
						lastChecked = Macro::locations.at(i).lastScouted;
						index = i;
					}
				}
			}
			if (index > -1) return Macro::locations.at(index).tilePosition;
		}

		for (size_t i = 0; i < Macro::locations.size(); i++)
		{
			if (Util::ownedBy(Macro::locations.at(i).tilePosition) == Macro::enemyIDs.front())
			{
				if (!locationScouted(Macro::locations.at(i))
					&& Macro::locations.at(i).lastScouted < lastChecked
					&& Macro::locations.at(i).lastScouted > Broodwar->getFrameCount() - (60 * 24))
				{
					lastChecked = Macro::locations.at(i).lastScouted;
					index = i;
				}
			}
		}
		if (index > -1) return Macro::locations.at(index).tilePosition;
	}

	// start locations if the enemy hasn't been found
	else
	{
		for (size_t i = 0; i < Macro::locations.size(); i++)
		{
			if (!locationScouted(Macro::locations.at(i))
				&& Macro::locations.at(i).startLocation)
			{
				if (Macro::locations.at(i).lastScouted < lastChecked
					&& Macro::locations.at(i).lastScouted > Broodwar->getFrameCount() - (60 * 24))
				{
					lastChecked = Macro::locations.at(i).lastScouted;
					index = i;
				}
			}
		}
		if (index > -1) return Macro::locations.at(index).tilePosition;
	}
	
	lastChecked = 180 * 60 * 24;
	index = -1;
	for (size_t i = 0; i < Macro::locations.size(); i++)
	{
		if (!locationScouted(Macro::locations.at(i)))
		{
			if (Macro::locations.at(i).lastScouted < lastChecked)
			{
				lastChecked = Macro::locations.at(i).lastScouted;
				index = i;
			}
		}
	}
	
	return Macro::locations.at(index).tilePosition;
}

bool Scouting::locationScouted(Location l)
{
	for (size_t i = 0; i < Macro::scouts.size(); i++)
	{
		if (Macro::scouts.at(i).target == l.tilePosition) return true;
		if (Macro::players.at(Macro::selfID).bases.front().tilePosition == l.tilePosition) return true;
	}
	return false;
}

void Scouting::scout()
{
	if (Broodwar->getFrameCount() > 60 * 24 
		&& Broodwar->getFrameCount() < 120 * 24
		&& !Macro::workerScout)
	{
		for (size_t i = 0; i < Macro::players.at(Macro::selfID).units.size(); i++)
		{
			if (Macro::players.at(Macro::selfID).units.at(i).unit->getType() == UnitTypes::Zerg_Drone 
				&& !Macro::workerScout)
			{
				Macro::freeUnit(i);
				Macro::players.at(Macro::selfID).units.at(i).action = "scout";
				Macro::players.at(Macro::selfID).units.at(i).unit->move(Position(Macro::players.at(Macro::selfID).bases.front().tilePosition), false);
				//Macro::players.at(Macro::selfID).units.at(i).unit->stop();
				for (size_t j = 0; j < Macro::locations.size(); j++)
				{
					if (Macro::locations.at(j).startLocation)
					{
						Macro::players.at(Macro::selfID).units.at(i).unit->move(Position(Macro::locations.at(j).tilePosition), true);
					}
				}
				Macro::players.at(Macro::selfID).units.at(i).unit->move(Position(Macro::players.at(Macro::selfID).bases.front().tilePosition), true);
				Macro::workerScout = true;
			}
		}
	}

	for (size_t i = 0; i < Macro::scouts.size(); i++)
	{
		if (Macro::scouts.at(i).target == TilePosition(-1, -1))
		{
			Macro::scouts.at(i).target = getScoutingLocation();
			Macro::scouts.at(i).unit->move(Position(Macro::scouts.at(i).target));
		}
		else
		{
			if (Military::isThreatened(Macro::scouts.at(i).unit->getTilePosition()))
			{
				std::vector<double> direction = BuildingPlacement::getDirection(Macro::scouts.at(i).unit->getTilePosition(), Macro::scouts.at(i).target);
				int x = Macro::scouts.at(i).unit->getTilePosition().x + direction.front() * 5;
				int y = Macro::scouts.at(i).unit->getTilePosition().y + direction.back() * 5;

				TilePosition moveTo = TilePosition(x, y);
				Macro::scouts.at(i).unit->move(Position(moveTo));
			}
			else if (Military::isThreatened(Macro::scouts.at(i).target))
			{
				Macro::scouts.at(i).target = getScoutingLocation();
				Macro::scouts.at(i).unit->move(Position(Macro::scouts.at(i).target));
			}
			if (Util::getDistance(Macro::scouts.at(i).unit->getTilePosition(), Macro::scouts.at(i).target) < 8)
			{
				int loc = Util::getLocation(Macro::scouts.at(i).target);
				Macro::locations.at(loc).lastScouted = Broodwar->getFrameCount();
				Macro::scouts.at(i).target = getScoutingLocation();
				Macro::scouts.at(i).unit->move(Position(Macro::scouts.at(i).target));
			}
		}
	}
}

void Scouting::setScouts()
{
	if (Macro::scouts.size() < 4)
	{
		bool added = false;
		for (size_t i = 0; i < Macro::players.at(Macro::selfID).units.size(); i++)
		{
			if (Macro::players.at(Macro::selfID).units.at(i).unit->getType() == UnitTypes::Zerg_Overlord && !added)
			{
				if (!added && !Macro::players.at(Macro::selfID).units.at(i).isScout || Macro::scouts.size() == 0)
				{
					Macro::players.at(Macro::selfID).units.at(i).action = "scout";
					Macro::players.at(Macro::selfID).units.at(i).isScout = true;
					Macro::scouts.push_back(Macro::players.at(Macro::selfID).units.at(i));
					added = true;
				}
			}
		}
	}
}