Client = {obj:{},scale:50,viewport:[-10,-10,800,800],clickMode:1,player:null,editing:null,selectedFleet:null,dragging:false,omni:false}

Client.ClickModes = {Browse:1,MoveTo:2,TransportTo:3,RelocateTo:4}
Client.Colors = ["blue", "lime", "red", "purple", "orange", "brown", "Teal", "aqua", "Fuchsia", "yellow"];
Client.FleetSymbols = ["&raquo;", "&curren;", "&sect;", "&ETH;", "&forall;", "&divide;", "&plusmn;", "$", "&Oslash", "<---|"];	//
Client.FleetImages = ["webclient/images/stencil_huge_0.gif","webclient/images/stencil_huge_1.gif","webclient/images/stencil_huge_2.gif","webclient/images/stencil_huge_3.gif","webclient/images/stencil_huge_4.gif","webclient/images/stencil_huge_5.gif","webclient/images/stencil_huge_6.gif"];
Client.PlanetImages = ["webclient/images/gaia_100.png","webclient/images/moon_100.png","webclient/images/saturn_200.png","webclient/images/venus_100.png"]
// planet images courtesy of http://www.kenmusgrave.com/

Client.SelectPlanet = function(planetIndex)
{
	var planet = Universe.Planets[planetIndex];
	
	switch(this.clickMode)
	{
		case Client.ClickModes.Browse:
			Client.ShowPlanet(planet);
			break;

		case Client.ClickModes.MoveTo:
			var selectedFleet = (Client.selectedFleet ? Client.selectedFleet : Client.editing.fleet);
			
			if (!planet.IsInRange(Client.player))
			{
				alert("out of range");
			}
			else if (selectedFleet)
			{
				selectedFleet.SendTo(planet, Client.GetFleetArray());
				Client.Render();
				Client.Cancel();
			}
			
			break;
		case Client.ClickModes.TransportTo:
			if (!planet.IsInRange(Client.player))
			{
				alert("out of range");
			}
			else if (!planet.owner)
			{
				alert("can't send transports until this planet is colonized");
			}
			else
			{
				var transportCount = 20;  // TODO
				
				if (transportCount > Client.editing.population / 2)
				{
					alert("can't transport more than half the population at once!");
				}
				else
				{
					var fleet = new Fleet(Client.player, Client.editing);
					fleet.transports = transportCount;
					fleet.SetCourse(planet);
					fleet.owner.Fleets.push(fleet);
					
					Client.editing.population -= transportCount;
				}
				
				Client.Render();
				Client.Cancel();
			}
			break;
	}
	
}

Client.HidePlanet = function()
{
	Client.obj.planetView.style.display = "none";
	Client.obj.planetEdit.style.display = "none";
	Client.obj.transportRelocate.style.display = "none";
	Client.obj.colonizePanel.style.display = "none";
}

Client.ShowPlanet = function(planet)
{
	Client.editing = planet;
	

	if (planet.owner == this.player)
	{
		Client.ShowPlanetEdit(planet);
	}
	else if (planet.owner != null && Client.omni)
	{
		Client.ShowPlanetDetail(planet);

		// HACK: client edits everybody for now!
		//Client.ShowPlanetEdit(planet);
	}
	else if (this.player.HasExplored(planet))
	{
		Client.ShowPlanetDetail(planet);
	}
	else
	{
		Client.ShowPlanetUnexplored(planet);
	}

	
	Client.Render();
}

Client.ShowPlanetEdit = function(planet)
{
	Client.editing = planet;

	Client.obj.planetView.style.display = "";
	Client.obj.planetEdit.style.display = "";
	Client.obj.transportRelocate.style.display = "";
	Client.obj.fleetView.style.display = "none";
	Client.obj.colonizePanel.style.display = "none";
	
	Client.obj.planetName.innerHTML = planet.name;
	Client.obj.environment.innerHTML = Planet.Environments[planet.environment];
	Client.obj.population.innerHTML = Math.floor(planet.population) + "<span class='light'>/" + planet.populationMax + "</span>";
	Client.obj.factories.innerHTML = Math.floor(planet.factories) + "<span class='light'>/" + planet.populationMax * planet.owner.factoriesPerWorker + "</span>";
	Client.obj.production.innerHTML = planet.GetProduction() + "<span class='light'>/" + (planet.populationMax * planet.owner.factoriesPerWorker * planet.owner.factoryProduction + planet.populationMax*planet.owner.workerProduction) + "</span>";
	Client.obj.bases.innerHTML = Math.floor(planet.bases);


	var priorities = Client.planetSliders.getValues();
	for (var a=0; a<planet.priority.length; a++)
	{
		Client.planetSliders.sliders[a].setValue(planet.priority[a], false);
	}


	// TODO - load fleet, show
	Client.obj.fleetEdit.style.display = "none";
	var fleet = Fleet.GetByPlanetAndOwner(planet, this.player);
	if (fleet)
	{
		//Client.ShowFleetEdit(fleet);
	}
	
}

