
//life_start with a 40x40 life_grid.
var life_width, life_height;

//life_grid tracks alive/dead status, life_squares manages corresponding div objects.
var life_grid = new Array();
var life_squares = new Array();

//track the neighbours
var life_totals = new Array();

//life_timer controls progression
var life_timer;


function life_init() {
	life_width = document.getElementById("life_width").value;
	life_height = document.getElementById("life_height").value;
	var life_board = document.getElementById("life_board");
	life_board.innerHTML = '';
	
	//set up the life_board.
	for (i=0; i<life_width; i++){
		
		life_squares[i] = new Array();
		life_grid[i] = new Array();
		
		for (j=0; j<life_height; j++) {
			newSq = document.createElement('div');
			life_squares[i][j] = newSq;
			newSq.column = i; newSq.row = j;
			newSq.style.left = i*10 + 2 + 'px';
			newSq.style.top = j*10 + 2 + 'px';
			newSq.onclick = function() {
				m = this.column; n = this.row;
				if (life_grid[m][n]) {
					life_grid[m][n] = 0;
					this.className = 'dead';
				} else {
					life_grid[m][n] = 1;
					this.className = 'alive';
				}
			}
			
			newSq.onmouseover = function() {
				if (life_grid[this.column][this.row])
					this.className = 'hover1';
				else
					this.className = 'hover2';
				
			}
			
			newSq.onmouseout = function() {
				if (life_grid[this.column][this.row])
					this.className = 'alive';
				else
					this.className = 'dead';
			}
			
			life_board.appendChild(life_squares[i][j]);
		}
	}
	life_clearBoard();
}

function life_clearBoard() {
	life_stop();
	for (i=0; i<life_width; i++){
		for (j=0; j<life_height; j++) {
			life_death(i,j);
		}
	}
}


function life_fillrandom(p) {
	//randomly populate the life_board with p probability of life
	for (i=0; i<life_width; i++){
		for (j=0; j<life_height; j++) {
			Math.random()<p ? life_birth(i,j) : life_death(i,j);
		}
	}
}

function life_start() {
	var button = document.getElementById("start");
	button.style.backgroundColor = "#c33";
	button.innerHTML = "Stop";
	life_live();
}

function life_stop() {
	var button = document.getElementById("start");
	button.style.backgroundColor = "#3c3";
	button.innerHTML = "Start";
	clearTimeout(life_timer);
}

function life_birth(i, j) {
	life_grid[i][j] = 1;
	life_squares[i][j].className = 'alive';
}

function life_death(i, j) {
	life_grid[i][j] = 0;
	life_squares[i][j].className = 'dead';
}

function life_live() {
	//reset all the life_totals
	for (i=0; i<life_width; i++) {
		life_totals[i] = new Array();
		for (j=0; j<life_width; j++) {
			life_totals[i][j] = 0;
		}
	}
	//count the neighbours
	for (i=0; i<life_width; i++) {
		for (j=0; j<life_width; j++) {
			if (life_grid[i][j]) {
				boundaries ? life_incr(i,j) : life_incr_noborder(i, j);
			}
		}
	}
	
	//RULES:
	life_birthCounts = document.getElementById("life_birthValues").value;
	life_surviCounts = document.getElementById("life_surviValues").value;
	
	for (i=0; i<life_width; i++) {
		for (j=0; j<life_height; j++) {
			total = life_totals[i][j];
			if (life_birthCounts.indexOf(total) != -1 && life_grid[i][j] == 0)
				life_birth(i,j);
			else if (life_surviCounts.indexOf(total) != -1  && life_grid[i][j] == 1) {
				//do nothing
			} else
				life_death(i,j);
		}
	}
	life_timer = setTimeout(life_live, 100);
}

var playing = false;

function toggleStart() {
	if (playing) {
		life_stop();
	} else {
		life_start();
	}
	playing = !playing;
}
		

//boundaries or seamless?
var boundaries = false;

function toggleBoundaries() {
	var button = document.getElementById("boundaries");
	if (boundaries) {
		button.style.backgroundColor = "#2ad";
		button.innerHTML = "Boundaries Off";
	}
	else {
		button.style.backgroundColor = "#fb1";
		button.innerHTML = "Boundaries On";
	}
	boundaries = !boundaries;
}
	
		

