// Global constants:
var TILE_BLANK = '<img src="images/tile-0.gif" width="16" height="16" border="0" />';
var TILE_FLAG  = '<img src="images/tile-f.gif" width="16" height="16" border="0" />';
var TILE_BOMB  = '<img src="images/tile-b.gif" width="16" height="16" border="0" />';

// Locals
var grid;// [y][x]
var visible; // [y][x]
var counters; // [y][x]
var marked; // [y][x]
var mode = 0;
var IE = document.all?true:false;

// Common sizes:
// 9x9, 10
// 9x9, 35
// 16x16, 40
// 16x16, 99
// 30x16, 99
// 30x16, 170

function calculateCounter(formName, x, y) {
	var width = document.forms[formName].width.value;
	var height = document.forms[formName].height.value;
	var i, j;
	var minx = x - 1, miny = y - 1, maxx = x + 1, maxy = y + 1;
	var result = 0;
	if (minx < 0) minx = 0;
	if (miny < 0) miny = 0;
	if (maxx >= width) maxx = width-1;
	if (maxy >= height) maxy = height - 1;
	for (i = minx; i<= maxx; i++)
		for (j=miny; j<= maxy; j++)
			if (grid[j][i] == 1)
				result = result + 1;
	return result;
}

function initialize(formName) {
	var width = document.forms[formName].width.value;
	var height = document.forms[formName].height.value;
	var count = document.forms[formName].count.value;
	var x = Math.floor(width / 2) - 1;
	var y = Math.floor(height / 2) - 1;
	var possibilities = new Array();
	var i;
	var j;
	// Initialize grid and visible to nulls
	grid = new Array(height);
	visible = new Array(height);
	counters = new Array(height);
	marked = new Array(height);
	for (i=0; i<height; i++) {
		var gridRow = new Array(width);
		var visibleRow = new Array(width);
		var countersRow = new Array(width);
		var markedRow = new Array(width);
		for (j=0; j<width; j++) {
			gridRow[j] = 0;
			visibleRow[j] = 0;
			countersRow[j] = 0;
			markedRow[j] = 0;
		}
		grid[i] = gridRow;
		visible[i] = visibleRow;
		counters[i] = countersRow;
		marked[i] = markedRow;
	}
	// Set up first visible blocks: center, plus immediate surroundings
	for (i=y-1; i<=y+1; i++)
		for (j=x-1; j<=x+1; j++)
			visible[i][j] = 1;
	// Figure out where to place targets (not within one of start)
	for (i=0; i<height; i++)
		for (j=0; j<width; j++)
			if ((Math.abs(i-y) > 1) || (Math.abs(j-x) > 1))
				possibilities[possibilities.length] = new Array(i, j);
	// Place targets
	for (i=0; i<count; i++) {
		j = Math.floor(Math.random() * 1000 % possibilities.length);
		grid[possibilities[j][0]][possibilities[j][1]] = 1;
	}
	// Calculate counters
	for (i=0; i<height; i++)
		for (j=0; j<width; j++)
			counters[i][j] = calculateCounter(formName, j, i);
}

function draw(formName, prefix, showAll) {
	var width = document.forms[formName].elements['width'].value;
	var height = document.forms[formName].elements['height'].value;
	var i;
	var j;
	for (i=0; i<height; i++) {
		for (j=0; j<width; j++) {
			var theElement;
			var elementName = prefix + j + '_' + i;
			// Get the table data
			if (!IE)
				theElement = document.getElementById(elementName);
			else
				theElement = document.all(elementName);
			// Abort this loop on error
			if (!theElement)
				continue;
			if (showAll) {
				// Debug mode...
				theElement.innerHTML = (grid[i][j] == 1 ? '<b>' : '') + visible[i][j] + ',' + grid[i][j] + ',' + counters[i][j] + (grid[i][j] == 1 ? '</b>' : '');
			} else {
				// Draw something in grid based on state
				if (marked[i][j])
					theElement.innerHTML = '<a href="#" onclick="return gridClick(' + String.fromCharCode(39) + formName + String.fromCharCode(39) + 
						',' + String.fromCharCode(39) + prefix + String.fromCharCode(39) + 
						',' + j + ',' + i + ')">' + TILE_FLAG + '</a>';
				else if (!visible[i][j])
					theElement.innerHTML = '<a href="#" onclick="return gridClick(' + String.fromCharCode(39) + formName + String.fromCharCode(39) + 
						',' + String.fromCharCode(39) + prefix + String.fromCharCode(39) + 
						',' + j + ',' + i + ')">' + TILE_BLANK + '</a>';
				else if (grid[i][j])
					theElement.innerHTML = TILE_BOMB;
				else
					theElement.innerHTML = counters[i][j];
			}
		}
	}
}

function checkWin(formName) {
	var width = document.forms[formName].width.value;
	var height = document.forms[formName].height.value;
	// Count how many squares *should* be visible (i.e. don't have bombs, i.e. grid size minus number of bombs)
	var visibleRemaining = width * height - document.forms[formName].count.value;
	for (i=0; i<height; i++) {
		for (j=0; j<width; j++) {
			if (visible[i][j]) {
				if (grid[i][j] == 0)
					// An empty good uncovered tile
					visibleRemaining = visibleRemaining - 1;
				else
					// An uncovered bomb.  Your head a splode.
					return 2;
			}
		}
	}
	// If everything that is possible to be uncovered is uncovered, we have a winning endgame
	if (visibleRemaining == 0)
		return 1;
	// If we reached here, user neither won nor lost
	return 0;
}

function gridClick(formName, prefix, x, y) {
	var width = document.forms[formName].width.value;
	var height = document.forms[formName].height.value;
	// Bounds check
	if ((x < 0) || (y < 0) || (x >= width) || (y >= height))
		return;
	// If in marking mode, toggle mark
	if (mode == 1) {
		marked[y][x] = marked[y][x] == 1 ? 0 : 1;
		draw(formName, prefix, false);
		return;
	}
	// If marked, don't let user accidentally uncover
	if (marked[y][x])
		return;
	// Uncover
	visible[y][x] = 1;
	draw(formName, prefix, false);
	// Check for endgame
	switch(checkWin(formName)) {
		case 0: break;
		case 1: alert('A WINNAR IS YOU!'); break;
		case 2: alert('YOUR HEAD A SPLODE!'); break;
	}
	return 1;
}

function setMode(newMode) {
	var theElement;
	mode = newMode;
	if (!IE)
		theElement = document.getElementById('uncoverLink');
	else
		theElement = document.all('uncoverLink');
	if (theElement)
		theElement.style.color = mode == 0 ? '#000000' : '#cccccc';
	if (!IE)
		theElement = document.getElementById('markLink');
	else
		theElement = document.all('markLink');
	if (theElement)
		theElement.style.color = mode == 1 ? '#000000' : '#cccccc';
}