Client.ShowPlanetDetail = function(planet)
{
	Client.obj.planetEdit.style.display = "none";
	Client.obj.planetView.style.display = "";
	Client.obj.fleetEdit.style.display = "none";
	Client.obj.fleetView.style.display = "none";
	Client.obj.transportRelocate.style.display = "none";
	Client.obj.colonizePanel.style.display = "none";

	Client.obj.planetName.innerHTML = planet.name;
	Client.obj.environment.innerHTML = Planet.Environments[planet.environment];
	Client.obj.population.innerHTML = Math.floor(planet.population);
	Client.obj.factories.innerHTML = Math.floor(planet.factories);
	Client.obj.production.innerHTML = planet.GetProduction();
	Client.obj.bases.innerHTML = Math.floor(planet.bases);

	if (!planet.owner)
	{
		Client.obj.population.innerHTML = planet.populationMax + " max"
		Client.obj.factories.innerHTML = "---";
		Client.obj.production.innerHTML = "---";
		Client.obj.bases.innerHTML = "---";

		Client.ShowColonizePanel(planet);
	}
}

Client.ShowPlanetUnexplored = function(planet)
{
	Client.obj.planetEdit.style.display = "none";
	Client.obj.planetView.style.display = "";
	Client.obj.fleetEdit.style.display = "none";
	Client.obj.fleetView.style.display = "none";
	Client.obj.transportRelocate.style.display = "none";
	Client.obj.colonizePanel.style.display = "none";

	Client.obj.planetName.innerHTML = planet.name;
	Client.obj.environment.innerHTML = "Unexplored"
	Client.obj.population.innerHTML = "---";
	Client.obj.factories.innerHTML = "---";
	Client.obj.production.innerHTML = "---";
	Client.obj.bases.innerHTML = "---";
}

Client.ShowPlanetOutOfRange = function(planet)
{

}

Client.ShowColonizePanel = function(planet, fleet)
{
	Client.obj.colonizePanel.style.display = "none";
	if (planet.owner)
	{
		return;
	}
	
	if (!fleet)
	{
		fleet = Fleet.GetByPlanetAndOwner(planet, Client.player);
	}
	
	if (fleet)
	{
		Client.obj.colonizePanel.style.display = "";
		if (fleet.GetTotalFirepower(false) >= Ship.ColonyFirepower)
		{
			Client.obj.colonize.disabled = "";
		}
		else
		{
			Client.obj.colonize.disabled = "disabled";
		}
		
	}
}

Client.SelectFleet = function(id)
{
	var fleet;
	if (!isNaN(parseInt(id)))
	{
		alert(id);
		// load fleet by id
		fleet = Fleet.GetByID(parseInt(id));
		alert(fleet);
	}
	else
	{
		// sniff fleet from event reference
		var target = id.target ? id.currentTarget : id.srcElement;
		fleet = target.jref;
	}

	if (!fleet)
	{
		return;
	}
	
	Client.Cancel();
	if (fleet.inTransit)
	{
		Client.obj.planetName.innerHTML = "to " + fleet.destination.name
	
		// TODO - cool lines & stuff
		//Client.ShowPlanet(fleet.destination);
		
	}
	else
	{
		Client.obj.planetName.innerHTML = "at " + fleet.planet.name
		//Client.ShowPlanet(fleet.planet);
	}

	Client.HidePlanet();
	
	
	// UNCOMMENTED THIS DURING COLONIZATION CHANGES.  NOT SURE WHY IT WAS COMMENTED IN THE FIRST PLACE!
	Client.editing = planet;
	
	
	Client.selectedFleet = fleet;

	if (!fleet.inTransit && fleet.owner == Client.player)
	{
		//Client.planetEdit.style.display = fleet.planet.owner == fleet.owner ? "" : "none";
		
		Client.ShowFleetEdit(fleet);
		
	}
	else
	{
		//Client.ShowPlanetDetail(fleet.planet);
		// enemy fleet
		Client.ShowFleetView(fleet);
	}
	
	Client.Render();

}

