
(function ($) {

	Particle3D = function (material ) {

		THREE.Particle.call( this );
		
		this.material = material instanceof Array ? material : [ material ];
		this.velocity = new THREE.Vector3(0,-8,0);
		this.velocity.rotateX(randomRange(-45,45)); 
		this.velocity.rotateY(randomRange(0,360)); 
		this.gravity = new THREE.Vector3(0,0,0); 
		this.drag = 1; 
	};

	Particle3D.prototype = new THREE.Particle();
	Particle3D.prototype.constructor = Particle3D;

	Particle3D.prototype.update = function() {
		this.velocity.multiplyScalar(this.drag); 
		this.velocity.addSelf(this.gravity);
		this.position.addSelf(this.velocity);
	};

	var TO_RADIANS = Math.PI / 180; 

	THREE.Vector3.prototype.rotateY = function(angle){
		cosRY = Math.cos(angle * TO_RADIANS);
		sinRY = Math.sin(angle * TO_RADIANS);
		
		var tempz = this.z; 
		var tempx = this.x; 

		this.x= (tempx*cosRY)+(tempz*sinRY);
		this.z= (tempx*-sinRY)+(tempz*cosRY);
	};

	THREE.Vector3.prototype.rotateX = function(angle){
		cosRY = Math.cos(angle * TO_RADIANS);
		sinRY = Math.sin(angle * TO_RADIANS);
		
		var tempz = this.z;
		var tempy = this.y; 

		this.y= (tempy*cosRY)+(tempz*sinRY);
		this.z= (tempy*-sinRY)+(tempz*cosRY);
	};

	THREE.Vector3.prototype.rotateZ = function(angle){
		cosRY = Math.cos(angle * TO_RADIANS);
		sinRY = Math.sin(angle * TO_RADIANS);
		
		var tempx = this.x; 
		var tempy = this.y; 

		this.y= (tempy*cosRY)+(tempx*sinRY);
		this.x= (tempy*-sinRY)+(tempx*cosRY);
	};

	function randomRange(min, max){
		return ((Math.random()*(max-min)) + min); 
	}

    $.fn.boddhiSnow = function (options) {
        var defaults = {
			uri: '',
			configPanel: true,
			avaibleParticlesImages: {},
			particleImage: 1,
			particleLength: 300,
			appearBelow: '',
			particlesSpeed: 5,
			partcielsToogleSpeed: 650,
			idleTime: 1000,
			running: false,
            animationStart: function () {},
            animationComplete: function () {}
        };
        var option = $.extend({}, defaults, options);
        return this.each(function () {
            var $t = $(this),
				win = {
					width: jQuery('body').width(),
					height: jQuery('body').outerHeight()
				},
				sliders = null,
				snowPanel = '',
				snowPanelBtn = '',
				windowHalfX = win.width / 2,
				windowHalfY = win.height / 2,
				particlesGenerated = false,
				particles = [],
				snowInt = 0,
				particleImage = new Image(),
				container, particle, camera, scene, renderer;
				
            var plugin = {
                init: function () {
					if(option.configPanel === true) plugin.triggerPanel();
					
					if(option.idleTime == 0){
						plugin.toggleSnowFlakes('show');
					}else{
					
						setIdleTimeout(option.idleTime);

						document.onIdle = function() {
							plugin.toggleSnowFlakes('show');
						}
						
						document.onBack = function(isIdle) {
							if (isIdle) {
								plugin.toggleSnowFlakes('hide');
							};
						}
					}
					
					particleImage.src = option.avaibleParticlesImages[option.particleImage];
				},
				
				
				createPanelHtml: function() {
					
					var html = "";
					html += "<div id='boddhi-snow-panel' class='close'>\
						<a href='#' id='btn'>toggle button</a>\
						<div class='config-box'>\
							<div id='snow-flake'>";
					
					jQuery.each(option.avaibleParticlesImages, function(key, value){
						html += "<a href='#' " + ( key == option.particleImage ? 'class=\"on\"' : '' ) + "><img src='" + ( value ) + "' width='26' alt='snow flake model' /></a>";
					});
					
					html += "\
						</div>\
							<!-- end #snow-flake -->\
							\
							<!-- snow scrollbar, petrol -->\
							<div class='boddhi-snow-scrollbar' id='slide-snowflake-size' style='top: 208px;'>\
								<span class='bar'>\
									<span class='red' style='width: 10px;'></span>\
									<a href='#'><img src='" + option.uri + "images/slide-btn.png' /></a>\
								</span>\
								<span class='bottom-left'>0</span>\
								<span class='bottom-right'>400 snow flake</span>\
							</div>\
							\
							<!-- snow scrollbar, green -->\
							<div class='boddhi-snow-scrollbar' id='slide-snowflake-speed' style='top: 265px;'>\
								<span class='bar'>\
									<span class='green' style='width: 10px;'></span>\
									<a href='#'><img src='" + option.uri + "images/slide-btn.png' /></a>\
								</span>\
								<span class='bottom-left'>0</span>\
								<span class='bottom-right'>10 sec.</span>\
							</div>\
							\
							<!-- snow scrollbar, red -->\
							<div class='boddhi-snow-scrollbar' id='slide-idle-time' style='top: 319px;'>\
								<span class='bar'>\
									<span class='petrol' style='width: 10px;'></span>\
									<a href='#'><img src='" + option.uri + "images/slide-btn.png' /></a>\
								</span>\
								<span class='bottom-left'>0</span>\
								<span class='bottom-right'>10 sec.</span>\
							</div>\
						</div>\
					</div>";
					
					sliders = jQuery(html);
					
					$t.append(sliders);
				},
				
				triggersSlide: function() {
					var slide_snowflake_size = jQuery('#slide-snowflake-size'),
						slide_snowflake_speed = jQuery('#slide-snowflake-speed'),
						slide_idle_time = jQuery('#slide-idle-time');
					
					slide_snowflake_speed.slider({
						min: 0,
						animate: true,
						max: 160,
						step: 16,
						slide: function( event, ui ) {
							if(ui.value <= 144) {
								slide_snowflake_speed.find('span.bar span').width((ui.value + 10) + "px");
								slide_snowflake_speed.find('span.bar a').css('margin-left', ui.value + "px");
								
								if(ui.value == 144) {
									slide_snowflake_speed.find('span.bar span').width((ui.value + 12) + "px");
									slide_snowflake_speed.find('span.bar a').css('margin-left', (ui.value + 2) + "px");
								}
							}
							option.particlesSpeed = (ui.value / 16);
							
							plugin.resetSnow();
						}
					});
					
					slide_snowflake_size.slider({
						min: 0,
						animate: true,
						max: 400,
						step: 40,
						slide: function( event, ui ) {
							var toLeft = (ui.value / 40),
								onLeft = toLeft * 16;
							if(toLeft < 10 && toLeft > 0) {
								slide_snowflake_size.find('span.bar span').width((onLeft + 10) + "px");
								slide_snowflake_size.find('span.bar a').css('margin-left', onLeft + "px");
							
								option.particleLength = toLeft * 40;
								plugin.resetSnow();
							}
						}
					});

					slide_idle_time.slider({
						min: 10,
						animate: true,
						max: 100,
						step: 10,
						slide: function( event, ui ) {
							var toLeft = (ui.value / 10),
								onLeft = toLeft * 16;
							if(toLeft < 10 && toLeft > 0) {
								slide_idle_time.find('span.bar span').width((onLeft + 10) + "px");
								slide_idle_time.find('span.bar a').css('margin-left', onLeft + "px");
							
								option.idleTime = toLeft * 1000;
								setIdleTimeout(option.idleTime);
							}
						}
					});
					
					var def_speed = ((16 * option.particlesSpeed));
					slide_snowflake_speed.find('span.bar span').width( (def_speed + 10) + "px");
					slide_snowflake_speed.find('span.bar a').css('margin-left', def_speed + "px");
					
					
					var def_size = ((16 * (option.particleLength / 40)));
					slide_snowflake_size.find('span.bar span').width( (def_size + 10) + "px");
					slide_snowflake_size.find('span.bar a').css('margin-left', def_size + "px");
					
					var def_idle = ((16 * (option.idleTime / 1000)));
					slide_idle_time.find('span.bar span').width( (def_idle + 10) + "px");
					slide_idle_time.find('span.bar a').css('margin-left', def_idle + "px");
				},
				
				toggleSnowFlakes: function(action) {
					if(action === 'show') {
						if(particlesGenerated === false) {
							plugin.initLayout();
						}
						if(container.length > 0) {
							container.show();
							container.animate({
								opacity: 1
							}, option.partcielsToogleSpeed);
						}
					}else{
						if(container.length > 0) {
							container.animate({
								opacity: 0
							}, option.partcielsToogleSpeed, function() {
								jQuery(this).css('display', 'none');
							});
						}
					}
				},
				
				triggerPanel: function() {
					
					plugin.createPanelHtml();
					
					snowPanel = $t.find('#boddhi-snow-panel'),
					snowPanelBtn = snowPanel.find('#btn');
					
					var maxWidth = 328,
						minWidth = 133;
						
					snowPanelBtn.live('click', function() {
						if(snowPanel.hasClass('close') === true) {
							snowPanel.animate({
								width: maxWidth + "px"
							}, 250, function() {
								snowPanel
									.removeClass('close')
									.addClass('open');
							});
						}else if(snowPanel.hasClass('open') === true) {
							snowPanel.animate({
								width: minWidth + "px"
							}, 150, function() {
								snowPanel
									.removeClass('open')
									.addClass('close');
							});
						}
						return false;
					});
					
					snowPanel.find("#snow-flake a").live('click', function() {
						
						snowPanel.find("#snow-flake a.on").removeClass('on');
						
						var $this 	= jQuery(this),
							img 	= $this.find('img'),
							src		= img.attr('src');
							
						particleImage.src = src;
						
						$this.addClass('on');
						
						return false;
					});
					
					plugin.triggersSlide();
				},
				
				resetSnow: function() {
					container.remove();
					option.particlesGenerated = false;
					
					clearInterval(snowInt);
					particles = [],
					container, particle, camera, scene, renderer;
				
					plugin.initLayout();
					plugin.toggleSnowFlakes('show');
				},
				
				initLayout: function() {
				
					container = jQuery('<div />')
								.addClass('snow-flakes')
								.css('opacity', 0);
					jQuery('body').append(container);
					
					if(option.appearBelow != ""){
						appearBelowElm = jQuery(option.appearBelow);
						
						appearBelowElm.css({
							'position': 'relative',
							'z-index': 1000
						});
					}
					
					camera = new THREE.Camera( 75, win.width / win.height, 1, 10000 );
					camera.position.z = 1000;

					scene = new THREE.Scene();
					
					renderer = new THREE.CanvasRenderer();
					renderer.setSize(win.width, win.height);
					
					container.width(win.width);
					container.height(win.height);

					for (var i = 0; i < option.particleLength; i++) {
						particle = new Particle3D( new THREE.ParticleBitmapMaterial(particleImage));
						particle.position.x = Math.random() * 2000 - 1000;
						particle.position.y = Math.random() * 2000 - 1000;
						particle.position.z = Math.random() * 2000 - 1000;
						particle.scale.x = particle.scale.y = 0.8;
						scene.addObject( particle );
						
						particles.push(particle); 
					}

					container.append( renderer.domElement );
					
					snowInt = setInterval( plugin.loop, 10 + (option.particlesSpeed));
					
					particlesGenerated = true;
				},
				
				loop: function() {
					for(var i = 0; i < particles.length; i++){
						particle = particles[i]; 
						particle.update(); 
						
						with(particle.position){
							if(y<-1000) y+=2000; 
							if(x>1000) x-=2000; 
							else if(x<-1000) x+=2000; 
							if(z>1000) z-=2000; 
							else if(z<-1000) z+=2000; 
						}				
					}
					renderer.render( scene, camera );
				}
            };
            plugin.init();
        });
    };
}(jQuery));

