/*
http://www.lgm.cl/trabajos/tetris/tetris.js

This is an implementation of a Tetris clone in Javascript/XHTML/CSS.
Written by Luis Alejandro González Miranda - locoluis at gmail dot com.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/


field = [];
speed = 1;
piece = {};
points = 0;
lines = 0;
playing = false;
nextPiece = '';

var piezas = {
	'I' : {
		'0': { 'x': 0, 'y': 0},
		'1': { 'x': 1, 'y': 0},
		'2': { 'x': 2, 'y': 0},
		'3': { 'x':-1, 'y': 0}
	},
	'J' : {
		'0': { 'x': 0, 'y': 0},
		'1': { 'x': 1, 'y': 0},
		'2': { 'x':-1, 'y':-1},
		'3': { 'x':-1, 'y': 0}
	},
	'L' : {
		'0': { 'x': 0, 'y': 0},
		'1': { 'x': 1, 'y': 0},
		'2': { 'x':-1, 'y': 1},
		'3': { 'x':-1, 'y': 0}
	},
	'O' : {
		'0': { 'x': 0, 'y': 0},
		'1': { 'x': 1, 'y': 0},
		'2': { 'x': 0, 'y':-1},
		'3': { 'x': 1, 'y':-1}
	},
	'S' : {
		'0': { 'x': 0, 'y': 0},
		'1': { 'x': 1, 'y': 0},
		'2': { 'x': 0, 'y': 1},
		'3': { 'x':-1, 'y': 1}
	},
	'T' : {
		'0': { 'x': 0, 'y': 0},
		'1': { 'x': 1, 'y': 0},
		'2': { 'x': 0, 'y': 1},
		'3': { 'x': 0, 'y':-1}
	},
	'Z' : {
		'0': { 'x': 0, 'y': 0},
		'1': { 'x': 1, 'y': 0},
		'2': { 'x': 0, 'y':-1},
		'3': { 'x':-1, 'y':-1}
	}
};

function newPiece()
{
	var rnd = ['I','J','L','O','S','T','Z'];
	var p = nextPiece; 
	if(p == '') {
		p = rnd[Math.floor(7 * Math.random())];
	}
	nextPiece = rnd[Math.floor(7 * Math.random())];
	var s = piezas[p];
	piece = {};
	piece.color = p;
	if(typeof s == 'undefined') {
		alert(p);
	}
	for(var i = 0; i < 4; i++) {
		piece[i] = {
		'x': s[i].x + 5,
		'y': s[i].y + 1
		};
	}
	for(var i = 0; i < 4; i++) {
		for(var j = 0; j < 4; j++) {
			$('nxt' + i + '_' + j).className = 'B';
		}
	}
	for(var i = 0; i < 4; i++) {
		var x = piezas[nextPiece][i].x + 1;
		var y = piezas[nextPiece][i].y + 1;
		var z = $('nxt' + y + '_' + x);
		if(!z) {
			alert(nextPiece);
			alert('nxt' + y + '_' + x);
			return false;
		}
		z.className = nextPiece;
	}
	refreshScreen();
	for(var i = 0; i < 4; i++) {
		if(field[piece[i].y][piece[i].x] != 'B') {
			$('debug').innerHTML = "FAIL";
			return false;
		}
	}
	return true;
}

function rotate(p, dir)
{
	removePiece();
	var q = new Array();
	for(var i = 1; i < 4; i++) {
		q[i] = {};
		q[i].y = p[i].y;
		q[i].x = p[i].x;
	}
	moveOkay = true;
	for(var i = 1; i < 4; i++) {
		var x = p[i].y - p[0].y;
		var y = p[i].x - p[0].x;
		if(dir) {
			x = -x;
		} else {
			y = -y;
		}
		p[i].y = y + p[0].y;
		p[i].x = x + p[0].x;
		if(
		   ((p[i].y < 0) || (p[i].y > 19))
		|| ((p[i].x < 0) || (p[i].x > 9))
		|| (field[p[i].y][p[i].x] != 'B')
		) {
			moveOkay = false;
		}
	}
	if(!moveOkay) {
		for(var i = 1; i < 4; i++) {
			p[i].y = q[i].y;
			p[i].x = q[i].x;
		}
	}
	showPiece();
}
function tetris()
{
	var lines = 0;
	for(var i = 19; i >= 0; i--) {
		var okay = true;
		for(var j = 0; j < 10; j++) {
			if(field[i][j] == 'B') {
				okay = false;
				break;
			}
		}
		if(okay) {
			for(var k = i; k > 0; k--) {
				for(var j = 0; j < 10; j++) {
					field[k][j] = field[k - 1][j];
				}
			}
			for(var j = 0; j < 10; j++) {
				field[0][j] = 'B';
			}
			i++;
			lines++;
		}
	}
	return lines;
}

function handleKeys(e)
{
	if(e == undefined) e = window.event;
	if(e == undefined) return;
	if(window.event) {
		keynum = e.keyCode;
	} else if(e.which) {
		keynum = e.which;
	}
	if(keynum == undefined) return;
	if(keynum == 0) {
		keynum = e.charCode;
	}

	if(!playing) {
		switch(keynum) {
		case 80:
		case 112:
		case 32:
			playing = true;
			$('debug').innerHTML = '';
			break;
		default:
			//$('debug').innerHTML = keynum;
		}
		return;
	}
	switch(keynum) {
	case Event.KEY_UP:
	case 38:
		rotate(piece, true);
		break;
	case Event.KEY_LEFT:
	case 37:
		movePiece(-1, 0);
		break;
	case Event.KEY_RIGHT:
	case 39:
		movePiece(1, 0);
		break;
	case Event.KEY_DOWN:
	case 40:
		while(movePiece(0, 1)) {
		}
		break;
	case 87:
	case 119:
		rotate(piece, true);
		break;
	case 65:
	case 97:
		movePiece(-1, 0);
		break;
	case 68:
	case 100:
		movePiece(1, 0);
		break;
	case 83:
	case 115:
		while(movePiece(0, 1)) {
		}
		break;
	case 80:
	case 112:
	case 32:
		playing = false;
		$('debug').innerHTML = 'Paused';
		break;
	default:
		$('debug').innerHTML = keynum;
	}
	refreshScreen();
}

function init()
{
	window.focus();
	var d = $('playfield');
	field = new Array();
	for(var i = 0; i < 20; i++) {
		var l = new Element('div', {'class': 'line'});
		field[i] = new Array();
		for(var j = 0; j < 10; j++) {
			var b = new Element('div', {
				'id': 'b' + i + '_' + j,
				'class': 'B'
			});
			l.appendChild(b);
			field[i][j] = 'B';
		}
		d.appendChild(l);
	}
	d = $('nextfield');
	for(var i = 0; i < 4; i++) {
		var l = new Element('div', {'class': 'line'});
		for(var j = 0; j < 4; j++) {
			var b = new Element('div', {
				'id': 'nxt' + i + '_' + j,
				'class': 'B'
			});
			l.appendChild(b);
		}
		d.appendChild(l);
	}
	newPiece();
	playing = true;
	// Event.observe(window, 'keydown', handleKeys);
	if(navigator.appName != "Mozilla"){
		// document.onkeyup = pongkup;
		document.onkeydown = handleKeys;
	} else{
		document.addEventListener("keypress", handleKeys, true);
		// document.addEventListener("keyrelease", pongkup, true);
	}
	setTimeout('tick();', 1000 / (speed + 1));
}

function removePiece()
{
	for(var i = 0; i < 4; i++) {
		field[piece[i].y][piece[i].x] = 'B';
	}
}
function showPiece()
{
	var i;
	for(i = 0; i < 4; i++) {
		field[piece[i].y][piece[i].x] = piece.color;
	}
}
function movePiece(ox, oy)
{
	removePiece();
	var moveOkay = true;
	var q = new Array();
	for(var i = 0; i < 4; i++) {
		q[i] = {};
		q[i].y = piece[i].y;
		q[i].x = piece[i].x;
	}
	for(var i = 0; i < 4; i++) {
		piece[i].x += ox;
		piece[i].y += oy;
		if((piece[i].x < 0) || (piece[i].x > 9) || piece[i].y > 19) {
			moveOkay = false;
			break;
		}
		if(field[piece[i].y][piece[i].x] != 'B') {
			moveOkay = false;
			break;
		}
	}
	if(!moveOkay) {
		//mostrar(piece);
		for(var i = 0; i < 4; i++) {
			piece[i].y = q[i].y;
			piece[i].x = q[i].x;
		}
		//mostrar(piece);
	}
	showPiece();
	return moveOkay;
}
function mostrar(x)
{
	var s = '';
	for(var i = 0; i < 4; i++) {
		s += x[i].x + ', ' + x[i].y + "\n";
	}
	s += x.color;
	alert(s);
}
function campo(x)
{
	var s = '';
	for(var i = 0; i < 20; i++) {
		for(var j = 0; j < 10; j++) {
			s += x[i][j] + ' ';
		}
		s += "\n";
	}
	alert(s);
}
var pointTable = [0, 100, 300, 600, 1200, 1200, 1200];
function tick()
{
	if(playing) {
		var f = movePiece(0, 1);
		if(!f) {
			var t = tetris();
			lines += t;
			points += pointTable[t];
			if(Math.floor(lines / 10) > speed) {
				speed++;
			}
			playing = newPiece();
		}
		refreshScreen();
	}
	setTimeout('tick();', 1000 / (speed + 1));
}
function refreshScreen()
{
	for(var i = 0; i < 20; i++) {
		for(var j = 0; j < 10; j++) {
			$('b' + i + '_' + j).className = field[i][j];
		}
	}
	$('lines').innerHTML = lines;
	$('points').innerHTML = points;
	$('speed').innerHTML = speed;
}
Event.observe(window, 'load', init);