Client.ShowFleetEdit = function(fleet)
{
	Client.obj.fleetView.style.display = "none";
	Client.obj.fleetEdit.style.display = !fleet || fleet.IsEmpty() ? "none" : "";
	Client.obj.colonizePanel.style.display = "none";
	
	
	if (fleet)
	{

		Client.selectedFleet = fleet;
		Client.mark1slider.setValue(100, true);
		Client.mark2slider.setValue(100, true);
		Client.mark3slider.setValue(100, true);
		Client.mark4slider.setValue(100, true);
		Client.RenderFleetEdit();
		
		if (!fleet.planet.owner)
		{
			Client.ShowColonizePanel(fleet.planet, fleet);
			//Client.obj.colonizePanel.style.display = "";
		}
	}
}

Client.ShowFleetView = function(fleet)
{
	var transportCount = Math.floor(fleet.transports);
	var firePower = fleet.GetTotalFirepower(true);
	
	Client.obj.planetEdit.style.display = "none";
	Client.obj.fleetEdit.style.display = "none";
	Client.obj.fleetView.style.display = "";
	Client.obj.colonizePanel.style.display = "none";

	Client.obj.raceName.innerHTML = fleet.owner.race;
	Client.obj.enemyFleet.innerHTML = (firePower == 0) ? "---" : fleet.ToString();
	Client.obj.fleetColonists.innerHTML = "---";
	Client.obj.fleetTransports.innerHTML = (transportCount == 0) ? "---" : transportCount;
	
	var fleetDescription = "";
	if (transportCount > 0)
	{
		if (fleet.destination && fleet.destination.owner)
		{
			if (fleet.destination.owner == fleet.owner)
			{
				fleetDescription = "Transport";
			}
			else
			{
				fleetDescription = "Invasion";
			}
		}
		else
		{
			fleetDescription = "Settler";
		}
	}
	else if (firePower < 10)
	{
		fleetDescription = "Scout";
	}
	else if (firePower < 100)
	{
		fleetDescription = "Battle";
	}
	else if (firePower < 1000)
	{
		fleetDescription = "War";
	}
	else if (firePower < 10000)
	{
		fleetDescription = "Extermination";
	}
	
	Client.obj.fleetDescription.innerHTML = fleetDescription;
	
	
	//"fleetDescription", "fleetColonists", "fleetTransports"
	
}

Client.RenderFleetEdit = function()
{
	if (!Client.selectedFleet)
	{
		return;
	}
	
	Client.RenderPercentageSlider(Client.mark1slider, Client.obj.mark1count, Client.selectedFleet.ships[0]);
	Client.RenderPercentageSlider(Client.mark2slider, Client.obj.mark2count, Client.selectedFleet.ships[1]);
	Client.RenderPercentageSlider(Client.mark3slider, Client.obj.mark3count, Client.selectedFleet.ships[2]);
	Client.RenderPercentageSlider(Client.mark4slider, Client.obj.mark4count, Client.selectedFleet.ships[3]);
}

Client.RenderPercentageSlider = function(slider, box, max)
{
	max = Math.floor(max);
	var current = Math.round(slider.value * max / 100);
	box.innerHTML = current + "/" + max;

	if (max == 0 || current == 0)
	{
		box.className = "disabled";
		if (max == 0)
		{
			slider.lock();
		}
	}
	else
	{
		box.className = "";
		slider.unlock();

		var percentage = Math.round(current/max * 100);
		slider.setValue(percentage, true);
	}
	
}


Client.GetFleetArray = function()
{
	if (!Client.selectedFleet)
	{
		return [0,0,0,0];
	}
	
	return [
		Client.mark1slider.getWeightedValue(Client.selectedFleet.ships[0])
		, Client.mark2slider.getWeightedValue(Client.selectedFleet.ships[1])
		, Client.mark3slider.getWeightedValue(Client.selectedFleet.ships[2])
		, Client.mark4slider.getWeightedValue(Client.selectedFleet.ships[3])
	]
	
}

Client.TogglePriorityLock =  function(link, index)
{
	Client.planetSliders.toggleLock(index);
	link.setAttribute("locked", Client.planetSliders.getLocked(index) ? "true" : "");
}

Client.PriorityChange = function()
{
	if (!Client.editing)
	{
		return;
	}
	setTimeout(function(){
		planet = Client.editing;
		var priorities = Client.planetSliders.getValues();
		for (var a=0; a<planet.priority.length; a++)
		{
			planet.priority[a] = priorities[a];
		}
		Client.PopulatePerTurnBoxes();
	},0);
	
}

