// Element Dots by pok5.de
// Licence: http://creativecommons.org/licenses/MIT/
 
var updateTime = 70;
var spawnTime = 200;
var updateEvent = null;
var fountainEvent = null;
var matrix = new Array();
var matrix_old = new Array();
var matrix_lock = new Array();
var dotw = 3;
var doth = 3;
var width = 0;
var height = 0;
var brushtyp = 10;
var brushsize = 1;
var fountains = new Array();
var spawns = new Array();
var selectedFountainIdx = null;
var canvas;
var context;

function updateBrush() {
	brushtyp = $('input[name=brush]:radio:checked').val();
	if (brushtyp==10) {
		$('input[name=brushsize]:radio').attr("disabled", true); 
		$('label[for=brushsize1]').attr("class", "disabled"); 
		$('label[for=brushsize2]').attr("class", "disabled"); 
	} else {
		$('input[name=brushsize]:radio').removeAttr("disabled");
		$('label[for=brushsize1]').removeAttr("class");
		$('label[for=brushsize2]').removeAttr("class");
	}
}

function updateBrushSize() {
	brushsize = $('input[name=brushsize]:radio:checked').val();
}

function play() {
	if ($("#pausePlayBtn").val() != "Play") {
		clearInterval(fountainEvent);
		$("#pausePlayBtn").val('Play');
	} else {
		fountainEvent = setInterval(spawnFountain, spawnTime);
		$("#pausePlayBtn").val('Pause');
	}
}

function reset() {
	if (confirm('Clear stage?')) window.location.reload();
}

function dot(x,y) {
	return (matrix[x] && matrix[x][y]) ? matrix[x][y] : 0;
}

function init() {
	CFInstall.check({
		mode: "overlay",
	    destination: "http://www.pok5.de/elementdots/"
	});
	
	if ($.browser.opera) {
    	alert("This doesn't work on Opera!");
    	return;
 	}
 	
	for(var i=0;i<3;i++) {
		spawns[i] = $('#spawn'+i);
		spawns[i].live('mousedown', {spawnId:i}, spawnDragStart);
	}
	
	canvas = $('#canvas');
	width = Math.floor(canvas[0].width / dotw);
	height = Math.floor(canvas[0].height / doth);
	$('input[name=brush][value=10]').attr('checked', true);
	$('input[name=brushsize][value=1]').attr('checked', true);
	updateBrush();
	updateBrushSize();
	context = canvas[0].getContext('2d');
	if (!context) return;
	context.globalCompositeOperation = 'copy';
	for (var w=0; w<=width; w++) {
		matrix[w] = new Array(height);
		matrix_old[w] = new Array(height);
		matrix_lock[w] = new Array(height);
	}
	setSpawnFountain(Math.round(width/4),30,1);		
	setSpawnFountain(Math.round(width/2),30,2);		
	setSpawnFountain(Math.round(width/4*3),30,5);		
	updateEvent = setInterval(update, updateTime);
	fountainEvent = setInterval(spawnFountain, spawnTime);
	canvas.live('mousedown', spawnEvent);
	canvas.live('mouseup', stopMouseMove);
	canvas.live('mouseleave', onCanvasLeave);
}


function killDot(x,y) {
	if (x>=0 && y>=0 && x<=width && y<=height) {
		matrix[x][y] = null;
		matrix_lock[x][y]=false;
	}
}

function addDot(x,y,d) {
	if (x>=0 && y>=0 && x<=width && y<=height) {
		matrix[x][y] = d;
		matrix_lock[x][y]=true;
	}
}

function moveDot(x,y,nx,ny,typ,ntyp) {
	if (nx>=0 && ny>=0 && nx<=width && ny<=height && x>=0 && y>=0 && x<=width && y<=height) {
		matrix[x][y] = typ;
		matrix_lock[x][y] = typ!=null;
		matrix[nx][ny] = ntyp;
		matrix_lock[nx][ny] = true;
	}
}

