//---------------------------------------------
// Helper functions

function isWindowsIE()
{
	var isIE = (navigator.appVersion.indexOf("MSIE") != -1);
	var isWin = (navigator.appVersion.toLowerCase().indexOf("win") != -1);
	var isOpera = (navigator.userAgent.indexOf("Opera") != -1);
	return (isIE && isWin && !isOpera);
}

function vector(x, y)
{
	this.x = x;
	this.y = y
}

function elemPos(el)
{
	var p = new vector(0, 0);
	while (el)
	{
		p.x += el.offsetLeft;
		p.y += el.offsetTop;
		el = el.offsetParent;
	}
	return p;
}

function pagePos(e)
{
	if (e.pageX != null)
		return new vector(e.pageX, e.pageY);
	return new vector(e.clientX + document.body.scrollLeft, e.clientY + document.body.scrollTop);
}

function eventBlock(e)
{
	if (!e) e = window.event;
	var p = pagePos(e);
	var r = elemPos(gGridLayer);
	return new vector(Math.floor((p.x - r.x) / 20), Math.floor((p.y - r.y) / 20));
}

function isLeftButton(e)
{
	if (!e) e = window.event;
	if (e.which == 1)
		return true;
	if (gIsWindowsIE)
		return (e.button == 1);
	return e.button == 0;
}

function eventTarget(e)
{
	if (!e) e = window.event;
	var targ = e.target || e.srcElement;
	return targ;
}

function createImage(x, y, src)
{
	var im = document.createElement("img");
	im.src = src;
	im.style.position = "absolute";
	im.style.left = x;
	im.style.top = y;
	gGridLayer.appendChild(im);
	return im;
}

function setCursor(el, c)
{
	if (!gIsWindowsIE)
	{
		if (c == "hand")
			c = "pointer";
	}
	el.style.cursor = c;
}

function createHilite()
{
	var im = document.createElement("img");
	im.style.position = "absolute";
	im.style.visibility = "hidden";
	gGridLayer.appendChild(im);
	return im;
}

function createImage2(src)
{
	var im = new Image;
	im.src = src;
	return im;
}


//---------------------------------------------
// class Grid

function Grid()
{
	this.width = 48;
	this.height = 52;
	
	var d = new Array(this.height);
	for (var i = 0; i < this.height; i++)
	{
		d[i] = new Array(this.width);
		for (var j = 0; j < this.width; j++)
			d[i][j] = null;
	}
	this.data = d;
}

Grid.prototype.invalidateBlocks = function(str)
{
	var d = this.data;
	var pos = 0;
	while (pos < str.length)
	{
		var end = str.indexOf(" ", pos);
		if (end < 0)
			end = str.length;
		var t = str.substring(pos, end);
		var b = t.split("_");
		d[b[1]][b[0]] = 0;
		pos = end + 1;
	}
}

Grid.prototype.isSet = function(b)
{
	var v = this.data[b.y][b.x];
	return (v != null && v != 0);
}

Grid.prototype.isInBounds = function(b)
{
	if (b.x < 0 || b.x >= this.width)
		return false;
	if (b.y < 0 || b.y >= this.height)
		return false;
	return true;
}

Grid.prototype.isValid = function(b)
{
	if (!this.isInBounds(b))
		return false;
	var v = this.data[b.y][b.x];
	return (v != 0);
}

Grid.prototype.select = function(b, show)
{
	var v = this.data[b.y][b.x];
	if (v != 0)
	{
		if (show && v == null)
		{
			this.data[b.y][b.x] = createImage(b.x * 20, b.y * 20, gCheck.src);
			this.updateCount();
		}
		else if (!show && v != null)
		{
			gGridLayer.removeChild(v);
			this.data[b.y][b.x] = null;
			this.updateCount();
		}
	}
}

Grid.prototype.getCount = function()
{
	var count = 0;
	for (var i = 0; i < this.height; i++)
	{
		for (var j = 0; j < this.width; j++)
		{
			var v = this.data[i][j];
			if (v != null && v != 0)
				count++;
		}
	}
	return count;
}

