#include "RoamingScoutMicroBehaviour.h"
#include "BaseModel.h"

RoamingScoutMicroBehaviour::RoamingScoutMicroBehaviour( UnitModel* sub , UnitManager* u )
{
	unitManager = u;
	subject = sub;
	targetPosition = BWAPI::Positions::None;
	targetCell = NULL;
	//pickNewTarget();
	currentTarget = NULL;
	id = PROTOSS_ROAMING_SCOUT;
		targettingSystem = new TargetEvaluator(sub);
}

bool RoamingScoutMicroBehaviour::execute()
{
	if(!subject->getUnit()->isCompleted()) {
		return true;
	}

	if((subject->isBeingTargetted() || subject->getQualitativeShields() < 25)){
		if(currentTarget != NULL && currentTarget->getQualitativeHP() <= 25) {

		} else {
		if(targetCell != NULL) {
			relinquishExploreTarget();
			currentTarget = NULL;
			subject->pathStop();
		}
		Position bestEscapePoint = unitManager->getClosestNeutralOrFriendlyBasePos(subject->getPosition());
		if(BWTA::getRegion(bestEscapePoint) == subject->getRegion()) {
			bestEscapePoint = unitManager->getClosestNeutralOrFriendlyBasePosNot(subject->getPosition(), subject->getRegion());
		}
		subject->getUnit()->move(bestEscapePoint);
		return true;
		}
	}

	if(currentTarget != NULL && currentTarget->isAlive() && currentTarget->getUnit()->isVisible() && subject->getQualitativeShields() > 25) {
		subject->attack(currentTarget);
		return true;
	}

	lookForAttackTarget();
	if(currentTarget != NULL) {
		alertNearByAllies();
	}

	if(targetCell != NULL) {
		//Broodwar->drawLineMap(subject->getPosition().x(), subject->getPosition().y(), targetPosition.x(), targetPosition.y(), BWAPI::Colors::Yellow);

		if(subject->getPosition().getDistance(targetPosition) <= 200) {
			relinquishExploreTarget();
			//Broodwar->drawEllipseMap(subject->getPosition().x(), subject->getPosition().y(), 8, 8, BWAPI::Colors::Yellow, true);
			subject->pathStop();
		} else {
			if(subject->getUnit()->isMoving()) {
				//Broodwar->drawEllipseMap(targetPosition.x(), targetPosition.y(), 8, 8, BWAPI::Colors::Green, true);
			} else {
				subject->pathMove((TilePosition)targetPosition, PATHFINDING_THREATAWARE_ASTAR_AIR);
			}
		}

	} else {
		pickNewExploreTarget();

	}
	return false;
}

void RoamingScoutMicroBehaviour::nudge()
{

}

void RoamingScoutMicroBehaviour::pickNewExploreTarget()
{
	// 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->getInformationValue() == 0.00) {
			continue;
		}

		if(bestCell == NULL) {
			bestCell = cur;
		} else {
			int distance = cur->getPosition().getDistance(subject->getPosition());
			float qualityValue = cur->getInformationValue()+(rand()%1000);
			if(cur->isBeingExplored()) {
				qualityValue*=0.5;
			}
			if(qualityValue > bestRatio) {
				bestCell = cur;
				bestRatio = qualityValue;
			}
		}
	}
	targetCell = bestCell;
	if(targetCell == NULL) {
		targetPosition = BWAPI::Positions::None;
		return;
	}
	targetPosition = bestCell->getPosition();
}

void RoamingScoutMicroBehaviour::relinquishExploreTarget()
{
	if(targetCell != NULL) {
		targetCell = NULL;
	}
}

void RoamingScoutMicroBehaviour::lookForAttackTarget()
{
	if(Broodwar->getFrameCount()%4==0) {
		std::vector<UnitModel*> units = unitManager->getAllEnemyUnitsInRange(subject->getPosition(), 312);
		if(units.empty()) {
			return;
		}
		if(currentTarget != NULL) {
			if(!currentTarget->isAlive()) {
				currentTarget = NULL;
			}
		}
		int bestScoreSoFar = 0;
		UnitModel* bestTarget = NULL;
		for (vector<UnitModel*>::iterator i = units.begin(); i != units.end(); ++i)
		{
			UnitModel* cur = *i;
			if(subject->getType() == UnitTypes::Protoss_Corsair) {
				if(!cur->getType().isFlyer()) {
					continue;
				}
			}
			if(!cur->getUnit()->isVisible()) { 
				continue;
			}
			if(cur->getUnit()->isVisible() && cur->getUnit()->isLoaded()) {
				continue;
			}
			//Broodwar->drawLineMap(cur->getPosition().x(), cur->getPosition().y(), subject->getPosition().x(), subject->getPosition().y(), Colors::White);


			if(bestTarget == NULL) {
				bestTarget = cur;
			} else {
				int candidateValue = targettingSystem->calculateValueOf(cur);
				if(cur->getType() == UnitTypes::Zerg_Overlord || cur->getType() == UnitTypes::Zerg_Zergling) {
					if(subject->getPosition().getDistance(cur->getPosition()) < subject->getType().sightRange()) {
					candidateValue += 10000;
					}
				}
				if(candidateValue > bestScoreSoFar) {
					bestScoreSoFar = candidateValue;
					bestTarget = cur;
				}
			}
		}
		currentTarget = bestTarget;

	}
}

void RoamingScoutMicroBehaviour::alertNearByAllies()
{
	std::vector<UnitModel*> allies = unitManager->getAllFriendlyUnitsOfType(subject->getType());

	for (vector<UnitModel*>::iterator i = allies.begin(); i != allies.end(); ++i)
	{
		UnitModel* cur = *i;
		RoamingScoutMicroBehaviour* beh = (RoamingScoutMicroBehaviour*)cur->getMicroBehaviour();
		if(cur->getPosition().getDistance(subject->getPosition()) <= 1024) {
			if(beh->getCurrentTarget() != NULL) {
				beh->setCurrentTarget(currentTarget);

			}
		}

	}

}