function draw(x,y,d) {
	if (d==1) context.fillStyle = (Math.random()<0.5)?"#12d":"#12f";
	else if (d==2) context.fillStyle = (Math.random()<0.6)?"#b73":"#a82";
	else if (d==3) context.fillStyle = (Math.random()<0.5)?"#c41":"#f60";
	else if (d==4) context.fillStyle = (Math.random()<0.5)?"#bbd":"#bbb";
	else if (d==5) context.fillStyle = (Math.random()<0.7)?"#212":"#111";
	else if (d==10) context.fillStyle = (Math.random()<0.5)?"#0b0":"#0d0";
	else context.fillStyle = "rgba(0,0,0,0)";
	context.fillRect(dotw*x, doth*y, dotw, doth);
}


function update(){
	for (var y=height; y>=0; y--) {
		for (var x=0; x<=width; x++) {

			if (matrix_lock[x][y]==true) continue;

			var d = dot(x,y);
			if (d==0 || d==10) continue;
			if (y==height) killDot(x,y);
												
			// Water
			if (d==1) { 
				var dbc = dot(x,y+1);
				if (dbc==3) { moveDot(x,y,x,y+1,4,1);} // Fire and Water
				else if (dot(x+1,y)==3) { addDot(x,y,4);killDot(x+1,y);} // Fire and Water
				else if (dot(x-1,y)==3) { addDot(x,y,4);killDot(x-1,y);} // Fire and Water
				else if (dbc==0) {if (Math.random()<0.95) moveDot(x,y,x,y+1,null,1);}
				else if (Math.random()<0.1 && dot(x+1,y)==5) 	moveDot(x+1,y,x,y,1,5);  // oil on water
				else if (Math.random()<0.3 && dbc==5) 			moveDot(x,y,x,y+1,5,1);  // oil on water
				else if (Math.random()<0.1 && dot(x-1,y)==5) 	moveDot(x-1,y,x,y,1,5);  // oil on water
				else if (dbc>0) liquid(x,y,1);
						
			// Sand	
			} else if (d==2) {
				var dbc = dot(x,y+1);
				if (dbc==0) {if (Math.random()<0.9) moveDot(x,y,x,y+1,null,2);}
				else if (dbc==1) {if (Math.random()<0.6) moveDot(x,y,x,y+1,1,2);}  // Sand in Water
				else if (dbc==5) {if (Math.random()<0.3) moveDot(x,y,x,y+1,5,2);}  // Sand in Oil
				else if (dbc==3) killDot(x,y+1);  // Fire and Sand
				else if (Math.random()<0.01 && dot(x-1,y)==0) moveDot(x,y,x-1,y,null,2);
				else if (Math.random()<0.01 && dot(x+1,y)==0) moveDot(x,y,x+1,y,null,2);
				else if (dbc>0 && Math.random()<0.3 && dot(x+1,y+1)==0 && dot(x+1,y)==0) moveDot(x,y,x+1,y,null,2);
				else if (dbc>0 && Math.random()<0.3 && dot(x+1,y)==1) moveDot(x,y,x+1,y,1,2);   // Sand in Water
				else if (dbc>0 && Math.random()<0.3 && dot(x+1,y)==5) moveDot(x,y,x+1,y,5,2);   // Sand in Water
				else if (dbc>0 && Math.random()<0.3 && dot(x-1,y)==0 && dot(x-1,y+1)==0) moveDot(x,y,x-1,y,null,2); 
				else if (dbc>0 && Math.random()<0.3 && dot(x-1,y)==1) moveDot(x,y,x-1,y,1,2);
				else if (dbc>0 && Math.random()<0.3 && dot(x-1,y)==5) moveDot(x,y,x-1,y,5,2);
			
			// Fire	
			} else if (d==3) {
				var dbc = dot(x,y+1);
				var dtc = dot(x,y-1);
				if (dbc==0 && Math.random()<0.7) moveDot(x,y,x,y+1,null,3);
				else if (dbc==5 && Math.random()<0.5) addDot(x+1,y-1,3);  // Fire and Oil
				else if (dbc==5 && Math.random()<0.5) addDot(x-1,y-1,3);  // Fire and Oil
				else if (dbc==5) {addDot(x,y-8,3);addDot(x,y-6,3);}  // Fire and Oil
				else if ((dbc==0 || dbc==10) && Math.random()<0.02) addDot(x+1,y-1,3);
				else if ((dbc==0 || dbc==10) && Math.random()<0.02) addDot(x-1,y-1,3);
				else if (dbc==1) { killDot(x,y); killDot(x,y+1); addDot(x,y,4); } // Fire and Water
				else if (dbc==10 && Math.random()<0.004) killDot(x,y+1);   // Fire and Solid
				else if (dbc==3 && Math.random()<0.4) moveDot(x,y,x,y-2,null,3);
				else if (dtc==3 && dot(x,y-2)==3 && dot(x,y-3)==3) killDot(x,y);

			// Steam	
			} else if (d==4) {
				var dtc = dot(x,y-1);
				if (dtc!=10 && dtc!=4 && Math.random()<0.5) moveDot(x,y,x,y-1,dtc,4);
				else if (Math.random()<0.3 && dtc>0 && dot(x-1,y)==0 && dot(x-1,y+1)!=4) 	moveDot(x,y,x-1,y,null,4);
				else if (Math.random()<0.3 && dtc>0 && dot(x+1,y)==0 && dot(x+1,y+1)!=4) 	moveDot(x,y,x+1,y,null,4);
				else if (Math.random()<0.3 && dtc>0 && dot(x+2,y)==0 && dot(x+2,y+1)!=4) 	moveDot(x,y,x+2,y,null,4);
				else if (Math.random()<0.3 && dtc>0 && dot(x-2,y)==0 && dot(x-2,y+1)!=4) 	moveDot(x,y,x-2,y,null,4);
				if (Math.random()<0.01 || y<1) killDot(x,y);
				
			// Oil	
			} else if (d==5) {
				var dbc = dot(x,y+1);
				if (dbc==3 && Math.random()<0.2) moveDot(x,y,x,y+1,5,5);  // Fire and Oil
				else if (dbc==0) {if (Math.random()<0.7) moveDot(x,y,x,y+1,null,5);}
				else if (dbc==0 && Math.random()<0.05) addDot(x,y+1,5);
				else if (dbc>0) liquid(x,y,5);
			}

		}// for x
	}// for y
					
	for (var y=height; y>=0; y--) {
		for (var x=0; x<=width; x++) {
			var d = dot(x,y);
			if (d != matrix_old[x][y]) draw(x,y,d);
			matrix_old[x][y] = d;
			matrix_lock[x][y] = false;
		}
	}

}

