var Dot = new Class({
	context: null,
	pos: {x: 0, y: 0},
	color: '#fff',
	scale: 0,
	size: 1,
	
	initialize: function( context, x, y, size ) {
		this.x = x;
		this.y = y;
		this.size = size;
		this.context = context;
	},
	
	draw: function() {
		var radius = this.scale * this.size;
		if( !isNaN(radius) ) {
			this.context.fillStyle = this.color;
			this.context.beginPath();
			this.context.arc( this.x, this.y, radius, 0, Math.PI*2, false ); 
			this.context.fill();
		}
	}
});


var DotField = new Class({
	dots: [[]],
	
	context: null,
	width: 320,
	height: 240,
	size: {x: 41, y: 31},
	scale: 1,
	rotation: 0,
	backgroundColor: '#000',
	
	initialize: function( context, width, height, sizeX, sizeY ) {
		this.context = context;
		this.width = width;
		this.height = height;
		this.size.x = sizeX;
		this.size.y = sizeY;
		
		var dotSize = width / this.size.x / 2;
		for( var x = 0; x < this.size.x; x++ ) {
			this.dots[x] = [];
			for( var y = 0; y < this.size.y; y++ ) {
				var pxX = x * dotSize * 2 + dotSize - this.width / 2;
				var pxY = y * dotSize * 2 + dotSize - this.height / 2;
				this.dots[x][y] = new Dot( this.context, pxX, pxY, dotSize );
			}
		}
	},
	
	draw: function() {
		this.context.save();
		
		this.context.fillStyle = this.backgroundColor;
		this.context.fillRect( 0, 0, this.width, this.height );
		
		this.context.translate( this.width/2, this.height/2 );
		this.context.scale( this.scale, this.scale );
		this.context.rotate( this.rotation );		
		
		for( var x = 0; x < this.size.x; x++ ) {
			for( var y = 0; y < this.size.y; y++ ) {
				this.dots[x][y].draw();
			}
		}
		
		this.context.restore()
	}
});



// Static functions to manipulate a dot
var FX = {
	// Set color and intensity. Defaults to white!
	color: function( dot, tick, x, y, amount, params ) {
		var base = 255 * (1-params.intensity);
		dot.color = 'rgb(' +
			Math.floor( params.r * params.intensity + base ) +','+
			Math.floor( params.g * params.intensity + base ) +','+
			Math.floor( params.b * params.intensity + base ) + ')';
	},

	// Scale by params.factor or absolute params.value
	scale: function( dot, tick, x, y, amount, params ) {
		if( params.factor ) {
			dot.scale = Math.abs( dot.scale * params.factor * amount );
		} 
		else {
			dot.scale = Math.abs( params.value * amount );
		}
	},
	
	// Cheesy plasma effect, based on position (x,y) and tick
	plasma: function( dot, tick, x, y, amount, params ) {
		var yt1 = Math.cos( y * 0.25 + tick * 0.5 );
		var yt2 = Math.cos( y * 0.5 - tick * 0.75 );
		var xt1 = Math.cos( x * 0.25 - tick * 0.5 );
		var xc1 = Math.cos( x * 0.66 + yt1 * 2 );
		var yc1 = Math.cos( y * 0.5 - xt1 *2 );

		var s = ( yt1 + yt2 + xt1 + xc1 + yc1 ) / 5;
		FX.scale( dot, tick, x, y, amount, { 'value': s } );
	}
};
