#include "CowardlyDragoonMicroBehaviour.h"
#include "BaseModel.h"

CowardlyDragoonMicroBehaviour::CowardlyDragoonMicroBehaviour( UnitModel* sub , UnitManager* u )
{
	subject = sub;
	unitManager = u;
	attacking = false;
	moving = false;
		currentTarget = NULL;
		id = PROTOSS_COWARDLY_DRAGOON;
}

//************************************
// Method:    execute
// FullName:  CowardlyDragoonMicroBehaviour::execute
// Access:    virtual public 
// Returns:   void
// Comments:  none
//************************************
bool CowardlyDragoonMicroBehaviour::execute()
{
	bool outcome = false;
	// general idea:
	// cowardly dragoon moves towards some map location
	// if it sees more than one enemy, or if an enemy gets too close, it will try to move back to the nearest base
	// if it sees one enemy, it will try to attack them.
	std::set<Unit*> nearbyUnits = Broodwar->getUnitsInRadius(subject->getPosition(), (subject->getType().airWeapon().maxRange()*2)*0.8);
	//Broodwar->drawEllipseMap(subject->getPosition().x(), subject->getPosition().y(),  subject->getType().airWeapon().maxRange()*2,  subject->getType().airWeapon().maxRange()*2, BWAPI::Colors::Green, false);
	////Broodwar->drawEllipseMap(subject->getPosition().x(), subject->getPosition().y(), subject->getType().groundWeapon().maxRange(), subject->getType().groundWeapon().maxRange(), BWAPI::Colors::Red, false);
	////Broodwar->drawEllipseMap(subject->getPosition().x(), subject->getPosition().y(), subject->getType().sightRange(), subject->getType().sightRange(), BWAPI::Colors::Purple, false);

	// for now this is just the main base, but in the future we want to fall back
	// to the nearest safe point (ie. back to a nearby army)
	Position fallBackLocation = (Position)Broodwar->self()->getStartLocation();


	// so now lets filter for stuff we don't care about
	int unitCount = 0;
	Unit* closestTarget = NULL;
	bool found = false;
	for (set<Unit*>::iterator i = nearbyUnits.begin(); i != nearbyUnits.end(); ++i)
	{
		BWAPI::Unit* curUnit = *i;
		if(closestTarget == NULL) {
			closestTarget = curUnit;
		} else {
			if(subject->getUnit()->getDistance(curUnit) < subject->getUnit()->getDistance(closestTarget)) {
				closestTarget = curUnit;
			}
		}
		if(curUnit->getPlayer() == Broodwar->self() || curUnit->getType().isNeutral() || curUnit->getType().isSpecialBuilding() || curUnit->getType() == UnitTypes::Zerg_Larva || curUnit->getType() == UnitTypes::Zerg_Egg) {

		} else {
			//if(curUnit->isInWeaponRange(subject->getUnit())) {
				unitCount++;
			//}
			//found = true;
		}
	}
	//if(unitCount == 0 && found) {
	//	if(!subject->getUnit()->isAttacking()) {
	//		subject->getUnit()->attack(closestTarget);
	//		return;
	//	}
	//}

	// so whatever is left must be stuff that can hurt us, right?
	//////////Broodwar->sendText("enemies: %d", unitCount);



	// so now we know whether to attack or retreat a bit
	if(unitCount == 1 || (unitCount >= 1 && subject->getRegion() == BWTA::getRegion(fallBackLocation))) {
		if(!subject->getUnit()->isAttacking()) {
			
			if(!subject->getUnit()->isHoldingPosition()) {
				subject->getUnit()->holdPosition();
				outcome = true;
			} else {
				if(subject->getUnit()->isAttacking()) {
					subject->getUnit()->attack(closestTarget);
					outcome = true;
				}
			}
		}
	} else {
			if(unitCount > 1) {

				// move back to the closest force concentration on the map
				subject->getUnit()->move(fallBackLocation);
				outcome = true;
			} 
			if(unitCount == 0) {

				// NOTE: WILL CRASH WITHOUT CHEATS, IE. WITHOUT KNOWING WHERE THE ENEMY BASE IS

				// NOTE: WILL ALSO CRASH IF ENEMY BASE IS DESTROYED - BASE MODEL IS DELETED
				if(!unitManager->getEnemyBaseModels().empty()) {

					// move to a nearby safe-spot, maybe?
					subject->getUnit()->move(unitManager->getEnemyBaseModels().at(0)->getSubject()->getPosition());
					outcome = true;
				}
			}
			//return true;
	}
	
	return outcome;
}

void CowardlyDragoonMicroBehaviour::nudge()
{

}
