function AttackMoveToCC(gameState, militaryManager){
	this.minAttackSize = 20;
	this.maxAttackSize = 60;
	this.idList=[];
	
	this.previousTime = 0;
	this.state = "unexecuted";
	
	this.healthRecord = [];
};

// Returns true if the attack can be executed at the current time 
AttackMoveToCC.prototype.canExecute = function(gameState, militaryManager){
	var enemyStrength = militaryManager.measureEnemyStrength(gameState);
	var enemyCount = militaryManager.measureEnemyCount(gameState);
	
	// We require our army to be >= this strength
	var targetStrength = enemyStrength * 1.5;
	
	var availableCount = militaryManager.countAvailableUnits();
	var availableStrength = militaryManager.measureAvailableStrength();
	
	debug("Troops needed for attack: " + this.minAttackSize + " Have: " + availableCount);
	debug("Troops strength for attack: " + targetStrength + " Have: " + availableStrength);
	
	return ((availableStrength >= targetStrength && availableCount >= this.minAttackSize)
			|| availableCount >= this.maxAttackSize);
};

// Executes the attack plan, after this is executed the update function will be run every turn
AttackMoveToCC.prototype.execute = function(gameState, militaryManager){
	var availableCount = militaryManager.countAvailableUnits();
	this.idList = militaryManager.getAvailableUnits(availableCount);
	
	var pending = EntityCollectionFromIds(gameState, this.idList);
	
	// Find the critical enemy buildings we could attack
	var targets = militaryManager.getEnemyBuildings(gameState,"ConquestCritical");
	// If there are no critical structures, attack anything else that's critical
	if (targets.length == 0) {
		targets = gameState.entities.filter(function(ent) {
			return (gameState.isEntityEnemy(ent) && ent.hasClass("ConquestCritical") && ent.owner() !== 0 && ent.position());
		});
	}
	// If there's nothing, attack anything else that's less critical
	if (targets.length == 0) {
		targets = militaryManager.getEnemyBuildings(gameState,"Town");
	}
	if (targets.length == 0) {
		targets = militaryManager.getEnemyBuildings(gameState,"Village");
	}

	// If we have a target, move to it
	if (targets.length) {
		// Add an attack role so the economic manager doesn't try and use them
		pending.forEach(function(ent) {
			ent.setMetadata("role", "attack");
		});
		
		var curPos = pending.getCentrePosition();
		
		var target = targets.toEntityArray()[0];
		this.targetPos = target.position();
		
		// Find possible distinct paths to the enemy 
		var pathFinder = new PathFinder(gameState);
		var pathsToEnemy = pathFinder.getPaths(curPos, this.targetPos);
		if (! pathsToEnemy){
			pathsToEnemy = [this.targetPos];
		}
		
		var rand = Math.floor(Math.random() * pathsToEnemy.length);
		this.path = pathsToEnemy[rand];

		pending.move(this.path[0][0], this.path[0][1]);
	} else if (targets.length == 0 ) {
		gameState.ai.gameFinished = true;
	}
	
	this.state = "walking";
};

// Runs every turn after the attack is executed
// This removes idle units from the attack
AttackMoveToCC.prototype.update = function(gameState, militaryManager, events){
	
	// keep the list of units in good order by pruning ids with no corresponding entities (i.e. dead units)
	var removeList = [];
	var totalHealth = 0;
	for (var idKey in this.idList){
		var id = this.idList[idKey];
		var ent = militaryManager.entity(id);
		if (ent === undefined){
			removeList.push(id);
		}else{
			if (ent.hitpoints()){
				totalHealth += ent.hitpoints();
			}
		}
	}
	for (var i in removeList){
		this.idList.splice(this.idList.indexOf(removeList[i]),1);
	}
	
	var units = EntityCollectionFromIds(gameState, this.idList);
	
	if (this.path.length === 0){
		var idleCount = 0;
		var self = this;
		units.forEach(function(ent){
			if (ent.isIdle()){
				if (ent.position() && VectorDistance(ent.position(), self.targetPos) > 30){
					ent.move(self.targetPos[0], self.targetPos[1]);
				}else{
					militaryManager.unassignUnit(ent.id());
				}
			}
		});
		return;
	}
	
	var deltaHealth = 0;
	var deltaTime = 1;
	var time = gameState.getTimeElapsed();
	this.healthRecord.push([totalHealth, time]);
	if (this.healthRecord.length > 1){
		for (var i = this.healthRecord.length - 1; i >= 0; i--){
			deltaHealth = totalHealth - this.healthRecord[i][0];
			deltaTime = time - this.healthRecord[i][1];
			if (this.healthRecord[i][1] < time - 5*1000){
				break;
			}
		}
	}
	
	var numUnits = this.idList.length;
	if (numUnits < 1) return;
	var damageRate = -deltaHealth / deltaTime * 1000;
	var centrePos = units.getCentrePosition();
	if (! centrePos) return;
	
	var idleCount = 0;
	// Looks for idle units away from the formations centre
	for (var idKey in this.idList){
		var id = this.idList[idKey];
		var ent = militaryManager.entity(id);
		if (ent.isIdle()){
			if (ent.position() && VectorDistance(ent.position(), centrePos) > 20){
				var dist = VectorDistance(ent.position(), centrePos);
				var vector = [centrePos[0] - ent.position()[0], centrePos[1] - ent.position()[1]];
				vector[0] *= 10/dist;
				vector[1] *= 10/dist;
				ent.move(centrePos[0] + vector[0], centrePos[1] + vector[1]);
			}else{
				idleCount++;
			}
		}
	}
	
	if ((damageRate / Math.sqrt(numUnits)) > 2){
		if (this.state === "walking"){
			var sumAttackerPos = [0,0];
			var numAttackers = 0;
			
			for (var key in events){
				var e = events[key];
				//{type:"Attacked", msg:{attacker:736, target:1133, type:"Melee"}}
				if (e.type === "Attacked" && e.msg){
					if (this.idList.indexOf(e.msg.target) !== -1){
						var attacker = militaryManager.entity(e.msg.attacker);
						if (attacker && attacker.position()){
							sumAttackerPos[0] += attacker.position()[0];
							sumAttackerPos[1] += attacker.position()[1];
							numAttackers += 1;
						}
					}
				}
			}
			if (numAttackers > 0){
				var avgAttackerPos = [sumAttackerPos[0]/numAttackers, sumAttackerPos[1]/numAttackers];
				// Stop moving
				units.move(centrePos[0], centrePos[1]);
				this.state = "attacking";
			}
		}
	}else{
		if (this.state === "attacking"){
			units.move(this.path[0][0], this.path[0][1]);
			this.state = "walking";
		}
	}
	
	if (this.state === "walking"){
		if (VectorDistance(centrePos, this.path[0]) < 20 || idleCount/numUnits > 0.8){
			this.path.shift();
			if (this.path.length > 0){
				units.move(this.path[0][0], this.path[0][1]);
			}
		}
	}
	
	this.previousTime = time;
	this.previousHealth = totalHealth;
};

