#include "Analysis.h"

double Analysis::analyze(TechType tech)
{
	double score = 0;

	return score;
}

double Analysis::analyze(BWAPI::UnitType unit)
{
	double score = 0;
	double likelihoodToAttack = Military::likelihoodToAttack();

	switch (unit)
	{
		case UnitTypes::Zerg_Drone:
			score = analyzeDrone(likelihoodToAttack);
			break;
		case UnitTypes::Zerg_Evolution_Chamber:
			score = analyzeEvoChamber(likelihoodToAttack);
			break;
		case UnitTypes::Zerg_Extractor:
			score = analyzeGas();
			break;
		case UnitTypes::Zerg_Hatchery:
			score = analyzeHatchery(likelihoodToAttack);
			break;
		case UnitTypes::Zerg_Hive:
			score = analyzeHive();
			break;
		case UnitTypes::Zerg_Hydralisk:
			score = analyzeHydralisk(likelihoodToAttack);
			break;
		case UnitTypes::Zerg_Hydralisk_Den:
			score = analyzeHydraDen();
			break;
		case UnitTypes::Zerg_Lair:
			score = analyzeLair();
			break;
		case UnitTypes::Zerg_Mutalisk:
			score = analyzeMutalisk();
			break;
		case UnitTypes::Zerg_Overlord:
			score = analyzeOverlord(likelihoodToAttack);
			break;
		case UnitTypes::Zerg_Queens_Nest:
			score = analyzeQueensNest();
			break;
		case UnitTypes::Zerg_Spawning_Pool:
			score = analyzeSpawningPool();
			break;
		case UnitTypes::Zerg_Spire:
			score = analyzeSpire();
			break;
		case UnitTypes::Zerg_Spore_Colony:
			score = analyzeSpore();
			break;
		case UnitTypes::Zerg_Sunken_Colony:
			score = analyzeSunken();
			break;
		case UnitTypes::Zerg_Ultralisk:
			score = analyzeUltralisk();
			break;
		case UnitTypes::Zerg_Ultralisk_Cavern:
			score = analyzeUltraCavern();
			break;
		case UnitTypes::Zerg_Zergling:
			score = analyzeZergling();
			break;
	}

	return score;
}

double Analysis::analyze(UpgradeType upgrade)
{
	double score = 0;
	switch (upgrade)
	{
		case UpgradeTypes::Grooved_Spines:
			score = analyzeHydraRange();
			break;
		case UpgradeTypes::Metabolic_Boost:
			score = analyzeLingSpeed();
			break;
		case UpgradeTypes::Muscular_Augments:
			score = analyzeHydraSpeed();
			break;
		case UpgradeTypes::Pneumatized_Carapace:
			score = analyzeOverlordSpeed();
			break;
		case UpgradeTypes::Zerg_Carapace:
			score = analyzeGroundArmor();
			break;
		case UpgradeTypes::Zerg_Missile_Attacks:
			score = analyzeMissile();
			break;
	}

	return score;
}

double Analysis::analyzeDrone(double likelihoodToAttack)
{
	double score = 0;
	if (Util::countUnits(Macro::selfID, UnitTypes::Zerg_Drone) < 65)
	{
		score = 1;
	}

	score -= Util::eggCount(UnitTypes::Zerg_Drone) * 0.02;

	if (likelihoodToAttack > 0.7) score -= 0.4;

	return score;
}

double Analysis::analyzeEvoChamber(double likelihoodToAttack)
{
	double score = 1.0;
	if (Military::likelihoodToAttack() > 0.7) score -= 0.4;
	return 1.0;
}

double Analysis::analyzeGas()
{
	return 1.0;
}

double Analysis::analyzeGroundArmor()
{
	return 1.0;
}

double Analysis::analyzeHatchery(double likelihoodToAttack)
{
	double score = 0;

	if (Macro::newBase)
	{
		score = 2;
	}
	else
	{
		score = 2;
	}

	return score - likelihoodToAttack;
}

double Analysis::analyzeHive()
{
	return 0.8;
}

