/**
 *  Author: Think Interactive
 *  Site: http://www.thinkinc.com
 *  
 *  Some physics code borrowed from Keith Peters. 
 *  Site: http://www.bit-101.com
 * 
 */
var THINKINC = THINKINC || {};

THINKINC.Confetti = new function() {

	var DOCUMENT = document,
		WINDOW = window,
		CANVAS,
		CONTEXT,
		$c, $f,
		maxWidth,
		maxHeight,
		confetti = [],
		args = {};
		maxBalls = 44,
		minRadius = 1,
		maxRadius = 5,
		spring = 0.05,
		bounce = -.5,
		gravity = .1,
		friction = 1;
	
	//
	this.init = function(canvas, feed) {
		
		$f = $(feed);
		$f.bind('feedBarAnimate', handleAnimateEvent);			
		
		$c = $(canvas);
		
		CANVAS = $c.get(0);//DOCUMENT.getElementById(canvas);
		CANVAS.width = 700;
		CANVAS.height = WINDOW.innerHeight - 68;
		CONTEXT = CANVAS.getContext('2d');
		
		if($f.css("display") === "none") {
			maxWidth = CANVAS.width;
		} else {
			maxWidth = CANVAS.width - $f.closest('aside').width();
		}
		
		maxHeight = CANVAS.height;
	
		while(maxBalls--) {
			var b = new Ball(CONTEXT, CANVAS.width, rand(1,maxHeight), rand(minRadius, maxRadius));
			confetti.push(b);
			b.draw();
		}
		update();
	}
	
	function handleAnimateEvent(event, isOpen) {
		if(isOpen) {
			collapse();
		} else {
			expand();
		}	
	}
	
	function expand(){
		setTimeout(function(){ maxWidth -= $f.width(); }, 500);
		var i = confetti.length;
		while(i--) {
			confetti[i].blow();	
		}
	}
	function collapse(){
		maxWidth += $f.width();
		var i = confetti.length;
		while(i--) {
			confetti[i].fall();	
		}
	}

	function update() {
		//
		requestAnimFrame(update);
		// clear the canvas context to prep for redraw
		CONTEXT.clearRect(0,0,CANVAS.width,CANVAS.height);
		//
		var numBalls = confetti.length;
		// collision test
		for(var i = 0; i < numBalls - 1; i++) {
			var ball0 = confetti[i];
			for(var j = i + 1; j < numBalls; j++) {
				var ball1 = confetti[j];
				checkCollision(ball0, ball1);
			}
		}
		// move balls
		while(numBalls--) {
			confetti[numBalls].updatePosition();
		}
	}
	
	function checkCollision(b0, b1) {
	   var dx = b1.x - b0.x,
		   dy = b1.y - b0.y,
		   dist = Math.sqrt(dx*dx + dy*dy),
		   minDist = b0.radius + b1.radius;	
		
		if(dist < minDist) {	 
			var angle = Math.atan2(dy, dx),
				tx = b0.x + dx / dist * minDist,
				ty = b0.y + dy / dist * minDist,
				ax = (tx - b1.x),// * spring,
				ay = (ty - b1.y);// * spring;
	
			b0.vx -= ax;
			b0.vy -= ay;
			b1.vx += ax;
			b1.vy += ay;	
		}	
	}
	
	// Ball Base Class
	function Ball(context, x, y, radius) {
		this.context = context;
		this.x = x;
		this.y = y;
		this.radius = radius;
		this.mass = this.radius;
		this.vx = rand(-3, -1);
		this.vy = rand(-2, 2);
		this.ovx = this.vx;
		this.ovy = this.vy;
		this.color = getColor();	
	}
	Ball.prototype.draw = function() {
			this.context.fillStyle = this.color;
			this.context.beginPath();
			this.context.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
			this.context.closePath();
			this.context.fill();				
	};
	Ball.prototype.fall = function() {
		bounce = -.5;
		gravity = .2;
		setTimeout(function(){gravity = .1}, 1500); 
	};
	Ball.prototype.blow = function() {
		bounce = -.5;
		gravity = .2;
		this.vx = rand(-13,-12);
		this.vy = rand(-2, 2);
		setTimeout(function(){gravity = .1}, 2000); 
	};
	Ball.prototype.updatePosition = function() {	
			//this.vy *= friction;
			this.vx += gravity;
			this.x += this.vx;
			this.y += this.vy;
			
			// check boundaries
			if(this.x + this.radius >= maxWidth) {
				this.x = maxWidth - this.radius;
				this.vx *= bounce;
				if(this.vx > -2)
				{
					this.vx = this.ovx * 1.1;	
				}
			}
			else if(this.x - this.radius <= 0) {
				this.x = this.radius;
				this.vx *= bounce;
			}
			if(this.y + this.radius >= maxHeight) {
				this.y = maxHeight - this.radius;
				this.vy *= bounce;
			}
			else if(this.y - this.radius <= 0) {
				this.y = this.radius;
				this.vy *= bounce;	
			}
			// redraw dot
			try{
				this.context.fillStyle = this.color;
				this.context.beginPath();
				this.context.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false);
				this.context.closePath();
				this.context.fill();
			} catch(e){
				
			}
			
	};

	/**
	 * Returns a random integer between min and max
	 */  
	function rand(min, max) { 
		return Math.floor(Math.random() * (max - min + 1)) + min;	
	}
	 
	/**
	 * Returns a random color from the color palatte
	 */	
	function getColor() {
		var colors = ['rgb(0,103,171)', 'rgb(226,46,38)', 'rgb(117,121,123)', 'rgb(255,217,69)'];
		return colors[Math.floor(Math.random() * 4)];
	}
	
	WINDOW.onresize = function() {
		CANVAS.height = WINDOW.innerHeight - 68;
		maxHeight = CANVAS.height;	
	}
	
}

/**
 * requestAnim shim layer by Paul Irish
 * http://www.paulirish.com
 * This method stops animation when tab is inactive
 * Saves cpu, gpu and memory usage =)
 */
window.requestAnimFrame = (function() {
	return window.requestAnimationFrame       || 
		   window.webkitRequestAnimationFrame || 
		   window.mozRequestAnimationFrame    || 
		   window.oRequestAnimationFrame      || 
		   window.msRequestAnimationFrame     || 
		   function(callback,element) {
		   	   window.setTimeout(callback, 1000 / 60);
		   };
})();

window.cancelRequestAnimFrame = (function() {
    return window.cancelAnimationFrame              ||
       	   window.webkitCancelRequestAnimationFrame ||
           window.mozCancelRequestAnimationFrame    ||
           window.oCancelRequestAnimationFrame      ||
           window.msCancelRequestAnimationFrame     ||
           clearTimeout
})();
