(function(window) {

var PJS = undefined;
var PC = undefined;

var CANVAS = undefined;
var CONTAINER = undefined;

/**
 * Sketch - Create a new processing sketch.
 * 
 * Sketch Events: 
 *
 * onLoad - parsing/preloading is done, before sketch starts
 * onSetup - setup() has been called, before first draw()
 * onPause - noLoop() has been called, pausing draw loop
 * onLoop - loop() has been called, resuming draw loop
 * onFrameStart - draw() loop about to begin
 * onFrameEnd - draw() loop finished
 * onExit - exit() done being called
 */
var P5 = function( icontainer ) {
	var that = this,
		p = undefined,
		
		sketch = undefined;
	
	CONTAINER = document.getElementById( icontainer ) || null

	var gui = undefined,

		width = 0,
		height = 0,

		r = 0,
		g = 0,
		b = 0,

		// Number of rectangles to draw.
		NUM_OF_RECTS = 8,

		rWidth = 64,
		rHeight = 64,

		// Accumulate the rotation.
		rotation = 0,

		// Clear canvas or not.
		clearCanvas = true,

		// Rotation speed.
		speed = 2,
		
		// Accumulate the RGB color.
		r = 0,
		g = 0,
		b = 0;

//------------------------------------------------------------------------------
// Public Methods

	/**
	 * Initialize.
	 */
	that.initialize = function() {
		if ( !Processing ) {

			console.log("We cannot found the Processing lib.");

		} else {

			createAndAppendCanvas();
			
			// Create a new sketch.
			sketch = new Processing.Sketch();
			// Register callbacks.
			sketch.onLoad 		= onLoad;
			sketch.onSetup		= onSetup;
			sketch.onPause		= onPause;
			sketch.onLoop		= onLoop;
			sketch.onFrameStart	= onFrameStart;
			sketch.onFrameEnd	= onFrameEnd;
			sketch.onExit		= onExit;
			// Register the starter function.
			sketch.attachFunction = run;

			p = new Processing( CANVAS , sketch );
			
		}

	};

	/**
	 * Exit from the actual this processing, 
	 * and disponse all other objects.
	 */
	this.disponse = function() {
		p.exit();
		p = null;
	};

//
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Private Methods
	
	function createAndAppendCanvas() {
		CANVAS = document.createElement( "canvas" );
		CANVAS.id = "prototype5-canvas";

		CONTAINER.appendChild( CANVAS );
	};

	/**
	 * Set the canvas size.
	 */
	function setCanvasSize() {
		$( CANVAS ).css({ 
			"width" : width,
			"height" : height
		});
	};
	
	/**
	 * Run the app.
	 */
	function run(p) {
		// Set processing stuffs.
		PJS = p;
		PC  = p.PConstants;

		setCanvasSize();

		width  = $( CONTAINER ).width();
		height = $( CONTAINER ).height();

		PJS.setup = setup;
		PJS.draw  = draw;
	};

//
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Processing

	function setup() {
		PJS.size( width , height );

		PJS.background( 255 );
		PJS.frameRate( 24 );
		PJS.smooth();
		PJS.noStroke();
	};

	function draw() {

		if (clearCanvas) {
			PJS.fill(255, 255, 255, 50);
			PJS.rect( 0 , 0 , width , height );
		}

		var tx = PJS.mouseX <= 0 ? width / 2 : PJS.mouseX;
		var ty = PJS.mouseY <= 0 ? height / 2 : PJS.mouseY;

		// Tranlate the world to the center.
		PJS.translate( tx , ty );

		// rotate the entire world.
		PJS.rotate( rotation * Math.PI/ 180 );
		
		for (var i = 0; i < NUM_OF_RECTS; i += 1) {

			r += PC.HALF_PI / 60;
  			g += PC.QUARTER_PI / 50;
  			b += PC.HALF_PI / 40;

    		PJS.fill( 120 + Math.sin( PC.HALF_PI * r ) * 130 , 
    				  110 + Math.sin( PC.THIRD_PI * g ) * 140 , 
    				  100 + Math.sin( PC.QUARTER_PI * b ) * 150 , 
		    		  180 );			
			
			rotation += speed;
			
			PJS.rotate( (i+360/NUM_OF_RECTS) * Math.PI/ 180 );
			
			PJS.rect( -80 , 0 , rWidth , rHeight );
		}

	};

//
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
// Events Handlers

	/**
	 * onLoad - parsing/preloading is done, before sketch starts
	 */
	function onLoad() {
		console.log("Prototype5::onLoad");
	};

	/**
	 * onSetup - setup() has been called, before first draw()
	 */
	function onSetup() {
		console.log("Prototype5::onSetup");

		$( "#NOR" ).bind("change", function( event ){
			NUM_OF_RECTS = event.target.value;
		});

		$( "#SPEED" ).bind("change", function( event ){
			speed = parseFloat(event.target.value);
		});

		$( "#CLEAR" ).bind("change", function( event ){
			clearCanvas = document.getElementById( "CLEAR" ).checked;
		});

		$( "#RW" ).bind("change", function( event ){
			rWidth = event.target.value;
		});

		$( "#RH" ).bind("change", function( event ){
			rHeight = event.target.value;
		});
	};

	/**
	 * onPause - noLoop() has been called, pausing draw loop
	 */
	function onPause() {
		console.log("Prototype5::onPause");
	};

	/**
	 * onLoop - loop() has been called, resuming draw loop
	 */
	function onLoop() {
		//console.log("Prototype5::onLoop");
	};

	/**
	 * onFrameStart - draw() loop about to begin
	 */
	function onFrameStart() {
		//console.log("Prototype5::onFrameStart");
	};

	/**
	 * onFrameEnd - draw() loop finished
	 */
	function onFrameEnd() {
		//console.log("Prototype5::onFrameEnd");
	};

	/**
	 * onExit - exit() done being called
	 */
	function onExit() {
		console.log("Prototype5::onExit");
	};

//
//------------------------------------------------------------------------------

};

window.P5 = P5;

})(window);
