#include "ArchonGeneralMicroBehaviour.h"
#include "BaseModel.h"

ArchonGeneralMicroBehaviour::ArchonGeneralMicroBehaviour( UnitModel* sub , UnitManager* u )
{
	subject = sub;
	unitManager = u;
	attacking = false;
	moving = false;
	targettingSystem = new TargetEvaluator(sub);
	currentTarget = NULL;
	id = PROTOSS_GENERAL_ARCHON;
	////Broodwar->sendText("insantiated archon");
}

//************************************
// Method:    execute
// FullName:  ArchonGeneralMicroBehaviour::execute
// Access:    virtual public 
// Returns:   void
// Comments:  none
//************************************
bool ArchonGeneralMicroBehaviour::execute()
{
	//Broodwar->drawEllipseMap(subject->getPosition().x(), subject->getPosition().y(), 32, 32, BWAPI::Colors::Green, false);
	std::vector<UnitModel*> units = unitManager->getAllEnemyUnitsInRange(subject->getPosition(), UnitTypes::Protoss_Zealot.sightRange()*1.2);
	if(currentTarget != NULL) {
		//Broodwar->drawLineMap(subject->getPosition().x(), subject->getPosition().y(), currentTarget->getPosition().x(), currentTarget->getPosition().y(), BWAPI::Colors::Red);
	}
	if(subject->getArmyOwner() != NULL) {
		if(subject->getArmyOwner()->isArmyUnderAttack()) {
			if(subject->getArmyOwner()->getCentrePoint().getDistance(subject->getPosition()) > 350) {
				subject->getUnit()->move(subject->getArmyOwner()->getCentrePoint());
				return true;
			}
		}
	}

	bool usingGlobalTargetMap = false;
	if(units.empty()) {
		currentTarget = NULL;
	//	//////Broodwar->sendText("units empty!");
		units = unitManager->getEnemyBuildingsInRegionOf(subject->getTilePosition());
		usingGlobalTargetMap = true;
		if(units.empty()) {
			////////Broodwar->sendText("no buildings");
			return false;
		}
	}
	
	int bestScoreSoFar = 0;
	UnitModel* bestTarget = NULL;
	int bestTarThresh = 0;
	for (vector<UnitModel*>::iterator i = units.begin(); i != units.end(); ++i)
	{
		UnitModel* cur = *i;
		if(!cur->getUnit()->isVisible()) { 
			continue;
		}
		if(subject->getArmyOwner() != NULL){
			if(subject->getArmyOwner()->isAlive()) {
				if(cur->getPosition().getDistance(subject->getArmyOwner()->getCentrePoint()) > 300) {
					continue;
				}
			}
		}

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

		if(bestTarget == NULL) {
			bestTarget = cur;
		} else {
			int targettingPenalty = 0;
			if(cur->getUnit()->isVisible()) {
				targettingPenalty = unitManager->calculateTargettingPenalty(cur->getUnit(), subject);
			}
			int candidateValue = targettingSystem->calculateValueOf(cur, targettingPenalty);
			std::vector<UnitModel*> enemyAllies = unitManager->getAllEnemyUnitsInRange(cur->getPosition(), 96);

			int dangerThresh = 0;
			
			for (vector<UnitModel*>::iterator it = enemyAllies.begin(); it != enemyAllies.end(); ++it)
			{
				UnitModel* cA = *it;
				if(cA->getType().isBuilding() && (cA->getType() != UnitTypes::Zerg_Spore_Colony && cA->getType() != UnitTypes::Zerg_Sunken_Colony && cA->getType() != UnitTypes::Protoss_Photon_Cannon && cA->getType() != UnitTypes::Terran_Bunker)) {
					continue;
				}
				if(cA->getType() == UnitTypes::Terran_Marine) {
					dangerThresh++;
				}
				if(cA->getType() == UnitTypes::Terran_Vulture) {
					dangerThresh++;
				}
				if(cA->getType() == UnitTypes::Zerg_Zergling) {
					dangerThresh++;
				}
				if(cA->getType() == UnitTypes::Zerg_Hydralisk) {
					dangerThresh++;
				}
				if(cA->getType() == UnitTypes::Protoss_Dragoon) {
					dangerThresh++;
				}
				if(cA->getType() == UnitTypes::Terran_Bunker) {
					dangerThresh+=4;
				}

			}

			if(dangerThresh > 4) {
				candidateValue -= 5000;
			}

			if(currentTarget != NULL) {
				if(cur == currentTarget) {
					candidateValue+=200;
				}
			}
			if(cur->getType().isBuilding() && (cur->getType() != UnitTypes::Zerg_Spore_Colony && cur->getType() != UnitTypes::Zerg_Sunken_Colony && cur->getType() != UnitTypes::Protoss_Photon_Cannon && cur->getType() != UnitTypes::Terran_Bunker)) {
				candidateValue -= 500;
				if(subject->getUnit()->isUnderAttack()) {
					candidateValue -= 2000;
				}
			}

			if(candidateValue > bestScoreSoFar) {
				bestScoreSoFar = candidateValue;
				bestTarget = cur;
				bestTarThresh = dangerThresh;
			}
		}
	}

	std::vector<UnitModel*> allies = unitManager->getAllFriendlyUnitsInRange(subject->getPosition(), UnitTypes::Protoss_Zealot.sightRange()*1.2);
	int avgX = 0;
	int avgY = 0;
	int livingMembers = 0;
	for (std::vector<UnitModel*>::iterator i = allies.begin(); i != allies.end(); ++i)
	{
		UnitModel* ncur = *i;
		if(!ncur->isAlive() || ncur == subject) {
			continue;
		}
		avgX = avgX+ncur->getPosition().x();
		avgY = avgY+ncur->getPosition().y();
		livingMembers++;
	}
	if(livingMembers != 0 && bestTarget != NULL) {
	avgX = avgX/livingMembers;
	avgY = avgY/livingMembers;
	Position avgPos = Position(avgX, avgY);
	if(bestTarget->getPosition().getDistance(avgPos) > UnitTypes::Protoss_Dragoon.sightRange() && bestTarThresh >= 2) {
		bestTarget = NULL;
		subject->getUnit()->move((Position)Broodwar->self()->getStartLocation());
		return false;
	}
	}
	
	currentTarget = bestTarget;
	if(subject->getUnit()->isMoving() && subject->getUnit()->getTarget() != NULL) {
		return true;
	}
	if(currentTarget != NULL) {
		if(!subject->getUnit()->isStartingAttack() && !subject->getUnit()->isAttackFrame() && !subject->getUnit()->isAttacking() ) {
			subject->getUnit()->attack(currentTarget->getUnit());
			unitManager->declareTargetToMap(subject, currentTarget->getUnit());
			return true;
		}

	}



	return false;
}

void ArchonGeneralMicroBehaviour::nudge()
{

}
