var EconomyManager = Class({

	_init: function()
	{
		this.baseNumWorkers = 30; // minimum number of workers we want
		this.targetNumWorkers = 55; // minimum number of workers we want
		this.targetNumBuilders = 6; // number of workers we want working on construction
		this.changetimeRegBui = 180*1000;
		// (This is a stupid design where we just construct certain numbers
		// of certain buildings in sequence)
		// Greek building list
		// Relative proportions of workers to assign to each resource type
		this.gatherWeights = {
			"food": 140,
			"wood": 140,
			"stone": 50,
			"metal": 120,
		};
	},

	
	checkBuildingList: function (gameState) {
			if (gameState.displayCiv() == "hele"){
		this.targetBuildings = [
			{
				"template": "structures/{civ}_civil_centre",
				"priority": 500,
				"count": 1,
			},
			{
				"template": "structures/{civ}_house",
				"priority": 110,
				"count": 2,
			},
			{
				"template": "structures/{civ}_scout_tower",
				"priority": 105,
				"count": 1,
			},
				{
				"template": "structures/{civ}_field",
				"priority": 103,
				"count": 1,
			},
			{
				"template": "structures/{civ}_barracks",
				"priority": 101,
				"count": 1,
			},
			{
				"template": "structures/{civ}_house",
				"priority": 100,
				"count": 5,
			},
			{
				"template": "structures/{civ}_scout_tower",
				"priority": 90,
				"count": 3,
			},
			{
				"template": "structures/hele_gymnasion",
				"priority": 80,
				"count": 1,
			},
				{
				"template": "structures/{civ}_field",
				"priority": 70,
				"count": 2,
			},
			{
				"template": "structures/hele_fortress",
				"priority": 60,
				"count": 1,
			},
			{
				"template": "structures/{civ}_house",
				"priority": 55,
				"count": 10,
			},
			{
				"template": "structures/{civ}_scout_tower",
				"priority": 50,
				"count": 5,
			},
			{
				"template": "structures/{civ}_house",
				"priority": 45,
				"count": 15,
			},
			{
				"template": "structures/{civ}_field",
				"priority": 40,
				"count": 3,
			},
			{
				"template": "structures/{civ}_house",
				"priority": 30,
				"count": 20,
			},
		];
			}
			// Celt building list
			else if (gameState.displayCiv() == "celt"){
		this.targetBuildings = [
			{
				"template": "structures/{civ}_civil_centre",
				"priority": 500,
				"count": 1,
			},
			{
				"template": "structures/{civ}_house",
				"priority": 110,
				"count": 6,
			},
				{
				"template": "structures/{civ}_field",
				"priority": 100,
				"count": 2,
			},
			{
				"template": "structures/{civ}_barracks",
				"priority": 90,
				"count": 1,
			},
			{
				"template": "structures/celt_fortress_b",
				"priority": 80,
				"count": 1,
			},
			{
				"template": "structures/{civ}_scout_tower",
				"priority": 60,
				"count": 3,
			},
			{
				"template": "structures/{civ}_house",
				"priority": 55,
				"count": 15,
			},
			{
				"template": "structures/{civ}_field",
				"priority": 40,
				"count": 3,
			},
			{
				"template": "structures/{civ}_house",
				"priority": 30,
				"count": 25,
			},
		];
			}
			// Celt building list
			else if (gameState.displayCiv() == "iber"){
		this.targetBuildings = [
			{
				"template": "structures/{civ}_civil_centre",
				"priority": 500,
				"count": 1,
			},
			{
				"template": "structures/{civ}_house",
				"priority": 110,
				"count": 6,
			},
				{
				"template": "structures/{civ}_field",
				"priority": 100,
				"count": 2,
			},
			{
				"template": "structures/{civ}_barracks",
				"priority": 100,
				"count": 1,
			},
			{
				"template": "structures/iber_fortress",
				"priority": 80,
				"count": 1,
			},
			{
				"template": "structures/{civ}_scout_tower",
				"priority": 70,
				"count": 3,
			},
			{
				"template": "structures/{civ}_house",
				"priority": 55,
				"count": 15,
			},
			{
				"template": "structures/{civ}_field",
				"priority": 40,
				"count": 3,
			},
			{
				"template": "structures/{civ}_house",
				"priority": 30,
				"count": 25,
			},
		];
			}

			// Fallback option just in case
		else {
		this.targetBuildings = [
			{
				"template": "structures/{civ}_civil_centre",
				"priority": 500,
				"count": 1,
			},
			{
				"template": "structures/{civ}_house",
				"priority": 110,
				"count": 2,
			},
			{
				"template": "structures/{civ}_scout_tower",
				"priority": 105,
				"count": 1,
			},
			{
				"template": "structures/{civ}_house",
				"priority": 100,
				"count": 5,
			},
				{
				"template": "structures/{civ}_field",
				"priority": 100,
				"count": 2,
			},
			{
				"template": "structures/{civ}_barracks",
				"priority": 99,
				"count": 1,
			},
			{
				"template": "structures/{civ}_house",
				"priority": 98,
				"count": 7,
			},
			{
				"template": "structures/{civ}_scout_tower",
				"priority": 60,
				"count": 4,
			},
			{
				"template": "structures/{civ}_house",
				"priority": 55,
				"count": 15,
			},
			{
				"template": "structures/{civ}_field",
				"priority": 40,
				"count": 5,
			},
			{
				"template": "structures/{civ}_house",
				"priority": 30,
				"count": 20,
			},
		];
			}
	},
	
	
	buildMoreBuildings: function(gameState, planGroups)
	{
		// Limit ourselves to constructing two buildings at a time
		if (gameState.findFoundations().length > 1)
			return;

		for each (var building in this.targetBuildings)
		{
			var numBuildings = gameState.countEntitiesAndQueuedWithType(gameState.applyCiv(building.template));

			// If we have too few, build another
			if (numBuildings < building.count)
			{
				planGroups.economyConstruction.addPlan(building.priority,
					new BuildingConstructionPlan(gameState, building.template, 1)
				);
			}
		}
	},

	trainMoreWorkers: function(gameState, planGroups)
	{
		// Count the workers in the world and in progress
		var numWorkers = gameState.countEntitiesAndQueuedWithRole("worker");

		// If we have too few, train another
//		print("Want "+this.targetNumWorkers+" workers; got "+numWorkers+"\n");
		if (numWorkers < this.baseNumWorkers)
		{
			var menorwomen = Math.random()*2;
			if (gameState.displayCiv() == "hele" || gameState.displayCiv() == "celt"){
			if (menorwomen < 1.5){
			planGroups.economyPersonnel.addPlan(120,
				new UnitTrainingPlan(gameState,
					"units/{civ}_support_female_citizen", 2, { "role": "worker" })
			);
			}
			else if (menorwomen > 1.82) {
			planGroups.economyPersonnel.addPlan(120,
				new UnitTrainingPlan(gameState,
					"units/{civ}_infantry_spearman_b", 2, { "role": "worker" })
			);
			}
			else {
			planGroups.economyPersonnel.addPlan(120,
				new UnitTrainingPlan(gameState,
					"units/{civ}_infantry_javelinist_b", 2, { "role": "worker" })
			);
			}
			}
			else {
			if (menorwomen < 1.5){
			planGroups.economyPersonnel.addPlan(120,
				new UnitTrainingPlan(gameState,
					"units/{civ}_support_female_citizen", 2, { "role": "worker" })
			);
			}
			else {
			planGroups.economyPersonnel.addPlan(120,
				new UnitTrainingPlan(gameState,
					"units/{civ}_infantry_swordsman_b", 2, { "role": "worker" })
			);
			}
			}
		}
		else if (numWorkers < this.targetNumWorkers)
		{
			var menorwomen = Math.random()*2;
			if (gameState.displayCiv() == "hele" || gameState.displayCiv() == "celt"){
			if (menorwomen < 1.5){
			planGroups.economyPersonnel.addPlan(90,
				new UnitTrainingPlan(gameState,
					"units/{civ}_support_female_citizen", 2, { "role": "worker" })
			);
			}
			else if (menorwomen > 1.82) {
			planGroups.economyPersonnel.addPlan(90,
				new UnitTrainingPlan(gameState,
					"units/{civ}_infantry_spearman_b", 2, { "role": "worker" })
			);
			}
			else {
			planGroups.economyPersonnel.addPlan(90,
				new UnitTrainingPlan(gameState,
					"units/{civ}_infantry_javelinist_b", 2, { "role": "worker" })
			);
			}
			}
			else {
			if (menorwomen < 1.5){
			planGroups.economyPersonnel.addPlan(90,
				new UnitTrainingPlan(gameState,
					"units/{civ}_support_female_citizen", 2, { "role": "worker" })
			);
			}
			else {
			planGroups.economyPersonnel.addPlan(90,
				new UnitTrainingPlan(gameState,
					"units/{civ}_infantry_swordsman_b", 2, { "role": "worker" })
			);
			}
			}
		}
	},

	pickMostNeededResources: function(gameState)
	{
		var self = this;

		// Find what resource type we're most in need of
		var numGatherers = {};
		for (var type in this.gatherWeights)
			numGatherers[type] = 0;

		gameState.getOwnEntitiesWithRole("worker").forEach(function(ent) {
			if (ent.getMetadata("subrole") === "gatherer")
				numGatherers[ent.getMetadata("gather-type")] += 1;
		});

		var types = Object.keys(this.gatherWeights);
		types.sort(function(a, b) {
			// Prefer fewer gatherers (divided by weight)
			var va = numGatherers[a] / self.gatherWeights[a];
			var vb = numGatherers[b] / self.gatherWeights[b];
			return va - vb;
		});

		return types;
	},

	reassignRolelessUnits: function(gameState)
	{
		var roleless = gameState.getOwnEntitiesWithRole(undefined);

		roleless.forEach(function(ent) {
			if (ent.hasClass("Worker"))
				ent.setMetadata("role", "worker");
			else
				ent.setMetadata("role", "randomcannonfodder");
		});
	},

	reassignIdleWorkers: function(gameState, planGroups)
	{
		var self = this;

		// Search for idle workers, and tell them to gather resources
		// Maybe just pick a random nearby resource type at first;
		// later we could add some timer that redistributes workers based on
		// resource demand.

		var idleWorkers = gameState.getOwnEntitiesWithRole("worker").filter(function(ent) {
			return ent.isIdle();
		});

		if (idleWorkers.length)
		{
			var resourceSupplies = gameState.findResourceSupplies();

			idleWorkers.forEach(function(ent) {

				var types = self.pickMostNeededResources(gameState);
				for each (var type in types)
				{
					// Make sure there's actually some of that type
					if (!resourceSupplies[type])
						continue;

					// Pick the closest one.
					// TODO: we should care about distance to dropsites, not (just) to the worker,
					// and gather rates of workers

					var workerPosition = ent.position();
					var supplies = [];
					resourceSupplies[type].forEach(function(supply) {
						// Skip targets that are too hard to hunt
						if (supply.entity.isUnhuntable())
							return;
		
		var distcheck = 1000000;
		gameState.getOwnEntities().forEach(function(centre) {
			if (centre.hasClass("CivCentre"))
			{
					var centrePosition = centre.position();
							var currentdistcheck = VectorDistance(supply.position, centrePosition);
							if (currentdistcheck < distcheck){
							distcheck = currentdistcheck;
							}
						// Skip targets that are far too far away (e.g. in the enemy base)
			}
		});
						if (distcheck > 500)
						return;
							
						var dist = VectorDistance(supply.position, workerPosition);

						// Skip targets that are far too far away (e.g. in the enemy base)
						if (dist > 500)
							return;							
							
						supplies.push({ dist: dist, entity: supply.entity });
					});

					supplies.sort(function (a, b) {
						// Prefer smaller distances
						if (a.dist != b.dist)
							return a.dist - b.dist;

						return false;
					});
									
					// Start gathering
					if (supplies.length)
					{
					// THIS SHOULD BE A GLOBAL VARIABLE
					var currentposformill = supplies[0].entity.position();
					var distcheckold = 10000;
					// CHECK DISTANCE
					gameState.getOwnEntities().forEach(function(centre) {
						if (centre.hasClass("CivCentre") || centre.hasClass("Economic"))
						{
								var centrePosition = centre.position();
								var distcheck = VectorDistance(currentposformill, centrePosition);
									if (distcheck < distcheckold){
									distcheckold = distcheck;
									}
						}
					});
					var foundationsyes = false;
					if (gameState.findFoundations().length > 2){
					foundationsyes = false;
					}
					else{
					foundationsyes = true;
					}
					
					if (distcheckold > 60 && foundationsyes == true){
					//JuBotAI.prototype.chat("Building Mill");
						planGroups.economyConstruction.addPlan(80,
						new BuildingConstructionPlanEcon(gameState, "structures/{civ}_mill", 1, currentposformill)
						);
						//JuBotAI.prototype.chat("Gathering");
						ent.gather(supplies[0].entity);
						ent.setMetadata("subrole", "gatherer");
						ent.setMetadata("gather-type", type);
						return;
					}
					else {
					//JuBotAI.prototype.chat("Gathering");
					ent.gather(supplies[0].entity);
					ent.setMetadata("subrole", "gatherer");
					ent.setMetadata("gather-type", type);
					return;
					}
					}
				}

				// Couldn't find any types to gather
				ent.setMetadata("subrole", "idle");
			});
		}
	},

	assignToFoundations: function(gameState, planGroups)
	{
		// If we have some foundations, and we don't have enough builder-workers,
		// try reassigning some other workers who are nearby

		var foundations = gameState.findFoundations();

		// Check if nothing to build
		if (!foundations.length)
			return;

		var workers = gameState.getOwnEntitiesWithRole("worker");

		var builderWorkers = workers.filter(function(ent) {
			return (ent.getMetadata("subrole") === "builder");
		});

		// Check if enough builders
		var extraNeeded = this.targetNumBuilders - builderWorkers.length;
		if (extraNeeded <= 0)
			return;

		// Pick non-builders who are closest to the first foundation,
		// and tell them to start building it

		var target = foundations.toEntityArray()[0];

		var nonBuilderWorkers = workers.filter(function(ent) {
			return (ent.getMetadata("subrole") !== "builder");
		});

		var nearestNonBuilders = nonBuilderWorkers.filterNearest(target.position(), extraNeeded);

		// Order each builder individually, not as a formation
		nearestNonBuilders.forEach(function(ent) {
			ent.repair(target);
			ent.setMetadata("subrole", "builder");
		});
	},
// This function recalls builders to the CC every 2 minutes; theoretically, this prevents the issue where they build a farm and people try to cross it and there's a traffic jam which wrecks the AI economy.
	buildRegroup: function(gameState, planGroups)
	{
			if (gameState.getTimeElapsed() > this.changetimeRegBui){
			var buildregroupers = gameState.getOwnEntitiesWithRole("worker");
			buildregroupers.forEach(function(shirk) {
			if (shirk.getMetadata("subrole") == "builder"){
			var targets = gameState.entities.filter(function(ent) {
				return (!ent.isEnemy() && ent.hasClass("CivCentre"));
			});
			if (targets.length){
				var target = targets.toEntityArray()[0];
				var targetPos = target.position();
				shirk.move(targetPos[0], targetPos[1]);
			}
			}
			});
			// Wait 4 mins to do this again.
			this.changetimeRegBui = this.changetimeRegBui + (120*1000);
			}
	},

	update: function(gameState, planGroups)
	{
		Engine.ProfileStart("economy update");

		this.buildRegroup(gameState, planGroups)
		
		this.checkBuildingList(gameState);
		
		this.reassignRolelessUnits(gameState);

		this.buildMoreBuildings(gameState, planGroups);

		this.trainMoreWorkers(gameState, planGroups);

		this.reassignIdleWorkers(gameState, planGroups);

		this.assignToFoundations(gameState, planGroups);

		Engine.ProfileStop();
	},

});
