#include "SupportingObserverMicroBehaviour.h"
#include "Army.h"

SupportingObserverMicroBehaviour::SupportingObserverMicroBehaviour( UnitModel* sub , UnitManager* u )
{
	subject = sub;
	unitManager = u;
	attacking = false;
	moving = false;
	armyEye = Positions::None;
	targettingSystem = new TargetEvaluator(sub);
	currentTarget = NULL;
	targetArmy = NULL;
	id = PROTOSS_MILITARY_OBSERVER;
}

bool SupportingObserverMicroBehaviour::execute()
{
	if(targetArmy == NULL) {
		return false;
	}
	// go through the target army
	// try to find the point where you have to stand in order to maximize the number of covered units
	// prefer to cloak dragoons over zealots
	int avgX = 0;
	int avgY = 0;
	int livingMembers = 0;
	std::vector<UnitModel*> forces = targetArmy->getMembers();
	for (std::vector<UnitModel*>::iterator i = forces.begin(); i != forces.end(); ++i)
	{
		UnitModel* cur = *i;
		if(!cur->isAlive()) {
			continue;
		}
		avgX = avgX+cur->getPosition().x();
		avgY = avgY+cur->getPosition().y();
		livingMembers++;
	}

	Position avgPos = Positions::None;
	if(livingMembers == 0) {
		//////Broodwar->sendText("dead army!");
		return false;
	} else {
		avgX = avgX/livingMembers;
		avgY = avgY/livingMembers;
		avgPos = Position(avgX, avgY);
	}
	// generate a cloud around the average point of all the thing you want to cloak
	// then score each position based on your interests - ie. enemy units in weapons range of that point
	// then change that over time, so prefer safer points as you lose shields and health
	ParticleGenerator* p = new ParticleGenerator(128, 128, avgPos);
	std::vector<Position> v = p->generate();
	Position bestPointSoFar = Positions::None;
	int bestScoreSoFar = -1000;
	for(std::vector<Position>::const_iterator i = v.begin(); i != v.end(); i++) {
		Position cur = *i;

		int currentScore = 0;
			if(bestPointSoFar == Positions::None) {
				bestPointSoFar = cur;
			} else {
				// score point 1: the number of enemy units in weapons range of this point
				// ie. it's safety
				std::vector<UnitModel*> enemiesInRange = unitManager->getAllEnemyUnitsInRange(cur, UnitTypes::Protoss_Arbiter.sightRange());
				for(std::vector<UnitModel*>::const_iterator it = enemiesInRange.begin(); it != enemiesInRange.end(); it++) {
					UnitModel* ncur = *it;
					if(!ncur->getUnit()->isDetected()) {
						currentScore+=250;
					} else {
					if(cur.getDistance(ncur->getPosition()) <= ncur->getType().airWeapon().maxRange()*1.3) {
						currentScore -= (100+(500-(subject->getHP()+subject->getShields())));
						if(ncur->getType() == UnitTypes::Terran_Missile_Turret) {
							currentScore -= 1000;		
						}
						if(ncur->getType() == UnitTypes::Zerg_Spore_Colony) {
							currentScore -= 1000;
						}
						if(ncur->getType() == UnitTypes::Protoss_Photon_Cannon) {
							currentScore -= 1000;
						}
					}
					}
				}

				// score point 2, the number of friendly units in cloak range of this point
				// ie. it's utility
				std::vector<UnitModel*> friendliesInRange = unitManager->getFriendlyMilitaryUnitsInRange(cur, UnitTypes::Protoss_Arbiter.sightRange()*0.7);
				for(std::vector<UnitModel*>::const_iterator it = friendliesInRange.begin(); it != friendliesInRange.end(); it++) {
					UnitModel* ncur = *it;
					if(ncur->isStasised()) {
						currentScore -= 100;
					} else {
						currentScore += 100;
					}
					if(ncur->getUnit()->isAttacking()) {
						currentScore+=50;
					}
				}

				if(currentScore > bestScoreSoFar) {
					bestPointSoFar = cur;
					bestScoreSoFar = currentScore;
				}
			}
		}
	if(bestPointSoFar != Positions::None) {
		if(Broodwar->getFrameCount()%4 == 0) {
		subject->getUnit()->move(bestPointSoFar);
		}
	}
	return false;
}

void SupportingObserverMicroBehaviour::nudge()
{

}

void SupportingObserverMicroBehaviour::setTargetArmy( Army* a )
{
	targetArmy = a;
}

void SupportingObserverMicroBehaviour::clearTargetArmy()
{
	targetArmy = NULL;
}
