jQuery(function ($) {
	function Unit(world, x, y, type) {
		return {
			type: type,
			x: world.norm(x),
			y: world.norm(y),
			el: $("<div class=\"unit\">" + type.charAt(0).toUpperCase() + "</div>").addClass(type),
			move: function (dx, dy) {
				this.x = world.norm(this.x + dx);
				this.y = world.norm(this.y + dy);
				console.log("Unit now at (" + this.x + ", " + this.y + ")");
			},
			flash: function () {
				$(this.el).toggleClass("hidden");
			}
		};
	}
	
	function World(table, size) {
		/* internal vars */
		var grid = [];
		var units = [];
		var activeUnit;
		
		/* internal functions */
		function toGrid(x) {
			return Math.floor((x + size) % size);
		}
		function cell(x, y) {
			return grid[toGrid(y)][toGrid(x)];
		}
		function activeUnit() {
			return units[0];
		}
		
		/* result: object with public functions */
		return {
			init: function () {
				for (var y = 0; y < size; y++) {
					var row = [];
					for (var x = 0; x < size; x++) {
						row.push({
							type: "water",
							units: []
						});
					}
					grid.push(row);
				}
				/* Continents */
				var landTiles = 0, maxLandTiles = size * size / 3;
				while (landTiles < maxLandTiles) {
					var cx = Math.random() * size;
					var cy = Math.random() * size * 2 / 3 + size / 6;
					var cs = Math.random() * size / 8 + 1;
					for (var r = 0; r < cs; r += 1) {
						for (var theta = 0; theta < 2 * Math.PI; theta += Math.PI / 32) {
							var x = cx + r * Math.cos(theta);
							var y = cy + r * Math.sin(theta);
							if (cell(x, y).type == "water") {
								cell(x, y).type = Math.random() < 0.5 ? "plains" : "grassland";
								landTiles++;
							}
						}
					}
				}
				for (var x = 0; x < size; x++) {
					cell(x, 0).type = "ice";
					cell(x, -1).type = "ice";
					if (Math.random() < 0.25) cell(x, 1).type = "ice";
					if (Math.random() < 0.25) cell(x, -2).type = "ice";
				}
				for (var u = 0; u < 4; u++) {
					var x = 0, y = 0;
					while (cell(x, y).type == "water" || cell(x, y).type == "ice") {
						x = Math.random() * size;
						y = Math.random() * size;
					}
					units.push(new Unit(this, x, y, "settler"));
				}
			},
			draw: function () {
				$(table).children().remove();
				var $headings = $("<tr><th></th></tr>");
				for (var x = 0; x < grid[0].length; x++) {
					$headings.append($("<th>" + x + "</th>"));
				}
				$(table).append($headings);
				for (var y = 0; y < grid.length; y++) {
					var $tr = $("<tr></tr>");
					$tr.append($("<th>" + y + "</th>"));
					for (var x = 0; x < grid[y].length; x++) {
						var $td = $("<td><div></div></td>");
						$td.addClass(cell(x, y).type);
						$tr.append($td);
					}
					$(table).append($tr);
				}
			},
			unit: function() {
				return activeUnit();
			},
			norm: function(x) {
				return toGrid(x);
			},
			update: function () {
				for (var u=0; u<units.length; u++) {
					var unit = units[u];
					var $el = $(table).find("tr:eq(" + (unit.y + 1) + ")")
						.find("td:eq(" + unit.x + ") > div");
					$el.append(unit.el);
				}
				activeUnit().flash();
			},
			advance: function () {
				$(activeUnit().el).removeClass("hidden");
				units.push(units.shift());
			}
		};
	}
	
	var world = new World($("#world"), 20);
	world.init();
	var x = 10, y = 10;
	world.draw();
	setInterval(world.update, 500);
	function toMove(dx, dy) {
		return function () {
			world.unit().move(dx, dy);
			world.advance();
			return false;
		};
	}
	$("#move-up-left").click(toMove(-1, -1));
	$("#move-up").click(toMove(0, -1));
	$("#move-up-right").click(toMove(1, -1));
	$("#move-left").click(toMove(-1, 0));
	$("#move-right").click(toMove(1, 0));
	$("#move-down-left").click(toMove(-1, 1));
	$("#move-down").click(toMove(0, 1));
	$("#move-down-right").click(toMove(1, 1));
	$("#sleep").click(function () {
		world.advance();
	});
});