Client.PopulatePerTurnBoxes = function()
{
	var planet = this.editing;
	var production = planet.GetProduction() - planet.GetMaintenance();
	
	Client.PopulateBaseAndShipPerTurn(planet.CalculateShipsPerTurn(production), Client.obj.shipsPerTurn);
	Client.PopulateBaseAndShipPerTurn(planet.CalculateBasesPerTurn(production), Client.obj.basesPerTurn);
	
	Client.obj.researchPerTurn.innerHTML = Math.floor(planet.CalculateResearchPerTurn(production)) + " RP";
}

Client.PopulateBaseAndShipPerTurn = function(count, box)
{
	if (count <= 0)
	{
		box.innerHTML = "none";
	}
	else if (count < 1)
	{
		box.innerHTML = Math.floor(1/count) + " y";
	}
	else
	{
		box.innerHTML = Math.floor(count) + "/y";
	}
}







Client.ShowReports = function()
{
	Client.obj.reports.innerHTML = "";
	for (var a=0; a<this.player.Reports.length; a++)
	{
		var report = this.player.Reports[a];
		var href = "javascript:void(null);";
		
		switch(report.reportType)
		{
			case Report.ReportTypes.Combat:
				href = "javascript:Client.SelectFleet(" + report.fleet.id + ");";
				break;
		}
		
		var reportHtml = Util.Format("<a href='{0}'>{1}</a><p/>", href, report.title);
		reportHtml += report.body.replace(/\r\n/g, "<br/>");
		reportHtml += "<p/>";
		
		Client.obj.reports.innerHTML += reportHtml;
	}
}

Client.GetFleetScreenWidth = function()
{
	return Math.floor(0 + 20 * (Client.scale-10) / 100);
}
Client.GetFleetScreenHeight = function()
{
	return Math.floor(Client.GetFleetScreenWidth() * 0.888);
}
Client.GetPlanetScreenSize = function()
{
	return Util.Bound( Math.floor( (Client.scale/4)*(Client.scale/4) / 15)-1, 1, 200);
}

