/**
 * @author Omer Gertel
 * All rights reserved
 */

function imageLoad(img, callback)
{
	var canvas = document.createElement("canvas");
	var pic = new Image();
			
	pic.src = img.src;
	$(pic).load(function()
	{	
		canvas.width = img.width;
		canvas.height = img.height;
		var ctx = canvas.getContext('2d');
		ctx.drawImage(pic, 0, 0, img.width, img.height);
		
		callback(img, ctx);
	});
}

jQuery.fn.mosaic = function(options)
{
	
	var settings = jQuery.extend({
        grainSize: 10,
        canvas:"canvas"
    }, options);
	
	return this.each(function()
		{
			function getColor(ctx, x, y, w, h) 
			{			
				var blockSize = 5;				
				var data =  ctx.getImageData(x,y ,w, h).data;
		
				var r_avg = 0, g_avg = 0, b_avg = 0;
			 
				//sum all channels values
				for (var i = 0; i < data.length; i += 4*blockSize	) 
				{
					r_avg += data[i];
			    	g_avg += data[i + 1];
			    	b_avg += data[i + 2];	   
				}
				 
				//calculate average color for each channel
				r_avg = Math.round(r_avg / (data.length / 4 / blockSize));
				g_avg = Math.round(g_avg / (data.length / 4 / blockSize));
				b_avg = Math.round(b_avg / (data.length / 4 / blockSize));
						
				res = {r:r_avg,g:g_avg,b:b_avg};
				return res;
	   		};
			
			function calcMosaic(ctx, w, h, grainSize)
			{
				var local = new Array();
				w = w / grainSize;
				h = h / grainSize;
				for(var i = 0; i < w; i++)
				{
					var width = grainSize;
					if (width + i*grainSize > ctx.canvas.width)
					{
						width = ctx.canvas.width - i*grainSize;
					}
					for(var j = 0; j < h ; j++)
					{
						var height = grainSize;
						if (height + j*grainSize > ctx.canvas.height)
						{
							height = ctx.canvas.height- j*grainSize;
						}
						local[~~(j*w + i)] = getColor(ctx, i*grainSize, j*grainSize, width, height);
					}
				}
				
				var total = {r:0,g:0,b:0};
				for(var i=0;i<local.length;i++)
				{
					total.r += local[i].r;
					total.g += local[i].g;
					total.b += local[i].b;
				}
				total.r  /= local.length;
				total.g  /= local.length;
				total.b  /= local.length;
									
				return {total:total, local:local};
			};
			
			imageLoad(this, function(img, data)
	    	{
	    		var w = img.width;
	    		var h = img.height;
	    		var grainSize = settings.grainSize;
	    		var res  = calcMosaic(data, w,h,grainSize);
	    		var workspace = $(settings.canvas)[0];
	    		workspace.width = w;
	    		workspace.height = h;
	    		var ctx = workspace.getContext("2d");
	    		
	    		w = w / grainSize;
				h = h / grainSize;
				for(var i = 0; i < w; i++)
				{
					for(var j = 0; j < h ; j++)
					{
						ctx.fillStyle="rgb("+res.local[~~(j*w + i)].r + "," +res.local[~~(j*w + i)].g + "," +res.local[~~(j*w + i)].b + ")";
						ctx.fillRect(i*grainSize, j*grainSize, grainSize, grainSize);
					}
				}			
	    	});
		});
}