function liquid(x,y,c) {
	var r1 = dot(x+1,y); var r2 = dot(x+2,y); var r3 = dot(x+3,y); 
	var l1 = dot(x-1,y); var l2 = dot(x-2,y); var l3 = dot(x-3,y); 
	var w = ((r1==c)?1:0) + ((r2==c)?1:0) + ((r3==c)?1:0) - ((l1==c)?1:0) - ((l2==c)?1:0) - ((l3==c)?1:0);
	if (w<=0 && Math.random()<0.5) {
		if (r1==0 && dot(x+1,y-1)!=c) moveDot(x,y,x+1,y,null,c);
		else if (r2==0 && dot(x+2,y-1)!=c) moveDot(x,y,x+2,y,null,c);
		else if (r3==0 && dot(x+3,y-1)!=c) moveDot(x,y,x+3,y,null,c);
	} else if (w>=0 && Math.random()<0.5) {
		if (l1==0 && dot(x-1,y-1)!=c) moveDot(x,y,x-1,y,null,c);
		else if (l2==0 && dot(x-2,y-1)!=c) moveDot(x,y,x-2,y,null,c);
		else if (l3==0 && dot(x-3,y-1)!=c) moveDot(x,y,x-3,y,null,c);
	}
}

function killFire() {
	for (var y=height; y>=0; y--) {
		for (var x=0; x<=width; x++) {
			if (dot(x,y)==3) addDot(x,y,4);
		}
	}
}