Client.Render = function()
{
	Client.omni = Client.obj.omniview.checked;
	if (Client.player.Planets.length == 0)
	{
		Client.omni = true;
	}

	Client.context.clearRect(0, 0, Client.context.width, Client.context.height);
	

	var fontSize = Math.floor(8 + 10 * Client.scale / 100);
	var fleetSize = Client.GetFleetScreenWidth();
	var fleetSizeY = Client.GetFleetScreenHeight();
	var planetSize = Client.GetPlanetScreenSize();
	for (var a=0; a<Universe.Planets.length; a++)
	{
		var planet = Universe.Planets[a];
		if (!planet.link)
		{
			planet.link = document.createElement("A");
			planet.link.style.position = "absolute";
			planet.link.href = "javascript:Client.SelectPlanet(" + a + ");";
			planet.link.className = "unexplored";
			
			planet.text = document.createElement("SPAN");
			planet.text.innerHTML = "<br/>" + planet.name;
			
			planet.image = document.createElement("IMG");
			// TODO - base this on planet type
			planet.image.src = Client.PlanetImages[Util.RandInt(Client.PlanetImages.length)];
			
			planet.link.appendChild(planet.image);
			planet.link.appendChild(planet.text);
			Client.obj.starmap.appendChild(planet.link);
		}
		
		
		planet.link.style.left = this.GetScreenX(planet.x) + "px";
		planet.link.style.top = this.GetScreenY(planet.x, planet.y) + "px";

		if (document.all)
		{
			// IE doesn't like auto-sizing images		
			planet.image.style.width = planetSize + "px";
		}
		planet.image.style.height = planetSize + "px";
		planet.link.style.fontSize = fontSize + "px";


		if (planet.owner && (Client.player.HasExplored(planet) || Client.omni || planet.IsInRange(Client.player)))
		{
			planet.link.className = "occupied";
			planet.link.style.color = Client.Colors[planet.owner.index];
		}
		else
		{
			if (Client.player.HasExplored(planet))
			{
				//planet.link.innerHTML = planet.name;
				planet.link.className = "explored";
				planet.link.style.color = "#eee";
			}	
			else
			{
				planet.link.className = "unexplored";
				planet.link.style.color = "#555";
			}	
		}
		
		if (planet == Client.editing)
		{
			planet.link.className = "occupied selected";
		
		}
		else if (planet.owner)
		{
			//planet.link.className = "occupied";
		}


	}
	
	for (var a=0; a<Universe.Players.length; a++)
	{
		var player = Universe.Players[a];
		for (var b=0; b<player.Fleets.length; b++)
		{
			var fleet = player.Fleets[b];
			if (!fleet.marker)
			{
				fleet.marker = document.createElement("A");
				fleet.marker.href = "javascript:void(null);";
				fleet.marker.jref = fleet;
				fleet.marker.className = "fleet";
				fleet.marker.style.position = "absolute";
				fleet.marker.style.color = Client.Colors[player.index];
				fleet.marker.style.left = "-200px";
				fleet.marker.style.top = "-200px";
				fleet.image = document.createElement("IMG");
				fleet.image.src = Client.FleetImages[player.index % 7];
				fleet.image.style.backgroundColor = Client.Colors[player.index];
				fleet.image.jref = fleet;
				//fleet.image.style.filter = 'fliph';
				fleet.marker.appendChild(fleet.image);
				Client.obj.starmap.appendChild(fleet.marker);
				
				Util.AddListener(fleet.marker, "click", Client.SelectFleet)
				
				fleet.onDelete = function()
				{
					Client.obj.starmap.removeChild(this.marker);
				}
			}

			fleet.image.src = Client.FleetImages[player.index % 7];
			fleet.marker.style.fontSize = fontSize + "px";
			fleet.image.style.width = fleetSize + "px";
			if (document.all)
			{
				fleet.image.style.height = fleetSizeY + "px";
			}

			fleet.marker.style.display = "";
			if (fleet.IsEmpty())
			{
				// this is rare.  It's a fleet that was in orbit its own planet that has been reduced to 0<n<1.
				// It thinks it is empty, but really isn't, so we need to hide it until it builds back up to at least one ship.
				fleet.marker.style.display = "none";
			}
			else if (!Client.omni && !fleet.IsVisibleTo(Client.player))
			{
				fleet.marker.style.display = "none";
			}
			else if (fleet.inTransit)
			{
				fromPosition = Client.GetPlanetScreenCenter(fleet.planet);
				toPosition = Client.GetPlanetScreenCenter(fleet.destination);
				var dx = fromPosition[0] - toPosition[0];
				var dy = fromPosition[1] - toPosition[1];

				var x = Math.round(fromPosition[0] - fleet.courseProgress *dx / fleet.courseLength - fleetSize/2);
				var y = Math.round(fromPosition[1] - fleet.courseProgress *dy / fleet.courseLength - fleetSizeY/2);
				
				fleet.marker.style.left = x + "px";
				fleet.marker.style.top = y + "px";
				
				fleet.image.src = Client.FleetImages[fleet.owner.index % 7];
				if (dx > 0)
				{
					fleet.image.src = fleet.image.src.replace(".gif", "_left.gif");
				}
				
				if (fleet == Client.selectedFleet || fleet.destination == Client.editing || fleet.planet == Client.editing)
				{
					Client.RenderFleetLines(fleet, x, y);
				}

			}
			else
			{
				var slotOffset = [Math.floor((5 + 0.1 * Client.scale) * player.index )
								, Math.floor(-7 - 0.2 * Client.scale)];
				fleet.marker.style.left = (Client.GetScreenX(fleet.planet.x) + slotOffset[0]) + "px";
				fleet.marker.style.top = (Client.GetScreenY(fleet.planet.x, fleet.planet.y) + slotOffset[1]) + "px";
			}
		}
	}

}

Client.RenderFleetLines = function(fleet, currentScreenX, currentScreenY)
{
	var fleetPosition = [currentScreenX + Client.GetFleetScreenWidth()/2, currentScreenY + Client.GetFleetScreenHeight()/2];
	
	var fromPlanet = Client.GetPlanetScreenCenter(fleet.planet);
	var destinationPlanet = Client.GetPlanetScreenCenter(fleet.destination);

	
	Client.context.strokeStyle = "#333";
	Client.context.lineWidth = 2;
	Client.context.lineCap = "round";

	Client.context.beginPath();
	Client.context.moveTo(fleetPosition[0], fleetPosition[1]);
	Client.context.lineTo(fromPlanet[0], fromPlanet[1]);
	Client.context.stroke();
		
	Client.context.strokeStyle = "#00ffff";
	if (fleet.owner != Client.player && fleet.destination.owner == Client.player)
	{
	Client.context.strokeStyle = "#ff0000";
	}
	
	Client.context.beginPath();
	Client.context.moveTo(fleetPosition[0], fleetPosition[1]);
	Client.context.lineTo(destinationPlanet[0], destinationPlanet[1]);
	Client.context.stroke();
	
}

