var Universe = {turn:1}

Universe.Clear = function()
{
	Fleet.SEQUENCE = 1;
	this.Planets = [];
	this.Players = [];
}

Universe.AddPlayer = function(playerIndex, playerType)
{
	var playerName = Player.Names[playerIndex][Util.RandInt(Player.Names[playerIndex].length)];
	
	var player = new playerType(playerName, Player.Races[playerIndex], this.Planets[playerIndex]);
	player.index = playerIndex;
	this.Players.push(player);

	var planet = this.Planets[playerIndex];
	planet.owner = player;
	planet.environment = 0;
	planet.populationMax = 100;
	planet.population = 40;
	planet.factories = 30;
	planet.AdjustEcology();

//	alert(playerIndex + ", " + planet.name + ", " + planet.owner.name + ", " + planet.owner.race)	
	
}

Universe.Initialize = function(width, height, planetCount, playerCount, humanPlayerIndex)
{

	this.Clear();
	this.width = width;
	this.height = height;

	// TODO: planets can be in the same system now.
	for (var a=0; a<planetCount; a++)
	{
		var x,y;
		do
		{
			x = Util.RandInt(this.width);
			y = Util.RandInt(this.height);
		}
		while (Universe.HasPlanetAt(x,y))
		
		var planet = new Planet(x, y, Planet.Names[a]);
		this.Planets.push(planet);
	}	

	if (humanPlayerIndex > -1)
	{
		Universe.AddPlayer(humanPlayerIndex, Player);
	}
	
	for (var a=1; a<playerCount; a++)
	{
		var playerIndex = 0;
		do
		{
			playerIndex = Util.RandInt(Player.Races.length);
		}
		while (this.Planets[playerIndex].owner)
		
		var playerType = Player;
		if (playerIndex<5)
		{
			playerType = RandomPlayer;
		}
		else if (playerIndex >= 5)
		{
			playerType = FocusedPlayer;
		}

		Universe.AddPlayer(playerIndex, playerType);
	}
}

Universe.HasPlanetAt = function(x,y)
{
	for (var a=0; a<this.Planets.length; a++)
	{
		if (this.Planets[a].x == x
			&& this.Planets[a].y == y)
		{
			return true;
		}
	}
	return false;
}

Universe.NextTurn = function()
{
	Universe.Plan();
	this.turn++

	Universe.ProcessPlanets();
	Universe.MoveShips();
	Universe.ResolveSpaceConflicts();
	Universe.NoteExplored();
	Universe.Bombard();
	Universe.ResolveGroundConflicts();
	Universe.Colonize();
	
	Universe.ResolveVictory();
}

Universe.Plan = function()
{
	Util.MapMethod(this.Players, "Plan");
}

Universe.ProcessPlanets = function()
{
	Util.MapMethod(this.Planets, "Step");
}

Universe.MoveShips = function()
{
	Util.MapMethod(this.Players, "MoveShips");
}

Universe.ResolveSpaceConflicts = function()
{
	Util.MapMethod(this.Planets, "ResolveSpaceConflicts");
}

Universe.NoteExplored = function()
{
	Util.MapMethod(this.Players, "NoteExplored");
}

Universe.Bombard = function()
{
	//Util.MapMethod(this.Players, "Plan");
}

Universe.ResolveGroundConflicts = function()
{
	Util.MapMethod(this.Planets, "ResolveGroundConflicts");
}

Universe.Colonize = function()
{
	Util.MapMethod(this.Players, "Colonize");
}

Universe.ResolveVictory = function()
{
	var victor = null;
	var liveplayers = 0;
	for (var a=0; a<this.Players.length && liveplayers<2; a++)
	{
		var player = this.Players[a];
		if (player.Planets.length > 0)
		{
			victor = player;
			liveplayers++;
		}
	}
	
	if (liveplayers == 1)
	{
		if (Universe.onGameFinished)
		{
			Universe.onGameFinished(victor);
		}
	}
}

Universe.toJSON = function()
{
	return {turn:this.turn
			, width:this.width
			, height:this.height
			, fleetSequence:Fleet.SEQUENCE
			,Planets:this.Planets
			,Players:this.Players
			};
}

Universe.toSaveFormat = function()
{
	// TODO - move json2.js into the core folder
	return JSON.stringify(Universe, null, 1);
}

Universe.fromSaveFormat = function(txt)
{
	var u = JSON.parse(txt);
	
	this.Clear();
	this.turn = u.turn;
	this.width = u.width;
	this.height = u.height;
	Fleet.SEQUENCE = u.fleetSequence
	this.Players = [];
	this.Planets = [];
	this.PlanetHash = {};	// convenience hash to speed up lookups below.

	for (var a=0; a<u.Planets.length; a++)
	{
		var planet = new Planet();
		Util.CopyProperties(u.Planets[a], planet, "name", "x", "y", "environment", "population", "populationMax", "factories", "bases", "waste", "priority");

		this.Planets.push(planet);	
		this.PlanetHash[planet.name] = planet;	
	}

	for (var a=0; a<u.Players.length; a++)
	{
		var p = u.Players[a];
		var playerClass = Player.Classes[p.type];
		
		var player = new playerClass();
		Util.CopyProperties(p, player, "name", "race", "index", "shipLevel", "research");
		
		var homeworld = Planet.GetByName(p.homeworld);
		player.Construct(p.name, p.race, homeworld)
		
		
		var planetExploder = function(planets, planetName){planets.push(Planet.GetByName(planetName));return planets;};
		player.Planets = Util.Reduce(planetExploder, p.Planets, []);
		player.Explored = Util.Reduce(planetExploder, p.Explored, []);

		for (var b=0; b<player.Planets.length; b++)
		{
			player.Planets[b].owner = player;
		}


		for (var b=0; b<p.Fleets.length; b++)
		{
			var f = p.Fleets[b];
			var planet = Planet.GetByName(f.planet);
			var destination = f.destination ? Planet.GetByName(f.destination) : null
			
			var fleet = new Fleet(player, planet);
			fleet.destination = destination;
			Util.CopyProperties(f, fleet, "id", "ships", "transports", "inTransit", "courseLength", "courseProgress");
			
			player.Fleets.push(fleet);
		}
		
		
		this.Players.push(player);

	}

}


