var game={
	scoreboard_size:10,
};

var scoring={
	'bbreaker':function(x) {return x*(x+1);}
};

jQuery.build=function(options) {
	$('#game').remove();

	game=$.extend({
		cookie_playername:'anti_samegame_playername',
		width:12,
		height:18,
		tileSize:32,
		colors:5,
		scoring:scoring.bbreaker,
		inplace:0,
	},game,options,{
		score:0,
		moves:0,
		allowClick:true
	});

	return $('<div>').id('game').mousedown(function() {return false;}).data('options',game).each(function() {
		$('<div>').id('score').html('Score: 0').add(
			$('<div>').id('table').css({
				width:game.width*game.tileSize,
				height:game.height*game.tileSize
			}).each(function() {
				for (x=0;x<game.width;x++) {
					var column=$('<div>').addClass('column').css({
						width:game.tileSize,
						height:game.tileSize*game.height
					});
					for (y=0;y<game.height;y++) {
						var c=rand(1,game.colors)-1;

						$('<div>').addClass('tile').css({
							width:game.tileSize,
							height:game.tileSize,
							top:y*game.tileSize,
							backgroundPosition:'0px -'+c*game.tileSize+'px'
						}).data('data',{
							x:x,
							y:y,
							c:c
						}).id('t'+x+'x'+y)
						.addClass('color'+c)
						.appendTo(column).click(function() {
							if (game.allowClick) {
								game.allowClick=false;
								$(this).getChain(function() {
									if ($('.matched').length>1) {
										$(this).addClass('clicked');
									}
									$.removeTiles();
								});
							}
						});

					}

					column.appendTo($(this));

				}

			})
		).appendTo($(this));

	}).appendTo($('#wrapper'));

}

jQuery.fn.id=function(newid) {
	return this.each(function() {
		$(this).attr('id',newid);
	});
}

jQuery.fn.getChain=function(callback) {
	game.inplace=0;
	var color=$(this).dataz().c;
	$(this).getNeighbours(color);

	if (callback) callback.call(this);

	return this;
}

jQuery.fn.getNeighbours=function(color) {
	// i don't know how to elegantly go about globals yet
	var data=$(this).dataz();
	var matched=$(this);

	if ($(this).parent().prev().length) matched=matched.add($.tile({x:data.x-1,y:data.y}));
	if (data.y>0) matched=matched.add($.tile({x:data.x,y:data.y-1}));
	if ($(this).parent().next().length) matched=matched.add($.tile({x:data.x+1,y:data.y}));
	if (data.y<game.height) matched=matched.add($.tile({x:data.x,y:data.y+1}));

 	matched=matched.not('.processed').filter('.color'+color);

 	if (matched.length) {
		matched.addClass('processed').addClass('matched').not(this).each(function() {
			$(this).getNeighbours(color);
		});
 	} else {
		return null;
	}
}

jQuery.removeTiles=function() {

	var m=$('.matched').removeClass('processed');
	var coords={
		x:$('#game .clicked').offset().left,
		y:$('#game .clicked').offset().top
	};

	var removed=0;
	if (m.length>1) {

		m.fadeOut(200,function() {
			removed++;
			$(this).remove();
			if (removed==m.length) {
				$.score(m.length,coords);
				$.drip();
			}
		});

	} else {
		m.removeClass('matched');
		game.allowClick=true;
	}
}

jQuery.collapseColumns=function() {

	var callback=function() {
		game.allowClick=true;
 		if ($.checkForMoves()) {
			$.gameEnd();
 		}
	}

	var c=$('.column:empty');
	var ctarget=c.length;
	if (ctarget==0 && callback) {callback.call();return false;}
	var ccollapsed=0;
	c.each(function() {
		if ($(this).children().length==0) {

			$(this).animate({
				width:0
			},200,'easeInQuart',function() {
				ccollapsed++;
				if (ccollapsed==ctarget) {
					if (callback) callback.call();
				};
				$(this).remove();
			});
		}
	});
}

jQuery.checkForMoves=function() {
	getBench(true);

	var c=$('.column');
	var mx=new Array(c.length);
	mx.height=0;
	c.each(function() {
		var h=$(this).children();
		if (h>mx.height) mx.height=h;
	});

	for (var x=0;x<c.length;x++) {
		mx[x]=new Array(mx.height);
	}
	var t=$('.tile');

	for (var i=0;i<t.length;i++) {
		var dataz=t.eq(i).dataz();
		mx[dataz.x][dataz.y]=dataz.c;
	}

	for (var x=0;x<mx.length;x++) {
		for (var y=0;y<mx[x].length;y++) {
			var t=mx[x][y];
			if (
				x+1<mx.length && mx[x+1][y]==t ||
				y+1<mx.height && mx[x][y+1]==t ||
				x>0 && mx[x-1][y]==t ||
				y>0 && mx[x][y-1]==t
			) {
				return false;
			}
		}
	}

	return true;
}

jQuery.drip=function() {
	if ($('.tile').length==0) {
		$.collapseColumns();
		return false;
	}

	for (var x=0;x<game.width;x++) {
		$.tile({x:x,y:0}).dribble();
	}
}

jQuery.fn.dribble=function() {

	var ind=$(this).nextAll().length;
	var rt=(game.height-ind-1)*game.tileSize;
	var fixed=((rt+'px')==$(this).css('top'));
	if (!fixed) {
		var tm=100+ind*30;
		$(this).animate({
			top:rt
		},tm<200?200:tm,'easeInOutSine',function() {
			game.inplace++;
			if (game.inplace==$('.tile').length) {$.collapseColumns();}
		});
	} else {
		game.inplace++;
		if (game.inplace==$('.tile').length) {$.collapseColumns();}
	}

	var p=$(this).prev();

	if (p.length) {
		p.dribble();
	} else {
		var column=$(this).parent();
		if (!column.children().length) column.remove();
	}

}

// OMG DATAZ
jQuery.fn.dataz=function() {
	return {
		x:$(this).parent().prevAll().length,
		y:$(this).nextAll().length,
		c:$(this).data('data').c
	};
}

jQuery.tile=function(coords) {
	var tile=$('.column').eq(coords.x).find('.tile').reverse().eq(coords.y).filter(':not(.processed)');
	return tile;
}

jQuery.score=function(offs,coords) {
	game.moves++;
	game.score=game.score+game.scoring(offs);
	$('#score').html('Score: '+game.score);
	Cufon.refresh();

	var f=$('<div class="floating">+'+game.scoring(offs)+'</div>').appendTo($('body')).css({
		left:coords.x-15,
		top:coords.y-20
	}).animate({
		opacity:0,
		marginTop:'-42px'
	},800,function() {
		$(this).remove();
	});
	Cufon.refresh();

}