function spawnDragStart(e) {
	selectedFountainIdx = e.data.spawnId;
	canvas.live('mousemove', {s:this}, spawnDragMove);
	spawns[selectedFountainIdx].live('mouseup', spawnDragStop);
}

function spawnDragStop(e) {
	selectedFountainIdx = null;
	$(e.currentTarget).die('mouseup');
	canvas.die('mousemove');
}

function spawnDragMove(e) {
	var pos = mousePos(e);
	var spawn = e.data.s;
	spawns[selectedFountainIdx].css('left', pos.x*dotw-8);
	spawns[selectedFountainIdx].css('top', pos.y*doth-8);
	if (fountains[selectedFountainIdx]) {
		fountains[selectedFountainIdx].x = pos.x;
		fountains[selectedFountainIdx].y = pos.y+2;
	}
}

function mousePos(e) {
	return {x: Math.round((e.pageX-canvas.offset().left)/dotw), y: Math.round((e.pageY-canvas.offset().top)/doth) }
}

function spawnEvent(e) {
	if (selectedFountainIdx!=null) {
		canvas.live('mousemove', updateToMousePos);
	} else {
		var pos = mousePos(e);
		spawnDot(pos.x, pos.y);
		canvas.live('mousemove', paintEvent);
	}
}

function paintEvent(e) {
	var pos = mousePos(e);
	spawnDot(pos.x, pos.y);
}

function delEvent(e) {
	var pos = mousePos(e);
	for (var h=-2;h<2;h++) {
		for (var i=-2;i<2;i++) {
			killDot(pos.x+i, pos.y+h);
		}
	}
}

function updateToMousePos(e) {
	var pos = mousePos(e);
	if (fountains[selectedFountainIdx]) {
		fountains[selectedFountainIdx].x = pos.x+2;
		fountains[selectedFountainIdx].y = pos.y+2;
	}
}

function spawnDot(x,y) {
	if (brushtyp==10 || brushsize>2) {
		var b = (brushtyp==10)?4:brushsize;
		for (var i=0;i<=b;i++) {	
			for (var j=0;j<=b;j++) {
				if ((i==0 || i==b) && (j==0 || j==b)) continue;
				addDot(x-(b/2)+i, y-(b/2)+j, brushtyp);
			}
		}
	} else if (brushsize==2) {
		addDot(x, y, brushtyp);
		addDot(x+1, y, brushtyp);
	} else {
		addDot(x, y, brushtyp);
	}
}

function onCanvasLeave(e) {
	e.stopPropagation();
	var pos = mousePos(e);
	if (pos.x<=0 || pos.y<=0 || pos.x>=width || pos.y>=height ) {
		if(selectedFountainIdx!=null) {
			spawns[selectedFountainIdx].die('mousemove');
			spawnDragStop(e);
		}
		canvas.die('mousemove');
		selectedFountainIdx = null;
	}
}

function stopMouseMove(e) {
	canvas.die('mousemove');
}

function setSpawnFountain(x,y,t) {
	if (x>width || y>height) return;
	var fountain = {
		x: x, y: y,	typ: t
	}
	fountains.push(fountain);
}

function spawnFountain() {
	for (i=0; i<fountains.length; i++) {
		if (f=fountains[i]) {
			if (f.x>=0 && f.y>=0 && f.x<=width && f.y<=height) matrix[f.x][f.y] = f.typ;
		}
	}
}


