/*
 * Set empire rankings in 4 categories.
 */

const string strStrength = "str", strPlanets = "Planet";
const string strStructures = "Structure", strShips = "Ship";
const string strTotalRes = "ResLevels", strMaxRes = "ResMaxLevel";
const string strPopulation = "Population";

const float rankCheckInterval = 0.25f;
float rankCheckTimer = 0.25f;

uint realEmpNum = 0;
uint curEmp = 0;
bool twoPlayerRankings = false;
bool calcRankings = true;

uint statCount = 4;
const string[] rankStats = {"RankMilitary", "RankColonization", "RankResearch", "RankEconomy"};
const string[] ptsStats = {"PtsMilitary", "PtsColonization", "PtsResearch", "PtsEconomy"};

const string[] econResources = {"AdvPartsProd", "ElectronicsProd", "MetalsProd"};
const float[] econMultipliers = {18.f, 6.f, 1.f};

void init() {
	// Count the number of actual empires
	uint cnt = getEmpireCount();
	for (uint i = 0; i < cnt; ++i) {
		Empire@ emp = getEmpire(i);

		if (emp.isValid() && emp.ID >= 0)
			++realEmpNum;
	}

	// Check if we should do rankings
	twoPlayerRankings = getGameSetting("GAME_TWO_PLAYER_RANKINGS", 0.f) > 0.5;
	calcRankings = realEmpNum > 2 || twoPlayerRankings;
}

void tick(float time) {
	if (!calcRankings)
		return;

	if (rankCheckTimer >= rankCheckInterval) {
		rankCheckTimer = 0.f;

		double[] points(statCount);
		uint[] rankings(statCount);

		// == Calculate points
		uint cnt = getEmpireCount();
		Empire@ emp = getEmpire(curEmp);
		curEmp = (curEmp + 1) % cnt;

		// Skip over invalid empires
		if (emp.ID < 0 || !emp.isValid())
			return;

		// * Military
		points[0] = emp.getStat(strStrength);

		// * Colonization
		points[1] = emp.getStat(strPlanets) * 10 + emp.getStat(strStructures);

		// * Research
		double resPts = 0.f;
		resPts = emp.getResearchRate();
		resPts *= max(emp.getStat(strTotalRes), 1.0);
		resPts *= max(emp.getStat(strMaxRes), 1.0);
		points[2] = resPts;

		// * Economy
		double econPts = 0.f;
		for (uint k = 0; k < econResources.length(); ++k)
			econPts += emp.getStat(econResources[k]) * econMultipliers[k];
		points[3] = econPts * emp.getStat(strPopulation);

		// Save the points in the empire
		for (uint p = 0; p < statCount; ++p)
			emp.setStat(ptsStats[p], points[p]);

		// == Calculate rankings
		// Reset rankings
		for (uint p = 0; p < statCount; ++p)
			rankings[p] = 1;

		// Find the actual ranking
		uint metEmpires = 0;
		for (uint n = 0; n < cnt; ++n) {
			Empire@ otherEmp = getEmpire(n);

			// Skip over invalid empires and empires we haven't met yet
			if (otherEmp.ID < 0 || !otherEmp.isValid() || otherEmp is emp || !emp.hasMet(otherEmp))
				continue;

			++metEmpires;

			for (uint p = 0; p < statCount; ++p)
				if (otherEmp.getStat(ptsStats[p]) > points[p])
					++rankings[p];
		}

		// Set the correct stats
		if (metEmpires == 0 || (metEmpires == 1 && !twoPlayerRankings))
			for (uint p = 0; p < statCount; ++p)
				emp.setStat(rankStats[p], 0.0);
		else
			for (uint p = 0; p < statCount; ++p)
				emp.setStat(rankStats[p], double(rankings[p]));
	}
	else
		rankCheckTimer += time;
}
