#include "GroundScoutBehaviour.h"


GroundScoutBehaviour::GroundScoutBehaviour( UnitModel* sub , UnitManager* u )
{
	unitManager = u;
	subject = sub;
	targetPosition = BWAPI::Positions::None;
	internalTargetPosition = BWAPI::Positions::None;
	targetCell = NULL;
	scoutingBase = false;
	moving = false;
	nextPoint = 0;
	currentTarget = NULL;
	//////Broodwar->sendText("scout behaviour attached!!!!");
	id = PROTOSS_SCOUTING_PROBE;
	initializeSearchStack();
}

bool GroundScoutBehaviour::execute()
{
	if(!subject->isAlive()) {
		return true;
	} 
	if(searchStack.empty()) {
		subject->clearMicroBehaviour();
		subject->setCurrentTaskType(NO_TASK);
		subject->getUnit()->move(unitManager->getClosestFriendlyBaseModel(subject->getPosition())->getPosition());
		return true;
	}

	std::vector<UnitModel*> enms = unitManager->getAllEnemyUnitsInRange(subject->getPosition(), 300);
	std::vector<UnitModel*> fenms;
	// wait, lets also filter for scouting probes
	for(std::vector<UnitModel*>::iterator i = enms.begin(); i != enms.end(); i++) {
		if((*i)->getType().isWorker()) {
			
		} else {
			fenms.push_back((*i));
		}
		if((*i)->getType().isBuilding()) {
			subject->clearMicroBehaviour();
			subject->setCurrentTaskType(NO_TASK);
			subject->getUnit()->move(unitManager->getClosestFriendlyBaseModel(subject->getPosition())->getPosition());
		}
	}
	

	if(fenms.empty()) {
		
	} else {
		std::set<BWTA::BaseLocation*> blocs = BWTA::getBaseLocations();
		
		BaseLocation* best = NULL;
		UnitModel* target = enms.at(0);
		for(std::set<BWTA::BaseLocation*>::const_iterator i = blocs.begin(); i != blocs.end(); i++) {
			BaseLocation* cur = *i;
			if(!cur->isStartLocation()) {
				continue;
			}
			if(best == NULL) {
				best = cur;
			} else {
				int bdist = best->getPosition().getDistance(target->getPosition());
				int cdist = cur->getPosition().getDistance(target->getPosition());
				if(cdist < bdist) {
					best = cur;
				}
			}

		}
		unitManager->registerSuspectedEnemyBaseLoc(best->getPosition());
	}


	if(subject->getUnit()->isUnderAttack() || searchStack.empty()) {
		// return to main base	
		subject->pathStop();
		if(unitManager->getFriendlyMainBase() != NULL) {
		subject->getUnit()->move(unitManager->getFriendlyMainBase()->getSubject()->getPosition());
		}
		subject->clearMicroBehaviour();
		subject->setCurrentTaskType(NO_TASK);

	}

	
	if(!scoutingBase) {
	if(targetPosition != BWAPI::Positions::None) {

		//Broodwar->drawLineMap(subject->getPosition().x(), subject->getPosition().y(), targetPosition.x(), targetPosition.y(), BWAPI::Colors::Yellow);

		if(subject->getPosition().getDistance(targetPosition) < 256) {
			//scoutingBase = true;
			//subject->pathStop();
			if(!searchStack.empty()) {
			searchStack.pop();
				if(!searchStack.empty()) {
					BaseLocation* tar = searchStack.top();	
					targetPosition = tar->getPosition();
					//subject->pathMove((TilePosition)targetPosition, PATHFINDING_THREATAWARE_ASTAR_GROUND_NO_OBSTACLES);
				}
			}
		} else {
			subject->getUnit()->move(targetPosition);
		}
		
	} else {
		if(searchStack.empty()) {
			pickNewTarget();
		}

	}
	} else {
		
		// note: this is a hack just to test something
		if(internalTargetPosition == BWAPI::Positions::None || subject->getPosition().getDistance(internalTargetPosition) < 128) {
			
			ParticleGenerator* p = new ParticleGenerator(16, 512, subject->getPosition());
			int n = 0;
			std::vector<Position> v = p->generate();
			internalTargetPosition = v.at(n);

			internalTargetPosition = BWTA::getRegion(targetPosition)->getPolygon().getNearestPoint(internalTargetPosition);

			subject->getUnit()->move(internalTargetPosition);	
		
		} else {
			subject->getUnit()->move(internalTargetPosition);
		}

	}

	
	return true;
}

void GroundScoutBehaviour::nudge()
{

}

void GroundScoutBehaviour::pickNewTarget()
{


	/*
	// pick new target
	std::vector<InformationCell*> mapCells = unitManager->getMapInformationSystem()->getMapCells();
	float bestRatio = -1000000;
	InformationCell* bestCell = NULL;
	for (vector<InformationCell*>::iterator i = mapCells.begin(); i != mapCells.end(); ++i)
	{
		InformationCell* cur = *i;

		if(cur->isBeingExplored() || cur->getInformationValue() == 0.00 || cur->getImportance() < 1.0) {
			continue;
		}

		if(bestCell == NULL) {
			bestCell = cur;
		} else {
			int distance = cur->getPosition().getDistance(subject->getPosition());
			float qualityValue = cur->getInformationValue();
			if(qualityValue > bestRatio) {
				bestCell = cur;
				bestRatio = qualityValue;
			}

		}
	}
	if(bestCell == NULL) {
		return;
	}
	targetCell = bestCell;
	targetPosition = bestCell->getPosition();
	targetCell->setBeingExplored(true);
	*/
}

bool compFunc( BaseLocation* a, BaseLocation* b )
{
	BWTA::BaseLocation* s = BWTA::getStartLocation(Broodwar->self());
	int adist = a->getGroundDistance(s);
	int bdist = b->getGroundDistance(s);
	
	return adist < bdist;
}

void GroundScoutBehaviour::initializeSearchStack()
{
	std::set<BWTA::BaseLocation*> blocs = BWTA::getStartLocations();
	std::vector<BWTA::BaseLocation*> fil;
	for (std::set<BWTA::BaseLocation*>::iterator i = blocs.begin(); i != blocs.end(); ++i)
	{
		BaseLocation* cur = *i;
		if(cur == BWTA::getStartLocation(Broodwar->self())) {

		} else {
			fil.push_back(cur);
		}
	}
	sort(fil.begin(), fil.end(), compFunc);
	for (std::vector<BWTA::BaseLocation*>::iterator i = fil.begin(); i != fil.end(); ++i)
	{
		BaseLocation* cur = *i;
		if(cur == BWTA::getStartLocation(Broodwar->self())) {
			continue;
		}
		searchStack.push(cur);
	}

	BaseLocation* tar = searchStack.top();
	targetPosition = tar->getPosition();

}