var idleTimeout = 1000,
	idleNow = false,
	idleTimestamp = null,
	idleTimer = null;
 
function setIdleTimeout(ms){
    idleTimeout = ms;
    idleTimestamp = new Date().getTime() + ms;
    if (idleTimer != null) {
	clearTimeout (idleTimer);
    }
    idleTimer = setTimeout(makeIdle, ms + 50);
}
 
function makeIdle(){
    var t = new Date().getTime();
    if (t < idleTimestamp) {
		idleTimer = setTimeout(makeIdle, idleTimestamp - t + 50);
		return;
    }
    idleNow = true;
    try {
		if (document.onIdle) document.onIdle();
    } catch (err) {
    }
}
 
function active(event){
    var t = new Date().getTime();
    idleTimestamp = t + idleTimeout;
 
    if (idleNow) {
		setIdleTimeout(idleTimeout);
    }
	if ((idleNow) && document.onBack) document.onBack(idleNow);

    idleNow = false;
}
var doc = $(document);
doc.ready(function(){
	doc.mousemove(active); 
	try {
		doc.mouseenter(active);
	} catch (err) { }
	try {
		doc.scroll(active);
	} catch (err) { }
	try {
		doc.keydown(active);
	} catch (err) { }
	try {
		doc.click(active);
	} catch (err) { }
	try {
		doc.dblclick(active);
	} catch (err) { }
});

