#include "InformationCell.h"
#include "UnitManager.h"

InformationCell::InformationCell( int x, int y, int r, float imp, UnitManager* uman, BWTA::BaseLocation* bc)
{
	position = Position(x, y);
	radius = r;
	lastVisited = 1;
	importance = imp;
	informationValue = 0;
	beingExplored = false;
	lastUnitScore = 0;
	unitManager = uman;
	regionEvaluator = new TargetEvaluator(unitManager);
	baseLoc = bc;
	region = BWTA::getRegion(position);
}

//************************************
// Method:    getRadius
// FullName:  InformationCell::getWidth
// Access:    public 
// Returns:   int
// Comments:  none
//************************************
int InformationCell::getRadius()
{
	return radius;
}

//************************************
// Method:    getPosition
// FullName:  InformationCell::getPosition
// Access:    public 
// Returns:   BWAPI::TilePosition
// Comments:  none
//************************************
BWAPI::Position InformationCell::getPosition()
{
	return position;
}

//************************************
// Method:    setLastVisited
// FullName:  InformationCell::setLastVisited
// Access:    public 
// Returns:   void
// Parameter: int tstamp
// Comments:  none
//************************************
void InformationCell::setLastVisited( int tstamp )
{
	lastVisited = tstamp;
}

//************************************
// Method:    updateInformationValue
// FullName:  InformationCell::updateInformationValue
// Access:    public 
// Returns:   void
// Comments:  none
//************************************
void InformationCell::updateInformationValue()
{
	
	// next step: count the interesting things we see at this point, and increase our
	// importance value correspondingly.
	// new importance: old importance+(difference between old and new) so long as new importance > 0


	// also remember that we might want to decay importance over time such as to simulate
	// the decreasing value of the same peice of information
	// maybe we can do this by remember the unit IDs of the stuff we see at each point
	// and then only applying reward for those that were previously unseen

	// see what we can see
	std::set<Unit*> nearbyUnits = Broodwar->getUnitsInRadius(position, 256);
	if(nearbyUnits.empty()) {
		/*
			Tom's Improved Technique
		*/
		float visitationDisparity = Broodwar->getFrameCount()-lastVisited;
		float distanceDisparity = Broodwar->self()->getStartLocation().getDistance((TilePosition)position);
		float scalingConstant = importance;

		// scaling of 0.01 added for sanity/debugging, since numbers get very large and hard to display on-screen
		informationValue = lastUnitScore+(0.01*(visitationDisparity*(scalingConstant*(distanceDisparity))));
	} else {

		// count enemy units seen this time, and increase the importance accordingly
		int count = 0;
		float score = 0;

		// ah but now we care about the believed value of units at this location
		std::vector<UnitModel*> believedUnits = unitManager->getAllEnemyUnitsInRange(position, 256);
		for(std::vector<UnitModel*>::const_iterator i = believedUnits.begin(); i != believedUnits.end(); i++) {
			UnitModel* cur = *i;
			if(!cur->isOwnedByPlayer()) {
				if(cur->getType().isBuilding()) {
					score += 100;
				} else {
					score += 50;
				}
				count++;
			}
		}
		lastUnitScore = score;
		lastVisited = Broodwar->getFrameCount();
		informationValue = 0;
	}


}

//************************************
// Method:    getInformationValue
// FullName:  InformationCell::getInformationValue
// Access:    public 
// Returns:   float
// Comments:  none
//************************************
float InformationCell::getInformationValue()
{
	return informationValue;
}

float InformationCell::getLastUnitScore()
{
	return lastUnitScore;
}

bool InformationCell::isBeingExplored()
{
	return beingExplored;
}

void InformationCell::setBeingExplored(bool status)
{
	beingExplored = status;

}

float InformationCell::getImportance()
{
	return importance;
}

float InformationCell::getRegionAttackValue()
{
	return regionEvaluator->calculateValueOf(BWTA::getRegion(position));
}

int InformationCell::getLastVisited()
{
	return lastVisited;
}

BWTA::Region* InformationCell::getRegion()
{
	return region;
}

void InformationCell::setRegion( BWTA::Region* r )
{
	region = r;
}

BWTA::BaseLocation* InformationCell::getBaseLoc()
{
	return baseLoc;
}