function life_incr(i, j) {
	if (i > 0) {
		life_totals[i-1][j]++;
		if (j > 0) {
			life_totals[i-1][j-1]++;
		}
		if (j+1 < life_height) {
			life_totals[i-1][j+1]++;
		}
	}
	if (j > 0) {
		life_totals[i][j-1]++;
		if (i+1 < life_width) {
			life_totals[i+1][j-1]++;
		}
	}
	if (i+1 < life_width) {
		life_totals[i+1][j]++;
		if (j+1 < life_height) {
			life_totals[i+1][j+1]++;
		}
	}
	if (j+1 < life_height) {
		life_totals[i][j+1]++;
	}
}
function life_incr_noborder(i, j) {
	iprev = i-1;
	inext = i+1;
	if (i == 0) iprev = life_width - 1;
	if (i == life_width - 1) inext = 0;
	
	jprev = j-1;
	jnext = j+1;
	if (j == 0) jprev = life_height - 1;
	if (j == life_height - 1) jnext = 0;
	
	life_totals[iprev][jprev]++;
	life_totals[iprev][j]++;
	life_totals[iprev][jnext]++;
	life_totals[i][jprev]++;
	life_totals[i][jnext]++;
	life_totals[inext][jprev]++;
	life_totals[inext][j]++;
	life_totals[inext][jnext]++;
}


function loadPreset(pre) {
	if (playing) toggleStart();
	var loadThis;
	var survi = document.getElementById("life_surviValues");
	var birth = document.getElementById("life_birthValues");
	switch (pre) {
		case 1:
			//glider
			loadThis = new Array(new Array(1,1,1),
								 new Array(1,0,0),
								 new Array(0,1,0));
			survi.value = "23";
			birth.value = "3";
			if (boundaries) toggleBoundaries();
			break;
		case 2:
			//LWSS
			loadThis = new Array(new Array(1,1,1,1,0),
								 new Array(1,0,0,0,1),
								 new Array(1,0,0,0,0),
								 new Array(0,1,0,0,1));
			survi.value = "23";
			birth.value = "3";
			if (boundaries) toggleBoundaries();
			break;
		case 3:
			//jellyfish
			loadThis = new Array(new Array(0,0,1),
								 new Array(0,1,1),
								 new Array(1,1,1));
			survi.value = "245";
			birth.value = "36";
			if (boundaries) toggleBoundaries();
			break;
		case 4:
			//osci1
			loadThis = new Array(new Array(1,1,1));
			survi.value = "23";
			birth.value = "3";
			break;
		case 5:
			//osci2
			loadThis = new Array(new Array(0,1,1,1),
								 new Array(1,1,1,0));
			survi.value = "23";
			birth.value = "3";
			break;
		case 6:
			//osci3
			loadThis = new Array(new Array(0,0,1,1,1,0,0),
								 new Array(0,0,0,1,0,0,0),
								 new Array(1,0,1,0,1,0,1),
								 new Array(0,0,0,1,0,0,0),
								 new Array(0,0,1,1,1,0,0));
			survi.value = "245";
			birth.value = "3";
			break;
		case 7:
			//glider gun
			loadThis = new Array(new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0),
								 new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0),
								 new Array(0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1),
								 new Array(0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,1,1),
								 new Array(1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
								 new Array(1,1,0,0,0,0,0,0,0,0,1,0,0,0,1,0,1,1,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0),
								 new Array(0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0),
								 new Array(0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
								 new Array(0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
								 new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
								 new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
								 new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
								 new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0),
								 new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0));
			survi.value = "23";
			birth.value = "3";
			if (!boundaries) toggleBoundaries();
			break;
		case 8:
			//bounce
			loadThis = new Array(new Array(0,0,0,0,0,0,1,1,0,0,0,0,0,0),
								 new Array(0,0,0,0,0,0,1,1,0,0,0,0,0,0),
								 new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0),
								 new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0),
								 new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0),
								 new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0),
								 new Array(0,0,0,0,0,0,0,0,0,0,0,0,0,0),
								 new Array(0,1,1,0,0,0,0,0,0,0,0,1,1,0),
								 new Array(1,0,1,0,0,0,0,0,0,0,0,1,0,1),
								 new Array(0,0,1,0,0,0,0,0,0,0,0,1,0,0));
			survi.value = "23";
			birth.value = "3";
			if (boundaries) toggleBoundaries();
			break;
		default:
			return;
	}
	var preset_height = loadThis.length;
	var preset_width = loadThis[0].length;
	var resize = false;
	if (preset_width + 4 > life_width) {
		document.getElementById("life_width").value = preset_width + 4;
		resize = true;
	}
	if (preset_height + 4 > life_height) {
		document.getElementById("life_height").value = preset_height + 4;
		resize = true;
	}
	if (resize) {
		life_init();
	}
	
	var leftMargin = Math.floor((life_width - preset_width) / 2);
	var topMargin = Math.floor((life_height - preset_height) / 2);
	life_clearBoard();
	
	for (i=0; i<preset_height; i++) {
		for (j=0; j<preset_width; j++) {
			if (loadThis[i][j]) {
				life_birth(j+leftMargin, i+topMargin);
			}
		}
	}
}