Grid.prototype.updateCount = function()
{
	count = this.getCount();
	gCost.firstChild.data = "$" + (count * 20);
}

Grid.prototype.clear = function()
{
	for (var i = 0; i < this.height; i++)
	{
		for (var j = 0; j < this.width; j++)
		{
			var v = this.data[i][j];
			if (v != null && v != 0)
			{
				gGridLayer.removeChild(v);
				this.data[i][j] = null;
			}
		}
	}
	this.updateCount();
}

Grid.prototype.getSelectionString = function()
{
	sel = new Array();
	for (var i = 0; i < this.height; i++)
	{
		for (var j = 0; j < this.width; j++)
		{
			var v = this.data[i][j];
			if (v != null && v != 0)
				sel.push(j + "_" + i);
		}
	}
	return sel.join(" ");
}


//---------------------------------------------
// Globals

var gIsWindowsIE = isWindowsIE();
var gGridLayer = document.getElementById("grid");
var gClear = document.getElementById("clear");
var gCost = document.getElementById("cost");
var gContinue = document.getElementById("continue");
var gHiddenForm = document.getElementById("blockform");
var gHiddenArg = document.getElementById("blocks");
var gGrid = new Grid();
var gDown = false;
var gShow = false;
var gPrevHilite = null;
var gHiliteImg = createImage2("images/blockhilite.gif");
var gUnhiliteImg = createImage2("images/blockunhilite.gif");
var gCheck = createImage2("images/blockcheck.gif");
var gHilite = createHilite();


//---------------------------------------------
// Events

gGridLayer.onmousedown = function(e)
{
	if (!isLeftButton(e))
		return false;
	var block = eventBlock(e);
	if (gGrid.isValid(block))
	{
		gDown = true;
		gShow = !gGrid.isSet(block);
		gGrid.select(block, gShow);
		updateHilite(null);
		updateHilite(block);
	}
	else
	{
		gDown = false;		
	}
	return false;
}

document.onmouseup = function(e)
{
	gDown = false;
}

document.onmouseout = function(e)
{
	if (!e) e = window.event;
	if (!e.relatedTarget && !e.toElement)
	{
		gDown = false;
		updateHilite(null);
	}
}

function updateHilite(b)
{
	var p = gPrevHilite;
	if (b == null && p == null)
		return;
	if (b && p && b.x == p.x && b.y == p.y)
		return;
		
	var o;
	if (p != null)
	{
		o = gGrid.data[p.y][p.x];
		if (o != null)
			gGrid.data[p.y][p.x].style.visibility = "visible";
	}
	if (b != null)
	{
		o = gGrid.data[b.y][b.x];
		if (o)
		{
			o.style.visibility = "hidden";
			gHilite.src = gUnhiliteImg.src;
		}
		else
			gHilite.src = gHiliteImg.src;

		gHilite.style.left = b.x * 20;
		gHilite.style.top = b.y * 20;
		gHilite.style.visibility = "visible";
		setCursor(gGridLayer, "hand");
	}
	else
	{
		gHilite.style.visibility = "hidden";
		setCursor(gGridLayer, "default");
	}
	gPrevHilite = b;
}

document.onmousemove = function(e)
{
	var block = eventBlock(e);
	if (gGrid.isValid(block))
	{
		if (gDown)
		{
			gGrid.select(block, gShow);
		}
		updateHilite(block);
	}
	else
	{
		updateHilite(null);
	}
}

document.ondragstart = function(e)
{
	return false;
}

gClear.onclick = function()
{
	gGrid.clear();
}

gContinue.onclick = function()
{
	count = gGrid.getCount();
	if (count == 0)
	{
		alert("You must select one or more blocks in order to continue.");
	}
	else
	{
		gHiddenArg.value = gGrid.getSelectionString();
		gHiddenForm.submit();
	}
}
