(function(window){

function ParticleStage(){
	this.initialize.apply(this,arguments);
}
var p = ParticleStage.prototype;
	p.particleAry = [];
	p.firstParticle = null;
	p.gravityX = 0;
	p.gravityY = 5;
	p.gravityZ = 0;
	p.canvasElement = null;
	p.context = null;
	p.stageWidth = 0;
	p.stageHeight =0;
	p.frameRate = 0;
	p.updateTimerId = 0;
	p.mode = "";
	p.faceImage = null;
	p.scrollY = 0;
	p.isActive = true;
	p.orientation = 0;
	p.completeCallback = null;

	p.initialize = function(canvasElement,number){
		if(typeof canvasElement.getContext == "undefined" || !canvasElement.getContext) {
			this.changeMode = this.active = function(){};
			return;
		}
		this.canvasElement = canvasElement;
		this.context = this.canvasElement.getContext('2d');
		this.frameRate = 33;
		this.createParticles(number);
		this.attachEventListener(window,"devicemotion",this.onDeviceMotion);
		this.attachEventListener(window,"resize",this.onResize);
		var that = this;
		window.onorientationchange = function () {
			 that.orientation = window.orientation;
		}
		this.orientation = window.orientation;
		this.onResize();
		this.context.globalAlpha = 0;
		this.changeMode("STOP");
		this.draw();

		this.faceImage = document.createElement('img');
		this.faceImage.setAttribute('src','img/noimage.jpg');
	}
	p.onResize = function(){
		var size = getWindowSize();
		this.canvasElement.width = size.width;
		this.canvasElement.height = size.height;
		this.stageWidth = size.width;
		this.stageHeight = size.height;
		this.context = this.canvasElement.getContext('2d');
	}
	p.attachEventListener = function(target,eventName,func){
		var self = this;
		if(target.addEventListener) target.addEventListener(eventName,function(e){func.call(self,e);},false);
		else target.attachEvent("on" + eventName,function(e){func.call(self,e);});
	}
	p.createParticles = function(num){
		for(var i = 0; i<num;i++)
		{
			var particle = new Particle(this);
			this.particleAry.push(particle);
			if(i > 0) particle.next = this.particleAry[i-1];
		}
		this.firstParticle = this.particleAry[num-1];
	}
	p.onDeviceMotion = function(e){
		var gravity = e.accelerationIncludingGravity;
		if(this.orientation == 0)
		{
			this.gravityX = gravity.x;
			this.gravityY = -gravity.y;
		}
		else if(this.orientation == 90)
		{
			this.gravityX = -gravity.y ;
			this.gravityY = -gravity.x;
		}
		else if(this.orientation == 180)
		{
			this.gravityX = -gravity.x;
			this.gravityY = gravity.y;
		}
		else if(this.orientation == -90)
		{
			this.gravityX = gravity.y ;
			this.gravityY = gravity.x;
		}
	}
	p.onScroll = function(value,valueDelta){
		this.scrollY = value;
		var particle = this.firstParticle;
		while(particle)
		{
			particle.y -= valueDelta;
			particle = particle.next;
		}
	}
	p.draw = function(){
		this.context.save();
		this.context.clearRect(0,0,this.stageWidth,this.stageHeight);
		var particle = this.firstParticle;
		while(particle)
		{
			this.update(particle);
			this.context.drawImage(particle.canvas, particle.x, particle.y);
			particle = particle.next;
		}
		this.context.restore();
		var self = this;
		this.updateTimerId = setTimeout(function(){self.draw.apply(self);},1000/this.frameRate);
	}
	p.active = function(bool){
		if(!bool && this.isActive)
		{
			clearTimeout(this.updateTimerId);
			this.canvasElement.style.width = "0px";
			this.isActive = false;
		}
		else if(bool && !this.isActive)
		{
			this.canvasElement.style.width = "100%";
			this.draw();
			this.isActive = true;
		}
	}
	p.setFaceImage = function(imageElement){
		this.faceImage = imageElement;
	}
	p.changeMode = function(modeName,value){
		var particle;
		if(modeName == "STOP" && this.mode!="STOP"){
			this.update = function(particle){}
			this.mode = modeName;
		}
		if(modeName == "SHOW" && this.mode!="SHOW"){
			particle = this.firstParticle;
			this.context.globalAlpha = 0;
			while(particle)
			{
				particle.alpha = 0;
				particle.fromX = (this.stageWidth - particle.size/2) * Math.random();
				particle.fromY = 440 - particle.size/2;
				particle.toX = particle.fromX + Math.random()*200 - 100;
				particle.toY = particle.fromY;
				particle.time = 4;
				particle.startTime = new Date().getTime() + Math.random()*2000;
				particle = particle.next;
			}
			this.easing = function(t, b, c, d ) {
				if ((t /= d / 2) < 1) { return c / 2 * t * t * t * t * t + b; } return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
			}
			this.update = function(particle){
				var currentTime = (new Date().getTime() - particle.startTime)/1000;
				if(currentTime < particle.time ) {
					particle.alpha = this.easing(currentTime,0,1,particle.time);
					particle.x = this.easing(currentTime,particle.fromX,particle.toX-particle.fromX,particle.time);
					particle.y = this.easing(currentTime,particle.fromY,particle.toY-particle.fromY,particle.time);
				}
				else{
					particle.alpha = 1;
					particle.x = particle.toX;
					particle.y = particle.toY;
				}
				this.context.globalAlpha = particle.alpha;
			}
			this.mode = modeName;
		}
		if(modeName == "BREAK" && this.mode!="BREAK"){
			this.context.globalAlpha = 1;
			particle = this.firstParticle;
			while(particle)
			{
				particle.fromX = particle.x;
				particle.fromY = particle.y;
				particle.toX = (this.stageWidth - particle.size) * Math.random();
				particle.toY = (this.stageHeight - particle.size) * Math.random();
				particle.time = 1.2;
				particle.startTime = new Date().getTime();
				particle = particle.next;
			}
			this.easing = function(t, b, c, d ) {
				 var s = 5; return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
			}
			this.update = function(particle){
				var currentTime = (new Date().getTime() - particle.startTime)/1000;
				if(currentTime < particle.time ) {
					particle.x = this.easing(currentTime,particle.fromX,particle.toX-particle.fromX,particle.time);
					particle.y = this.easing(currentTime,particle.fromY,particle.toY-particle.fromY,particle.time);
				}
				else{
					particle.x = particle.toX;
					particle.y = particle.toY;
				}
			}
			this.mode = modeName;
		}
		if(modeName == "FREE" && this.mode!="FREE"){
			this.context.globalAlpha = 1;
			particle = this.firstParticle;
			while(particle)
			{
				particle.vx = value* Math.random() - value/2;
				particle.vy = value* Math.random() - value/2;
				particle = particle.next;
			}
			this.update = function(particle){
				particle.vx += 0.01 - 0.02*Math.random();
				particle.x += particle.vx;
				particle.vy += 0.01 - 0.02*Math.random();
				particle.y += particle.vy;
				if(particle.x < 0 ) {particle.x = 0; particle.vx = -particle.vx*particle.k*(0.95 + 0.05*Math.random());}
				if(particle.y < 0 ) {particle.y = 0; particle.vy = -particle.vy*particle.k*(0.95 + 0.05*Math.random());}
				if(particle.x + particle.size > this.stageWidth ) {particle.x = this.stageWidth - particle.size; particle.vx = -particle.vx*particle.k*(0.8 + 0.4*Math.random());}
				if(particle.y + particle.size > this.stageHeight ) {particle.y = this.stageHeight - particle.size; particle.vy = -particle.vy*particle.k*(0.8 + 0.4*Math.random());}

				if(this.scrollY < 4000){
					var borderline1 = 4/11 * (particle.x - this.stageWidth/2) - particle.size +1457 - this.scrollY;
					if(particle.y > borderline1) {
						if(particle.vx < 0) particle.vy = 0;
						particle.y = borderline1;
						particle.vy = -particle.vy*particle.k*(0.95 + 0.05*Math.random());
						particle.vx+=0.1;
					}
					var borderline2 = -3 * (particle.x - this.stageWidth/2) - particle.size +2785 - this.scrollY;
					if(particle.y > borderline2) {
						if(particle.vx > 0) particle.vx = 0;
						particle.y = borderline2;
						particle.vy = -particle.vy*particle.k*(0.95 + 0.05*Math.random());
						particle.vx-=0.2;
					}
				}
			}
			this.mode = modeName;
		}
		if(modeName == "GRAVITY" && this.mode!="GRAVITY"){
			this.context.globalAlpha = 1;
			this.update = function(particle){
				particle.vx += this.gravityX * (0.5 + 0.5*Math.random());
				particle.x += particle.vx;
				particle.vy += this.gravityY * (0.5 + 0.5*Math.random());
				particle.y += particle.vy;
				if(particle.x < 0 ) {
					particle.x = 0;
					particle.vx = -particle.vx*particle.k*(0.95 + 0.05*Math.random());
				}
				if(particle.y < 0 ) {
					particle.y = 0;
					particle.vy = -particle.vy*particle.k*(0.95 + 0.05*Math.random());
				}
				if(particle.x + particle.size > this.stageWidth ) {
					particle.x = this.stageWidth - particle.size;
					particle.vx = -particle.vx*particle.k*(0.8 + 0.4*Math.random());
				}
				if(particle.y + particle.size > this.stageHeight ) {
					particle.y = this.stageHeight - particle.size;
					particle.vy = -particle.vy*particle.k*(0.8 + 0.4*Math.random());
					particle.vx *= 0.95;
				}

				var borderline1 = 4/11 * (particle.x - this.stageWidth/2) - particle.size +1457 - this.scrollY;
				if(particle.y > borderline1) {
					if(particle.vx < 0) particle.vy = 0;
					particle.y = borderline1;
					particle.vy = -particle.vy*particle.k*(0.95 + 0.05*Math.random());
					particle.vx+=0.1;
				}
				var borderline2 = -3 * (particle.x - this.stageWidth/2) - particle.size +2785 - this.scrollY;
				if(particle.y > borderline2) {
					if(particle.vx > 0) particle.vx = 0;
					particle.y = borderline2;
					particle.vy = -particle.vy*particle.k*(0.95 + 0.05*Math.random());
					particle.vx-=0.2;
				}
			}
			this.mode = modeName;
		}
		if(modeName == "DOWNOUT" && this.mode!="DOWNOUT"){
			this.context.globalAlpha = 1;
			this.update = function(particle){
				particle.vx += this.gravityX * (0.5 + 0.5*Math.random());
				particle.x += particle.vx;
				particle.vy += this.gravityY * (0.5 + 0.5*Math.random());
				particle.y += particle.vy;
			
			}
			this.mode = modeName;
		}
		if(modeName == "UPIN" && this.mode!="UPIN"){
			this.context.globalAlpha = 1;
			particle = this.firstParticle;
			while(particle)
			{
				particle.y = this.stageHeight;
				particle.vy = -5*Math.random();
				particle = particle.next;
			}
			this.mode = modeName;
		}
		else if(modeName == "RANDOM" && this.mode!="RANDOM"){
			this.update = function(particle){
				particle.vx += Math.random() - 0.5;
				particle.vy += Math.random() - 0.5;
				particle.x += particle.vx;
				particle.y += particle.vy;
				if(particle.x < 0 ) {particle.x = 0; particle.vx = -particle.vx*particle.k*(0.95 + 0.05*Math.random());}
				if(particle.y < 0 ) {particle.y = 0; particle.vy = -particle.vy*particle.k*(0.95 + 0.05*Math.random());}
				if(particle.x + particle.size > this.stageWidth ) {particle.x = this.stageWidth - particle.size; particle.vx = -particle.vx*particle.k*(0.8 + 0.4*Math.random());}
				if(particle.y + particle.size > this.stageHeight ) {particle.y = this.stageHeight - particle.size; particle.vy = -particle.vy*particle.k*(0.8 + 0.4*Math.random());}
			}
			this.mode = modeName;
		}
		else if(modeName == "FACE" && this.mode!="FACE"){
			this.context.globalAlpha = 1;
			var imageAry = imageToAry(this.faceImage);
			var width = this.faceImage.width;
			var counter = 0;
			var size = 10;
			var step = 5;
			particle = this.firstParticle;
			while(particle)
			{
				particle.fromX = particle.x;
				particle.fromY = particle.y;
				particle.toX = (counter*step%width)*size/step;
				particle.toY = Math.floor(counter*step/width) * size;
				var index = counter*4*step + Math.floor(counter*4*step/width)*width*4;
				if(imageAry[index+3]) particle.create([imageAry[index],imageAry[index+1],imageAry[index+2],imageAry[index+3]],[imageAry[index],imageAry[index+1],imageAry[index+2],imageAry[index+3]],size);
				particle.time = 4;
				particle.startTime = new Date().getTime() + Math.random()*3000;
				particle = particle.next;
				counter+=1;
			}
			this.easing = function(t, b, c, d ) {
				if ((t /= d / 2) < 1) { return c / 2 * t * t * t * t * t + b; } return c / 2 * ((t -= 2) * t * t * t * t + 2) + b;
			}
			this.update = function(particle){
				var currentTime = (new Date().getTime() - particle.startTime)/1000;
				if(currentTime < 0 )
				{
					particle.x = particle.fromX;
					particle.y = particle.fromY;
				}
				else if(currentTime < particle.time) {
					particle.x = this.easing(currentTime,particle.fromX,particle.toX-particle.fromX,particle.time);
					particle.y = this.easing(currentTime,particle.fromY,particle.toY-particle.fromY,particle.time);
				}
				else{
					particle.alpha = particle.toAlpha;
					particle.x = particle.toX;
					particle.y = particle.toY;
				}
			}
			this.mode = modeName;
		}
	}

window.ParticleStage = ParticleStage;

function Particle(){
	this.initialize.apply(this,arguments);
}
var p = Particle.prototype;
	p.x = 0;
	p.y = 0;
	p.alpha = 0;
	p.vx = 0;
	p.vy = 0;
	p.toX = 0;
	p.toY = 0;
	p.toAlpha = 0;
	p.fromX = 0;
	p.fromY = 0;
	p.fromAlpha = 0;
	p.time = 0;
	p.startTime = 0;

	p.k = 0.5;
	p.next = null;
	p.canvas = null;
	p.imageData = null;
	p.context = null;
	p.size = 0;
	p.round = 0;
	p.stageWidth = 0;
	p.stageHeight = 0;

	p.MAX_SIZE = 20;

	p.initialize = function(stage){
		this.size = this.MAX_SIZE * Math.random() + 2;
		this.stageWidth = stage.stageWidth;
		this.stageHeight = stage.stageHeight;
		this.canvas = document.createElement('canvas');
		if(this.size >= 10){
			this.canvas.setAttribute("width", this.size);
	   		this.canvas.setAttribute("height",this.size);
		}
		else{
			this.canvas.setAttribute("width", 10);
	   		this.canvas.setAttribute("height",10);
		}
		this.context = this.canvas.getContext('2d');
		var alpha = 0.3 + 0.3 * Math.random();
		this.create([0,67,155,alpha],[0,147,222,alpha]);
	}
	p.create = function(grad1,grad2){
		this.context.clearRect(0,0,this.canvas.width,this.canvas.height);
		var round = this.size/6;
		var grad  = this.context.createLinearGradient(0,0, 0,this.size);
		grad.addColorStop(0,'rgba(' + grad1[0] + ',' + grad1[1] + ',' + grad1[2] + ',' + grad1[3] + ')');
  		grad.addColorStop(1,'rgba(' + grad2[0] + ',' + grad2[1] + ',' + grad2[2] + ',' + grad2[3] + ')');
		this.context.beginPath();
 		this.context.fillStyle = grad;
		this.context.moveTo(round, 0);
		this.context.lineTo( this.size - round, 0);
		this.context.quadraticCurveTo(this.size, 0, this.size, round);
		this.context.lineTo(this.size,  this.size - round);
		this.context.quadraticCurveTo(this.size, this.size, this.size - round, this.size);
		this.context.lineTo(round,  this.size);
		this.context.quadraticCurveTo(0, this.size, 0, this.size - round);
		this.context.lineTo(0, round);
		this.context.quadraticCurveTo(0, 0, round, 0);
		this.context.fill();
	}

function getWindowSize(){
	var size = {width:0,height:0};
	if ( window.innerWidth ) {
		size.width = window.innerWidth;
		size.height = window.innerHeight;
	}
	else if ( document.documentElement && document.documentElement.clientWidth != 0 ) {
		size.width = document.documentElement.clientWidth;
		size.height = document.documentElement.clientHeight;
	}
	else if ( document.body ) {
		size.width = document.body.clientWidth;
		size.height = document.body.clientHeight;
	}
	return size;
}

function imageToAry(image){
	var canvasElement = document.createElement('canvas');
	var ctx = canvasElement.getContext('2d');
	var w = canvasElement.width = image.width;
	var h = canvasElement.height = image.height;

	ctx.drawImage(image,0,0,w,h);
	var orgData  = ctx.getImageData(0,0,w,h).data;
	return orgData;
}

}(window))
