var tileApp = {
	truchetObj: {
		"rows": 10,
		"cols": 10,
		"tiletype": 2,
		"pixels": 11,
		"tilefiles": [
			"a.gif",
			"b.gif",
			"c.gif",
			"d.gif",
			"e.gif",
			"f.gif"
		],
		"tiles": [
			0,1,2,3,0,1,2,3,0,1,
			3,2,1,0,3,2,1,0,3,2,
			2,3,0,1,2,3,0,1,2,3,
			1,0,3,2,1,0,3,2,1,0,
			0,1,2,3,0,1,2,3,0,1,
			3,2,1,0,3,2,1,0,3,2,
			2,3,0,1,2,3,0,1,2,3,
			1,0,3,2,1,0,3,2,1,0,
			0,1,2,3,0,1,2,3,0,1,
			3,2,1,0,3,2,1,0,3,2
		]
	},
	gridId: "truchetGrid",
	codeAreaId: "codeArea",
	tilesActive: false,
	useDefault: true,
	rows: 25,
	cols: 25,
	pixelSize: 11,
	mainArr: [],
	cursorIndex: 0,
	tileType: 1,
	possibleIdx: ["a.gif", "b.gif", "c.gif", "d.gif"],
	setAllTo: 0,
	getArgs: function () {
		var i, args = {}, query = location.search.substring(1), pairs = query.split("&"), pos, argname, argvalue;
		for (i = 0; i < pairs.length; i++) {
			pos = pairs[i].indexOf("=");
			if (pos == -1) {
				continue;
			}
			argname = pairs[i].substring(0, pos);
			argvalue = pairs[i].substring(pos + 1);
			args[argname] = unescape(argvalue);
		}
		return args;
	},
	initTileArray: function () {
		var rndIdx, rndImg, y, x;
		tileApp.mainArr = [];
		for (y = 1; y <= tileApp.rows; y++) {
			for (x = 1; x <= tileApp.cols; x++) {
				rndIdx = (tileApp.setAllTo > 0) ? (tileApp.setAllTo - 1) : parseInt(Math.random() * tileApp.possibleIdx.length, 10);
				rndImg = tileApp.possibleIdx[rndIdx];
				tileApp.mainArr.push(rndIdx);
			}
		}
	},
	getTruchetHTML: function (tilesOnly) {
		var tmp = "", tmp1, idx = 0, y, x;
		for (y = 1; y <= tileApp.rows; y++) {
			tmp1 = "";
			for (x = 1; x <= tileApp.cols; x++) {
				if (tilesOnly)
					tmp1 += "<td><img src=\"" + tileApp.possibleIdx[tileApp.mainArr[idx]] + "\" alt=\"" + tileApp.mainArr[idx] + "\"/></td>";
				else
					tmp1 += "<td><a href=\"#\" id=\"a" + idx + "\" onclick=\"return tileApp.toggle(" + idx + ");\"><img src=\"" + tileApp.possibleIdx[tileApp.mainArr[idx]] + "\" id=\"i" + idx + "\"/></a></td>";
				idx++;
			}
			tmp += "\n<tr>" + tmp1 + "</tr>";
		}
		return "<table class=\"tilesTable\" border=\"0\" cellspacing=\"0\" cellpadding=\"0\">" + tmp + "\n</table>";
	},
	getTruchetJSON: function (obj) {
		var i, y, x, row,
		tmp = "{\n" +
			"  \"rows\": " + tileApp.rows + ",\n" +
			"  \"cols\": " + tileApp.cols + ",\n" +
			"  \"pixels\": " + tileApp.pixelSize + ",\n" +
			"  \"tiletype\": " + tileApp.tileType + ",\n" +
			"  \"tilefiles\": [\n";
		for (i = 0; i < tileApp.possibleIdx.length; i++) {
			tmp += "    \"" + tileApp.possibleIdx[i] + "\",\n";
		}
		tmp += "  ],\n" +
			"  \"tiles\": [\n";
		for (y = 0; y < tileApp.rows; y++) {
			row = "";
			for (x = 0; x < tileApp.cols; x++) {
				row += tileApp.mainArr[y * tileApp.cols + x] + ",";
			}
			if (y == tileApp.rows - 1) {
				row = row.substring(0, row.length - 1);
			}
			tmp += "    " + row + "\n";
		}
		tmp += "  ]\n" +
			"}";
		return tmp;
	},
	toggle: function (idx) {
		var currentIdx = tileApp.mainArr[idx],
		nextIdx = currentIdx + 1;
		if (nextIdx >= tileApp.possibleIdx.length) {
			nextIdx = 0;
		}
		tileApp.mainArr[idx] = nextIdx;
		document.getElementById("i" + idx).src = tileApp.possibleIdx[nextIdx];
		tileApp.cursorIndex = idx;
		return false;
	},
	initSelect: function (obj, arr, idx) {
		var i, sel;
		obj.options.length = 0;
		for (i = 0; i < arr.length; i++) {
			sel = (i == idx);
			obj.options[obj.options.length] = new Option(arr[i]);
		}
		obj.options.selectedIndex = (idx - 1);
	},
	navigate: function (e) {
		var keynum = 0, offset = 0;
		if (window.event) {
			e = window.event;
			keynum = e.keyCode;
		} else if (e.which) {
			keynum = e.which;
		}
		//only use custom keyboard events when tilesActive is true
		if (tileApp.tilesActive && keynum != 0) {
			switch (keynum) {
				case 32: //space bar
					tileApp.toggle(tileApp.cursorIndex);
					break;
				case 37: //left
					if (tileApp.cursorIndex > 0) offset = -1;
					break;
				case 38: //up
					if (tileApp.cursorIndex < tileApp.cols)
						//tileApp.cursorIndex = 0;
						tileApp.cursorIndex = (tileApp.rows - 1) * tileApp.cols + tileApp.cursorIndex;
					else
						offset = -tileApp.cols;
					break;
				case 39: //right
					if (tileApp.cursorIndex < tileApp.rows * tileApp.cols - 1) offset = 1;
					break;
				case 40: //down
					if (tileApp.cursorIndex > tileApp.rows * tileApp.cols - tileApp.cols - 1)
						//cursorIndex = tileApp.rows * tileApp.cols - 1;
						tileApp.cursorIndex = tileApp.cursorIndex % tileApp.cols;
					else
						offset = tileApp.cols;
					break;
				default:
					//alert(keynum);
					return true;
					break;
			}
			tileApp.cursorIndex += offset;
			document.getElementById("a" + tileApp.cursorIndex).focus();
			return false;
		}
	},
	showTextArea: function (txt) {
		var codeArea = document.getElementById(tileApp.codeAreaId),
		textBox = codeArea.getElementsByTagName("textarea")[0];
		codeArea.style.display = "block";
		if (document.body && document.body.scrollHeight) {
			window.scrollTo(0, document.body.scrollHeight);
		} else if (screen.height) {
			window.scrollTo(0, screen.height);
		}
		textBox.value = txt;
		textBox.focus();
		tileApp.tilesActive = false;
	},
	hideTextArea: function () {
		document.getElementById(tileApp.codeAreaId).style.display = "none";
		tileApp.tilesActive = true;
	},
	writeJSON: function () {
		tileApp.showTextArea(tileApp.getTruchetJSON(tileApp.truchetObj));
	},
	writeHTML: function (title) {
		if (!title) title = "JavaScript-generated Truchet Tiles from scriptar.com/tiles";
		var tmp = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n" +
			"<html xmlns=\"http://www.w3.org/1999/xhtml\">\n" +
			"<head>\n" +
			"<title>" + title + "</title>\n" +
			"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\"/>\n" +
			"<base href=\"http://scriptar.com/tiles/\"/>\n" +
			"<style type=\"text/css\" media=\"all\">\n" +
			"table.tilesTable {\n" +
			"  border: #000 1px solid;\n" +
			"  margin: 0px auto;\n" +
			"}\n" +
			"table.tilesTable img {\n" +
			"  border: none;\n" +
			"}\n" +
			"</style>\n" +
			"</head>\n" +
			"<body>\n" + tileApp.getTruchetHTML(true) + "\n</body>\n" +
			"</html>";
		tileApp.showTextArea(tmp);
	},
	start: function (f) {
		var i, rowColArr = [],
		typeArr = ["Triangles", "T+SS (Triangles plus Solid Squares)", "T+SS (25x25)", "Large quartered circles+SS", "Curves"],
		allArr = ["Random", "1st Tile", "2nd Tile", "3rd Tile", "4th Tile", "5th Tile", "6th Tile"];
		for (i = 0; i < 50; i++) {
			rowColArr[i] = (i + 1);
		}
		tileApp.rows = (tileApp.rows > 0 && tileApp.rows <= 50) ? tileApp.rows : 25;
		tileApp.cols = (tileApp.cols > 0 && tileApp.cols <= 50) ? tileApp.cols : 25;
		tileApp.possibleIdx = ["a.gif", "b.gif", "c.gif", "d.gif"];
		tileApp.pixelSize = 11;
		switch (tileApp.tileType) {
			case 1: //Triangle Truchet tiles (11x11)
				break;
			case 2: //Triangle Truchet tiles w/solid squares (11x11)
				tileApp.possibleIdx.push("e.gif");
				tileApp.possibleIdx.push("f.gif");
				break;
			case 3: //Triangles w/solid squares (25x25)
				tileApp.possibleIdx = ["img/a25.gif", "img/b25.gif", "img/c25.gif", "img/d25.gif", "img/e25.gif", "img/f25.gif"];
				tileApp.pixelSize = 25;
				break;
			case 4: //Quartered circles (99x99)
				tileApp.possibleIdx = ["img/qa99.gif", "img/qb99.gif", "img/qc99.gif", "img/qd99.gif", "img/e99.gif", "img/f99.gif"];
				tileApp.pixelSize = 99;
				break;
			default: //Curves
				tileApp.possibleIdx = ["1.gif", "2.gif"];
				break;
		}
		tileApp.setAllTo = (!isNaN(tileApp.setAllTo) && tileApp.setAllTo > 0 && tileApp.setAllTo <= tileApp.possibleIdx.length) ? tileApp.setAllTo : 0;
		if (tileApp.useDefault && typeof tileApp.truchetObj === "object") {
			tileApp.rows = tileApp.truchetObj.rows;
			tileApp.cols = tileApp.truchetObj.cols;
			tileApp.tileType = tileApp.truchetObj.tiletype;
			tileApp.possibleIdx = tileApp.truchetObj.tilefiles;
			tileApp.mainArr = tileApp.truchetObj.tiles;
		} else {
			tileApp.initTileArray();
		}
		document.getElementById(tileApp.gridId).innerHTML = tileApp.getTruchetHTML(false);
		if (!f) {
			f = document.forms[0];
		}
		if (f.rows && f.cols && f.type && f.setAll) {
			tileApp.initSelect(f.rows, rowColArr, tileApp.rows);
			tileApp.initSelect(f.cols, rowColArr, tileApp.cols);
			tileApp.initSelect(f.type, typeArr, tileApp.tileType);
			tileApp.initSelect(f.setAll, allArr, tileApp.setAllTo + 1);
		}
	},
	loadFromJSON: function (json) {
		tileApp.useDefault = false;
		try {
			tileApp.truchetObj = eval("(" + json + ")"); //this is dangerous
			tileApp.useDefault = (!isNaN(tileApp.truchetObj.rows) && !isNaN(tileApp.truchetObj.cols) && tileApp.truchetObj.rows * tileApp.truchetObj.cols === tileApp.truchetObj.tiles.length);
		} catch (err) {
			alert("JSON error: " + err.message);
		}
		if (!tileApp.useDefault) {
			alert("Invalid JSON. Using default parameters.");
			tileApp.hideTextArea();
		}
		tileApp.start();
	},
	loadFromForm: function (f) {
		tileApp.rows = f.rows.selectedIndex + 1;
		tileApp.cols = f.cols.selectedIndex + 1;
		tileApp.tileType = f.type.selectedIndex + 1;
		tileApp.setAllTo = f.setAll.selectedIndex;
		tileApp.useDefault = false;
		tileApp.start(f);
		return false;
	},
	loadFromQueryString: function (f) {
		location.search = "rows=" + (f.rows.selectedIndex + 1) + "&cols=" + (f.cols.selectedIndex + 1) + "&type=" + (f.type.selectedIndex + 1) + "&setAll=" + (f.setAll.selectedIndex);
	},
	init: function () {
		var args = tileApp.getArgs();
		tileApp.useDefault = (!args.rows || !args.cols);
		tileApp.rows = (args.rows) ? parseInt(args.rows, 10) : 25;
		tileApp.cols = (args.cols) ? parseInt(args.cols, 10) : 25;
		tileApp.tileType = (args.type) ? parseInt(args.type, 10) : 1;
		tileApp.setAllTo = parseInt(args.setAll, 10);
		tileApp.start();
		document.onkeydown = tileApp.navigate;
		tileApp.tilesActive = true;
	}
};