var life = {};

life.neighbors = function(x,y) {
	neighbors = -1;
	for(i=-1;i<2;++i) {
		for(j=-1;j<2;++j) {
			if(life.current[y+j] && life.current[y+j].indexOf(x+i) != -1) {++neighbors;}
			if(neighbors > 3) {return 4;}
		}
	}
	return neighbors;
}

life.simulate = function() {
	if(life.newInterval) {
		clearInterval(life.interval);
		life.refresh_period = life.newInterval;
		life.interval = setInterval('life.simulate()',life.refresh_period);
		life.newInterval = false;
	}
	
	if(life.newSize) {
		clearInterval(life.interval);
		life.context.clearRect(0,0,life.width,life.height);
		if(life.newSize < life.block_size) {
			life.block_size = life.newSize
		}
		else {
			life.current.splice((life.height/life.newSize)+1);			
			life.new_max_x = Math.max(0,life.new_max_x);
			for(y=0;y<life.current.length+2;++y) {
				if(life.current[y]) {
					for(x=0;x<life.current[y].length;++x) {
						if(life.current[y][x] > ((life.width/life.newSize)+1)) {
							life.current[y].splice(x,1);	
						}
						else {
							life.new_max_x = Math.max(life.current[y][x],life.new_max_x);	
						}
					}
				}
			}
			life.max_x = life.new_max_x;
			life.block_size = life.newSize;
		}
		life.newSize = false;
		life.interval = setInterval('life.simulate()',life.refresh_period);
	}
	
	life.new_max_x = Math.max(0,life.new_max_x);
	for(y=0;y<life.current.length+2;++y) {
		if(!life.next[y]){life.next[y] = [];}
		for(x=0;x<life.max_x+2;++x) {
			if(life.current[y] && life.current[y].indexOf(x) != -1) {
				if(y>0 && y<=(life.height/life.block_size) && x>0 && x<=(life.width/life.block_size)) {
					life.context.fillRect((x-1)*life.block_size,(y-1)*life.block_size,life.block_size,life.block_size);
				}
				
				var neighbors = life.neighbors(x,y);
				if(neighbors > 1 && neighbors < 4) {
					life.next[y].push(x);
					life.new_max_x = Math.min(Math.max(x,life.new_max_x),(life.width/life.block_size)+3);
				}
				else {
					life.context.clearRect((x-1)*life.block_size,(y-1)*life.block_size,life.block_size,life.block_size);	
				}
			}
			else {
				if(life.neighbors(x,y) == 2) {
					life.next[y].push(x);
					life.new_max_x = Math.min(Math.max(x,life.new_max_x),(life.width/life.block_size)+3);
					life.context.fillRect((x-1)*life.block_size,(y-1)*life.block_size,life.block_size,life.block_size);
				}
			}
		}
	}
	
	life.next.splice((life.height/life.block_size)+3);
	life.current = life.next;
	life.max_x = life.new_max_x;
	life.new_max_x=0;
	life.next = [];
	
	if(life.clear) {
		clearInterval(life.interval);	
		life.clear = false;
		life.current = [[]];
		life.next = [];
		life.context.clearRect(0,0,life.width,life.height);
		life.max_x = 0;
		if(life.choosing) {life.makeChoice();}
		life.interval = setInterval('life.simulate()',life.refresh_period);
	}
}

life.toggleTime = function(e) {
	e.returnValue = false;
	
	life.simulating = (life.simulating+1)%2;
	if(life.simulating == 1) {
		life.interval = setInterval('life.simulate()',life.refresh_period);
		life.time_toggle_input.value='Pause Time';
	}
	else {
		clearInterval(life.interval);	
		life.time_toggle_input.value='Carry On';
	}
	return false;
}

life.clearLife = function(e) {
	if(e && e.returnValue) {e.returnValue = false;}
	
	life.clear = true;
	
	return false;
}

life.choose = function() {
	life.choosing = true;
	life.clearLife();	
}

life.makeChoice = function() {
	life.max_x = life.width/life.block_size;
	life.current = life.choices[life.chooser.value];
	for(y=1;y<life.current.length;++y) {
		for(x=0;x<life.current[y].length;++x) {
			if(life.current[y][x] != 0) {
				life.context.fillRect((life.current[y][x]-1)*life.block_size,(y-1)*life.block_size,life.block_size,life.block_size);
			}
		}
	}
	life.choosing = false;
}

life.dragAndDraw = function(e) {
	var curX = e.clientX;
	var curY = e.clientY;
	
	if(Math.abs(curX-life.lastX) >= life.block_size || Math.abs(curY-life.lastY) >= life.block_size) {
		life.lastX = curX;
		life.lastY = curY;
		
		curX = Math.floor((curX-life.canvas.offsetLeft)/life.block_size)+1;
		curY = Math.floor((curY-life.canvas.offsetTop)/life.block_size)+1;
		
		for(i=0;i<=curY;++i) {
			if(!life.next[i]){life.next[i] = [];}
		}
		life.next[curY].push(curX);
		life.context.fillRect((curX-1)*life.block_size,(curY-1)*life.block_size,life.block_size,life.block_size);
		life.new_max_x = Math.max(life.new_max_x,curX+1);		
	}

	life.lastX = curX;
	life.lastY = curY;
}

life.periods = [1000,250,160,100,20];
life.bsizes = [4,8,16];