Client.Empty = function()
{
	for (var a=0; a<Universe.Planets.length; a++)
	{
		var planet = Universe.Planets[a];
		if (planet.link)
		{
			Client.obj.starmap.removeChild(planet.link);
		}
	}

	for (var a=0; a<Universe.Players.length; a++)
	{
		var player = Universe.Players[a];
		for (var b=0; b<player.Fleets.length; b++)
		{
			var fleet = player.Fleets[b];
			if (fleet.marker)
			{
				Client.obj.starmap.removeChild(fleet.marker);
			}
		}
	}

}

Client.GetScreenX = function(starX)
{
	return starX * this.scale - Client.viewport[0];
}

Client.GetScreenY = function(starX, starY)
{
	var yfudge = 0;
	if (starX != null)
	{
		starX = Math.round(starX);
		if (starX/2 == Math.floor(starX/2))
		{
			yfudge = this.scale/2
		}
	}

	return starY * this.scale + yfudge - Client.viewport[1];
}


Client.GetPlanetScreenCenter =  function(planet)
{
	var planetRadius = Client.GetPlanetScreenSize() / 2;
	var x = getLeft(planet.image) + planetRadius;
	var y = getTop(planet.image) + planetRadius;
	return [x,y];
}

Client.StartMove = function()
{
	Client.clickMode = Client.ClickModes.MoveTo;

	Client.obj.starmap.style.cursor="crosshair";
	Client.obj.move.value = "to...";
	Client.obj.move.disabled = "disabled";
	Client.obj.move.blur();
}

Client.Cancel = function()
{
	Client.CancelMove();
	Client.CancelTransport();
	Client.CancelRelocate();
}

Client.CancelMove = function()
{
	Client.clickMode = Client.ClickModes.Browse;

	Client.obj.starmap.style.cursor="";
	Client.obj.move.value = "move";
	Client.obj.move.disabled = "";
	
	if (Client.editing && Client.editing.owner == Client.player)
	{
		Client.ShowPlanetEdit(Client.editing);
	}
}

Client.StartTransport = function()
{
	Client.clickMode = Client.ClickModes.TransportTo;

	Client.obj.starmap.style.cursor="crosshair";
	Client.obj.transport.value = "to...";
	Client.obj.transport.disabled = "disabled";
	Client.obj.transport.blur();
}

Client.CancelTransport = function()
{
	Client.clickMode = Client.ClickModes.Browse;

	Client.obj.starmap.style.cursor="";
	Client.obj.transport.value = "transport";
	Client.obj.transport.disabled = "";
	
	if (Client.editing && Client.editing.owner == Client.player)
	{
		Client.ShowPlanetEdit(Client.editing);
	}
}

Client.StartRelocate = function()
{
	Client.clickMode = Client.ClickModes.RelocateTo;

	Client.obj.starmap.style.cursor="crosshair";
	Client.obj.relocate.value = "to...";
	Client.obj.relocate.disabled = "disabled";
	Client.obj.relocate.blur();
}

Client.CancelRelocate = function()
{
	Client.clickMode = Client.ClickModes.Browse;

	Client.obj.starmap.style.cursor="";
	Client.obj.relocate.value = "relocate";
	Client.obj.relocate.disabled = "";
	
	if (Client.editing && Client.editing.owner == Client.player)
	{
		Client.ShowPlanetEdit(Client.editing);
	}
}

Client.Colonize = function()
{
	if (Client.editing && !Client.editing.owner)
	{
		var fleet = Fleet.GetByPlanetAndOwner(Client.editing, Client.player);
		var planet = Client.editing;
		
		if (fleet && fleet.GetTotalFirepower(false) >= Ship.ColonyFirepower)
		{
			fleet.Colonize(planet);
			Client.ShowPlanet(planet);
		}
	}
	else if (Client.selectedFleet)
	{
		Client.selectedFleet.Colonize(Client.selectedFleet.planet);
		Client.ShowPlanet(Client.selectedFleet.planet);
	}
}

Client.NextTurn = function()
{
	Client.Cancel();
	Universe.NextTurn();
	
	if (this.player.Planets.length == 0)
	{
		// dead.  May as well watch everything.
		this.omni = true;
	}
	
	if (this.editing)
	{
		this.ShowPlanet(this.editing);
		//this.ShowPlanetEdit(this.editing);
	}
	
	Client.ShowReports();
	Client.Render();
	Client.PopulatePerTurnBoxes()
	
	
}