double Analysis::analyzeHydraDen()
{
	double score = 0;
	if (Util::countUnits(Macro::selfID, UnitTypes::Zerg_Hydralisk_Den) == 0)
	{
		score += 0.7;
		if (Broodwar->self()->supplyUsed() >= 38) score += 0.5;
	}
	return score;
}

double Analysis::analyzeHydralisk(double likelihoodToAttack)
{
	if (Broodwar->self()->supplyUsed() > Broodwar->self()->supplyTotal()) return 0;

	double score = 0.8;
	score -= Util::eggCount(UnitTypes::Zerg_Hydralisk) * 0.1;
	//if (Military::likelihoodToAttack() > 0.7) score += 0.3;
	if (likelihoodToAttack < 0.2) score -= 0.4;

	if (!Macro::enemyIDs.empty())
	{
		score += Util::countUnits(Macro::enemyIDs.front(), UnitTypes::Protoss_Zealot) * 0.02;
		score += Util::countUnits(Macro::enemyIDs.front(), UnitTypes::Terran_Firebat) * 0.02;
	}
	return score;
}

double Analysis::analyzeHydraRange()
{
	return 1.0;
}

double Analysis::analyzeHydraSpeed()
{
	return 1.0;
}

double Analysis::analyzeLair()
{
	return 0.8;
}

double Analysis::analyzeLingSpeed()
{
	return 1.0;
}

double Analysis::analyzeMissile()
{
	return 1.0;
}

double Analysis::analyzeMutalisk()
{
	double score = 0.7;
	score -= Util::eggCount(UnitTypes::Zerg_Mutalisk) * 0.1;
	if (!Macro::enemyIDs.empty())
	{
		score -= Util::countUnits(Macro::enemyIDs.front(), UnitTypes::Protoss_Corsair) * 0.05;
		score -= Util::countUnits(Macro::enemyIDs.front(), UnitTypes::Terran_Valkyrie) * 0.05;

		int staticD = Util::getStaticDCount(Macro::enemyIDs.front(), "air");
		score += (0.5 - (staticD * 0.05));
	}
	return score;
}

double Analysis::analyzeOverlord(double likelihoodToAttack)
{
	double score = 1.5;

	if (likelihoodToAttack > 0.7) score -= 0.1;

	return score;
}

double Analysis::analyzeOverlordSpeed()
{
	return 1.0;
}

double Analysis::analyzeQueensNest()
{
	return 1.0;
}

double Analysis::analyzeSpawningPool()
{
	double score = 0;

	if (Util::countUnits(Macro::selfID, UnitTypes::Zerg_Spawning_Pool) == 0)
	{
		score += 0.7;
		if (Broodwar->self()->supplyUsed() >= 24) score += 0.5;
	}

	return score;
}

double Analysis::analyzeSpire()
{
	return 1.0;
}

double Analysis::analyzeSpore()
{
	return 1.0;
}

double Analysis::analyzeSunken()
{
	return 1.3;
}

double Analysis::analyzeUltraCavern()
{
	return 1.0;
}

double Analysis::analyzeUltralisk()
{
	double score = 0.6;
	score -= Util::eggCount(UnitTypes::Zerg_Ultralisk) * 0.1;
	return score;
}

double Analysis::analyzeZergling()
{
	double score = 0.6;
	score -= Util::eggCount(UnitTypes::Zerg_Zergling) * 0.1;
	if (!Macro::enemyIDs.empty())
	{
		score -= Util::countUnits(Macro::enemyIDs.front(), UnitTypes::Protoss_Zealot) * 0.05;
		score -= Util::countUnits(Macro::enemyIDs.front(), UnitTypes::Terran_Firebat) * 0.05;
	}
	else
	{
		score += Util::countUnits(Macro::enemyIDs.front(), UnitTypes::Protoss_Dragoon) * 0.05;
		score += Util::countUnits(Macro::enemyIDs.front(), UnitTypes::Terran_Siege_Tank_Siege_Mode) * 0.1;
		score += Util::countUnits(Macro::enemyIDs.front(), UnitTypes::Terran_Siege_Tank_Tank_Mode) * 0.1;
	}

	if (Util::countUnits(Macro::enemyIDs.front(), UnitTypes::Terran_Factory) > 0)
	{
		score += 0.2;
	}

	return score;
}