if (navigator.userAgent.indexOf('Chrome') != -1) {
	life.refresh_period=life.periods[3];
	document.getElementById('sp2').setAttribute('checked','');document.getElementById('sp3').setAttribute('checked','checked');
}
else {
	life.refresh_period=life.periods[2];
	document.getElementById('sp2').setAttribute('checked','checked');
}
document.getElementById('bs1').setAttribute('checked','checked');


life.canvas = document.getElementById('life');
life.chooser = document.getElementById('life-choices');
life.clear_life_input = document.getElementById('clear-life');
life.time_toggle_input = document.getElementById('time-toggle');
life.bs_controls = document.getElementById('ctrl-bsize').getElementsByTagName('input');
life.sp_controls = document.getElementById('ctrl-speed').getElementsByTagName('input');

if (life.canvas && life.canvas.getContext) {
	life.context = life.canvas.getContext('2d');
	if(life.context) {		
		life.choices = [
						[[],[],[],[],[],[],[],[],[],[5,8],[9],[5,9],[6,7,8,9],[],[],[],[4],[5],[3,4,5]],
						[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[17,18,24,25],[18,19,23,24],[15,18,20,22,24,27],[15,16,17,19,20,22,23,25,26,27],[16,18,20,22,24,26],[17,18,19,23,24,25],[],[17,18,19,23,24,25],[16,18,20,22,24,26],[15,16,17,19,20,22,23,25,26,27],[15,18,20,22,24,27],[18,19,23,24],[17,18,24,25]],
						[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[17,18,24,25],[18,19,23,24],[15,18,20,22,24,27],[15,16,17,19,20,22,23,25,26,27],[16,18,20,22,24,26,61,64],[17,18,19,23,24,25,60],[60,64],[17,18,19,23,24,25,60,61,62,63],[16,18,20,22,24,26],[15,16,17,19,20,22,23,25,26,27],[15,18,20,22,24,27],[18,19,23,24],[17,18,24,25]],
						[[],[],[],[],[],[30],[28,30],[18,19,26,27,40,41],[17,21,26,27,40,41],[6,7,16,22,26,27],[6,7,16,20,22,23,28,30],[16,22,30],[17,21],[18,19]],
						[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[52,54],[51,54],[50,51],[49],[48,49,50,51],[47,52],[47,50],[47,50],[48,58,59,60,64,65,66],[49,50,51,52,54,57,60,64,67],[50,54,60,64],[51,60,64],[51,53,60,64],[],[50,51,52,58,59,60,64,65,66],[50,51,59,65],[50,51,52,59,60,61,62,63,64,65],[58,66],[51,53,57,58,59,60,61,62,63,64,65,66,67],[50,53,56,69,70],[50,56,57,58,59,60,61,62,63,64,65,66,67,71],[50,54,68,72],[51,55,56,57,58,59,60,61,62,63,64,65,66,72],[52,53,66,69,72],[55,56,57,58,59,60,61,62,63,64,65,69,71],[56,64],[57,58,59,60,61,62,63,70,71,72],[57,63,71,72],[56,57,58,62,63,64,70,71,72],[],[58,62,69,71],[58,62,71],[58,62,68,72],[55,58,62,65,68,70,71,72,73],[56,57,58,62,63,64,74],[72,75],[72,75],[70,75],[71,72,73,74],[73],[71,72],[68,71],[68,70]],
						[[],[],[],[],[],[],[],[],[],[],[],[],[],[],[22,23,29,30,31,32],[20,21,23,24,28,32],[20,21,22,23,32],[21,22,28,31],[],[19],[18,19,28,29],[17,27,30],[18,19,20,21,22,27,30],[19,20,21,22,26,27,29,30],[22,27,28],[],[],[],[29,30,31,32],[11,14,28,32],[15,32],[11,15,28,31],[12,13,14,15]]
						];
		
		life.lastX = -20;
		life.lastY = -20;
		
		life.block_size = 8;		
		life.width = 1024;
		life.height = 640;
		life.max_x = life.width/life.block_size;
		life.new_max_x = 0;
		
		life.makeChoice();
		life.next = [];
		life.simulating = true;	
		
		life.interval = setInterval('life.simulate()',life.refresh_period);
	}
}

/*controls*/
for(i=0;i<life.sp_controls.length;++i) {
	life.sp_controls[i].onclick = function() {
		if(this && this.value && life.periods[this.value]) {
			life.newInterval = life.periods[this.value];
		}
	}
}

for(i=0;i<life.bs_controls.length;++i) {
	life.bs_controls[i].onclick = function() {
		if(this && this.value && life.bsizes[this.value]) {
			life.newSize = life.bsizes[this.value];
		}
	}
}

life.time_toggle_input.onclick = function(event) {
	return life.toggleTime(event);	
};

life.clear_life_input.onclick = function(event) {
	return life.clearLife(event);	
}

life.chooser.onchange = function(event) {
	life.choose();
}

life.canvas.onmousedown = function(event) {
	if(life.simulating){
		life.pauseByMouseDown = true;
		life.toggleTime(event);
	}
	life.canvas.onmousemove = function(event) {
		life.dragAndDraw(event);
	}
}
document.onmouseup = function(event) {
	life.canvas.onmousemove = null;	
	if(life.pauseByMouseDown && !life.simulating) {life.toggleTime(event);life.pauseByMouseDown=false;}
	life.lastX = -20;
	life.lastY = -20;
}