var FlashHelper =
{
	movieIsLoaded : function (theMovie)
	{
		if (typeof(theMovie) != "undefined") return theMovie.PercentLoaded() == 100;
		else return
		false;
  },

	getMovie : function (movieName)
	{
  	if (navigator.appName.indexOf ("Microsoft") !=-1) return window[movieName];
	  else return document[movieName];
	}
};

function niftyplayer(name)
{
	this.obj = FlashHelper.getMovie(name);

	if (!FlashHelper.movieIsLoaded(this.obj)) return;

	this.play = function () {
		this.obj.TCallLabel('/','play');
	};

	this.stop = function () {
		this.obj.TCallLabel('/','stop');
	};

	this.pause = function () {
		this.obj.TCallLabel('/','pause');
	};

	this.playToggle = function () {
		this.obj.TCallLabel('/','playToggle');
	};

	this.reset = function () {
		this.obj.TCallLabel('/','reset');
	};

	this.load = function (url) {
		this.obj.SetVariable('currentSong', url);
		this.obj.TCallLabel('/','load');
	};

	this.loadAndPlay = function (url) {
		this.load(url);
		this.play();
	};

	this.getState = function () {
		var ps = this.obj.GetVariable('playingState');
		var ls = this.obj.GetVariable('loadingState');

		if (ps == 'playing')
			if (ls == 'loaded') return ps;
			else return ls;

		if (ps == 'stopped')
			if (ls == 'empty') return ls;
			if (ls == 'error') return ls;
			else return ps;

		return ps;

	};

	this.getPlayingState = function () {
		return this.obj.GetVariable('playingState');
	};

	this.getLoadingState = function () {
		return this.obj.GetVariable('loadingState');
	};

	this.registerEvent = function (eventName, action) {
		this.obj.SetVariable(eventName, action);
	};

	return this;
}

jQuery("#boddhiSnow-sound-btn").live('click', function() {
	var $this = jQuery(this);
	
	if($this.hasClass('off')) {
		$this.removeClass('off');
		niftyplayer('carolPlayer').play();
	} else {
		$this.addClass('off');
		niftyplayer('carolPlayer').pause();
	}
	
	return false;
})

if(typeof console === "undefined") {
    console = { log: function() { } };
}