Client.mousedown = function(e)
{
	Client.dragging = true;
	Client.dragOffset = [e.clientX + Client.viewport[0], e.clientY + Client.viewport[1]];
	Client.lastMouse = [e.clientX, e.clientY];
}

Client.mouseup = function(e)
{
	if (Client.dragging)
	{
		//var velocity = [Client.lastMouse[0] - e.clientX, Client.lastMouse[1] - e.clientY];
		//Client.SkidToStop(velocity, 5);
		
		//alert(velocity);
	}
	
	Client.dragging = false;
}

Client.mousemove = function(e)
{
	if (Client.dragging)
	{
		Client.viewport[0] = Client.dragOffset[0] - e.clientX;
		Client.viewport[1] = Client.dragOffset[1] - e.clientY;
		Client.Render();

		Client.lastMouse = [e.clientX, e.clientY];
		return(cancelEvent(e));
	}
}

Client.SkidToStop = function(velocity, maxlength)
{
	var coeff = 0.7;
	velocity = [velocity[0] * coeff, velocity[1] * coeff];
	Client.viewport[0] += Math.floor(velocity[0]);
	Client.viewport[1] += Math.floor(velocity[1]);
	Client.Render();
	
	if (Math.abs(velocity[0]) > 1 && maxlength > 0)
	{
		setTimeout(function(){Client.SkidToStop(velocity, maxlength-1);}, 30);
	}
}

Client.mousewheel = function(e)
{
	var target = e.target ? e.currentTarget : e.srcElement;
	
	var delta = e.wheelDelta ? e.wheelDelta : -e.detail;  // NOTE that FF's e.detail runs in the opposite direction to everybody else!
	delta = Math.abs(delta)/delta;
	
	// our goal is to have starCoords map to screenCoords in the new view by shifting the viewport.
	var screenCoords = [e.clientX, e.clientY];
	var starCoords = [(Client.viewport[0] + e.clientX) / Client.scale
				    , (Client.viewport[1] + e.clientY) / Client.scale];
	
	Client.scale = Util.Bound(Client.scale + delta*10, 20, 200);

	var newScreenCoords = [Client.GetScreenX(starCoords[0]), Client.GetScreenY(null, starCoords[1])]

	Client.viewport[0] += newScreenCoords[0] - screenCoords[0];
	Client.viewport[1] += newScreenCoords[1] - screenCoords[1];
	
	
	Client.Render();
	
	return cancelEvent(e);
}

Client.RenderAITable = function(player)
{
	while (Client.obj.airesults.rows.length > 0) 
	{
		Client.obj.airesults.deleteRow(0);
	}


	
	for (key in Client.playerStats)
	{
		var row = Client.obj.airesults.insertRow(-1);
		row.insertCell(-1).innerHTML = key;
		row.insertCell(-1).innerHTML = Client.playerStats[key][0];
		row.insertCell(-1).innerHTML = Client.playerStats[key][1];
	}
}

Client.ToggleFullyAutomate = function(wait)
{
	Client.autoWait = wait;
	if (!Client.autoInterval)
	{
		Client.autoInterval = setInterval(function(){Client.NextTurn();}, wait);
	}
	else
	{
		clearInterval(Client.autoInterval);
		Client.autoInterval = null;
	}
}

Client.onGameFinished = function(victor)
{
	var autorestart = document.getElementById("autorestart").checked;
	
	if (Client.autoInterval)
	{
		clearInterval(Client.autoInterval);
		Client.autoInterval = null;
		
		if (!Client.playerStats)
		{
			Client.playerStats = [];
		}
		if (!Client.playerStats[victor.race])
		{
			Client.playerStats[victor.race] = [0, victor.type];
		}
		Client.playerStats[victor.race][0]++;
		Client.RenderAITable();
	}
	
	Client.Render();
	if (autorestart || confirm(victor.name + " wins!  Play again?"))
	{
		Client.Empty();
		Client.StartGame();
/*		
		Universe.Initialize(24,16,50, 7);
		//Universe.Initialize(40,30,100, 10);
		//Universe.Initialize(17,12,20, 7);
		Client.player = Universe.Players[0];
		Client.ShowPlanetEdit(Client.player.homeworld);

		Client.Render();
		Client.Cancel();
*/
	}
	
	if (autorestart)
	{
		Client.autoInterval = setInterval(function(){Client.NextTurn();}, Client.autoWait);
	}
}

