#include "DefenseMonitor.h"
#include "Overseer.h"
//#include "Windows.h"

DefenseMonitor::DefenseMonitor( Overseer* o )
{
	overseer = o;
}

void DefenseMonitor::monitor()
{
	if(Broodwar->getFrameCount()%12==0) {
		//////OutputDebugString(TEXT("\t * getting bases\n"));
		friendlyBases = overseer->getUnitManager()->getFriendlyBaseModels();
		//////OutputDebugString(TEXT("\t\t * got em\n"));
		if(friendlyBases.empty()) {
			return;
		}
		std::vector<Position> positionsUnderAttack;

		// see if anything is under attack, and record the locations
		for(std::vector<BaseModel*>::const_iterator i = friendlyBases.begin(); i != friendlyBases.end(); ++i) {
			BaseModel* cur = *i;
			if(cur == NULL) {
				continue;
			}
			if(!cur->isAlive()) {
				continue;
			}
			if(cur != NULL && cur->isAlive() && cur->isUnderThreat()) {

				Position attackPosition = cur->getBaseThreatLoc();
				//////OutputDebugString(TEXT("\t \t \t * got the attack loc\n"));
				if(attackPosition != Positions::None && !cur->isBeingDefended()) {
					//////OutputDebugString(TEXT("\t \t \t * popping it in!\n"));
					positionsUnderAttack.push_back(attackPosition);
					//////OutputDebugString(TEXT("\t \t \t * done!\n"));
				}
			}
		}

		monitorBuildingsUnderConstruction();

		if(positionsUnderAttack.empty()) {
			return;
		}

		// so now we need to know if we have anything we can use to defend against this attack
		//////OutputDebugString(TEXT("\t* getting mil units\n"));
		std::vector<UnitModel*> units = overseer->getUnitManager()->getFriendlyMilitaryUnits();
		if(units.empty()) {
			return;
		}
		std::vector<UnitModel*> potentialDefenders;
		for(std::vector<UnitModel*>::const_iterator it = units.begin(); it != units.end(); it++) {
			UnitModel* cur = *it;
			if(!cur->isAlive()) {
				continue;
			}
			//////OutputDebugString(TEXT("\t\t* looking at a dude\n"));
			if(cur->getCurrentTaskType() == NO_TASK) {
				potentialDefenders.push_back(cur);
			}
			if(cur->getCurrentTaskType() == GUARD) {
				if(cur->getPosition().getDistance(*positionsUnderAttack.begin()) < 512) {
					if(!cur->isBeingTargetted() && !cur->getUnit()->isMoving()) {
						potentialDefenders.push_back(cur);
					}
				}
			}
		}

		for(std::vector<Position>::const_iterator i = positionsUnderAttack.begin(); i != positionsUnderAttack.end(); ++i) {
			Position cur = *i;
			overseer->getUnitManager()->requestDefense((TilePosition)cur, 1, false);
		}
	}
	if(Broodwar->getFrameCount()%1024 == 0) {
		if(Broodwar->self()->minerals() >= 2000) {
			manageMainBaseCannonDefense();
		}
	}

}

void DefenseMonitor::monitorBuildingsUnderConstruction()
{
	std::vector<UnitModel*> units = overseer->getUnitManager()->getFriendlyBuildings();
	for(std::vector<UnitModel*>::const_iterator i = units.begin(); i != units.end(); ++i) {
		UnitModel* cur = *i;
		Unit* curU = cur->getUnit();
		if(curU->isBeingConstructed()) {
			if(curU->isUnderAttack()) {
				if(cur->getHP() < 15) {
					////OutputDebugString(TEXT("STOPPED A BUILDING"));
					curU->cancelConstruction();
					//cur->setAlive(false);
					/*
					ConstructionTask* replace = new ConstructionTask(cur->getBaseOwner(),cur->getType(),overseer);
					if(cur->getBaseOwner() != NULL) { 
						if(cur->getBaseOwner()->isFriendlyBase() && cur->getBaseOwner()->getBuildOrder() != NULL) {
							if(cur->getType() == UnitTypes::Protoss_Nexus) {
								cur->getBaseOwner()->getBuildOrder()->addToOpeningSequenceUrgent(UnitTypes::Protoss_Nexus);
							} else {
								cur->getBaseOwner()->getBuildOrder()->addToOpeningSequence(replace);
							}
						}
					}
					*/
				}
			}

		}

	}
}

void DefenseMonitor::manageMainBaseCannonDefense()
{
	BaseModel* fb = overseer->getUnitManager()->getFriendlyMainBase();
	int numGateways = fb->countNumTypeInBase(UnitTypes::Protoss_Gateway);

	if(numGateways == 0 || !overseer->getUnitManager()->hasBuildingComplete(UnitTypes::Protoss_Forge)) {
		return;
	}

	int numGuns = fb->countNumTypeInBase(UnitTypes::Protoss_Photon_Cannon);
	if(numGuns > 3) {
		return;
	}
	if(numGuns < (numGateways*0.7)) {
		fb->getBuildOrder()->addToOpeningSequence(UnitTypes::Protoss_Photon_Cannon);

		std::set<UnitModel*> gateways = overseer->getUnitManager()->getAllFriendlyBuildingsOfType(UnitTypes::Protoss_Gateway);
		if(!gateways.empty()) {

		ConstructionTask* c = new ConstructionTask(fb, UnitTypes::Protoss_Photon_Cannon, overseer);
		fb->getBuildOrder()->addToOpeningSequence(c);


		}

	}

}