// given a list of DOM ids, get references to the objects and add them to the Client namespace
Client.Sniff = function()
{
	for (var a=0; a<Client.Sniff.arguments.length; a++)
	{
		var id = Client.Sniff.arguments[a];
		var obj = document.getElementById(id);
		if (!obj)
		{
			alert("bad object reference: " + id);
		}
		else
		{
			Client.obj[id] = obj;
		}
	}
}

Client.StartGame = function()
{
	var width = NewGame.GetUniverseSize();
	var height = Math.round( width * 480 / 640);
	
	//Util.AlertMulti(width, height, NewGame.GetPlanetCount(), NewGame.GetPlayerCount());
	//Universe.Initialize(17,12,20, 7);
	Universe.Initialize(width, height, NewGame.GetPlanetCount(), NewGame.GetPlayerCount(), NewGame.GetPlayerRaceIndex());
	Client.player = Universe.Players[0];
	Client.ShowPlanetEdit(Client.player.homeworld);
	Client.Render();
	Client.Cancel();

}

Client.Save = function()
{
	document.getElementById("txt").value = Universe.toSaveFormat();
	
	// JSON.stringify(Universe, null, 1);
	//alert(Universe.Planets[0].waste);
}

Client.Load = function()
{
	var txt = document.getElementById("txt").value;

	Client.Empty();
	Universe.fromSaveFormat(txt);
	
	for (var a=0; a<Universe.Players.length; a++)
	{
		if (Universe.Players[a].type == Player.prototype.type)
		{
			this.player = Universe.Players[a];
			//alert(this.player.name);
		}
	}
	
	Client.Render();
	Client.Cancel();
	
}

Client.Init = function()
{
	Client.Sniff("starmap", "cv1", "planetEdit", "planetView", "fleetEdit", "fleetView", "reports", "transportRelocate");
	Client.Sniff("planetName", "environment", "population", "factories", "production", "bases", "move", "transport", "relocate");
	Client.Sniff("raceName", "enemyFleet", "fleetDescription", "fleetColonists", "fleetTransports", "colonizePanel", "colonize");
	Client.Sniff("shipPriority", "basePriority", "industryPriority", "ecologyPriority", "researchPriority", "shipsPerTurn", "basesPerTurn", "industryPerTurn", "ecologyPerTurn", "researchPerTurn");
	Client.Sniff("airesults", "omniview");
	Client.Sniff("mark1slider", "mark1count", "mark2slider", "mark2count", "mark3slider", "mark3count", "mark4slider", "mark4count");
	
	
	
	Client.planetSliders = new MultiSlider();
	Client.planetSliders.add(new Slider(Client.obj.shipPriority, 20));
	Client.planetSliders.add(new Slider(Client.obj.basePriority, 20));
	Client.planetSliders.add(new Slider(Client.obj.industryPriority, 20));
	Client.planetSliders.add(new Slider(Client.obj.ecologyPriority, 20));
	Client.planetSliders.add(new Slider(Client.obj.researchPriority, 20));
	Client.planetSliders.onChange = Client.PriorityChange;
	
	Client.mark1slider = new Slider(Client.obj.mark1slider, 100);
	Client.mark2slider = new Slider(Client.obj.mark2slider, 100);
	Client.mark3slider = new Slider(Client.obj.mark3slider, 100);
	Client.mark4slider = new Slider(Client.obj.mark4slider, 100);
	Client.mark1slider.onChange = Client.RenderFleetEdit;
	Client.mark2slider.onChange = Client.RenderFleetEdit;
	Client.mark3slider.onChange = Client.RenderFleetEdit;
	Client.mark4slider.onChange = Client.RenderFleetEdit;
	
	
	
	Util.AddListener(Client.obj.starmap, "mousemove", Client.mousemove);
	Util.AddListener(Client.obj.starmap, "mousedown", Client.mousedown);
	Util.AddListener(Client.obj.starmap, "mouseup", Client.mouseup);
	Util.AddListener(Client.obj.starmap, "mouseout", Client.mouseup);
	Util.AddListener(Client.obj.starmap, "mousewheel", Client.mousewheel);
	Util.AddListener(Client.obj.starmap, "DOMMouseScroll", Client.mousewheel);


	Universe.onGameFinished = Client.onGameFinished;


	
	Client.context = Client.obj.cv1.getContext('2d');
	Client.context.width = 1800;
	Client.context.height = 1200;


	
	// autoplay:
	//setInterval(function(){Client.NextTurn();}, 100);
}





//window.onload = Client.Init;
window.onload = NewGame.Init;






