/*-------------------------------------------------

	nSlider.js
	Author: mikkok / nitro
	
	Modifications to version 1.01
	
	-Added a stop method on mouseover and mouseout
	-Now the slider can interact with next and prev clicks without
	 confusing the interval and it changes direction as well.
	-Now by default the first element is loaded to the viewport
	
--------------------------------------------------*/
// remap jQuery to $
(function($){

 $.fn.nSlider = function(options) {
	 
	 var loopCtr = 0;	 
	//set default values
	var defaults = {
		speed : 300,
		pause : 5000,
		transition : 'slide',
		click : true,
		element_width : 180,
		element_height : 200
	};
	
	//markup for controll generation when running slide-mode
	var navigation = {
		count : 0,
		wrapper : '<div class="nSlider-navigation-wrapper"><ul class="nSlider-navigation"></ul></div>',
		controlls_prev : '<li class="nSlider-navigation-controlls"><a href="javascript:;" id="nSlider-navigation-prev">Previous</a></li>',
		controlls_next : '<li class="nSlider-navigation-controlls"><a href="javascript:;" id="nSlider-navigation-next">Next</a></li>'
	};
	
	// Take the options that the user selects, and merge them with defaults.
	options = $.extend(defaults, options);
	
	//set variables for runtime configuration
	var animate = {
		click : options.click,
		direction : 'left',
		position : ':first'
	};
	
	//set variables to handle intialization and click events when running auto mode. 
	var event = {
		clicked : false,
		hover : false,
		initialized : false,
		intervalId : 0,
		temporal : null
	};
	
	if($('html').hasClass('no-js')) {
		$('html').removeClass('no-js');
	}
	
	// Needed to fix a tiny bug. If the pause is less than speed, it'll cause a flickr.
	// This will check for that, and if it is smaller, it increases it to just about the options.speed.
	if(options.pause <= options.speed) { options.pause = options.speed + 100; }
	
	this.each(function() {
		var $this = $(this);
		
		//if one or zero children don't animate
		var $children = $this.children();
		if ($children.length < 2)
		{
			$children.show();
			return;
		}

		//wrap the parent to hide the overflowing width
		$this.wrap('<div class="nSlider-wrap" />');
		
		$(navigation.wrapper).appendTo('.nSlider-wrap');
		
		//count all the children and add a class to represent the position
		$children.each(function() { 
			$(this).addClass('element-'+navigation.count);
			$('<li class="nSlider-navigation-element"><a id="navigation-element-'+navigation.count+'" href="javascript:;">'+navigation.count+'</a></li>').appendTo('.nSlider-navigation');
			
			navigation.count += 1;
		})
		
		// less than 3 children fails the animation
		if ($children.length == 2)
		{
			$this.append($children.eq(0).clone().removeClass('element-0').addClass('element-2'));
			$this.append($children.eq(1).clone().removeClass('element-1').addClass('element-3'));
		}
		
		//if transition is slide we do things little bit different
		if(options.transition == 'slide') {
			$(navigation.controlls_prev).appendTo('.nSlider-navigation');
			$(navigation.controlls_next).appendTo('.nSlider-navigation');
			
			//bind click event for controlls
			$('.nSlider-navigation-controlls a').bind('click',  nMoveTo);
			
			//create a empty dom element to fill empty space on left
			//this dom element is destroyet after first run.
			$('<div id="nSlider-initialized"></di>').prependTo($this);
			$('#nSlider-initialized').css({
				'width' : options.element_width + 'px',
				'height' : options.element_height + 'px',
				'display' : 'block'
			});
		}
		
		//bind hover event to stop the slide animation
		//done with boolean variables to make it fast.
		if(!options.click) {
			$this.children().hover(
				function() { event.hover = true; },
				function() { event.hover = false; }
			);
		}
		
		//set the active element on initalization
		nSetActive();
		
		//add absurd width so that all the children
		//can float to left
		$this.css({
			'width' : 9999+'px',
			'position' : 'relative',
			'left' : '-' + options.element_width + 'px',
			'padding'  : 0
		});
		
		$('.nSlider-wrap').css({
			'width' : options.element_width+'px',
			'height' : options.element_height+'px',
			'overflow' : 'hidden',
			'position' : 'relative'
		});
		
		$('.nSlider-navigation-wrapper').css({
			'width' : options.element_width+'px',
			'position' : 'absolute',
			'bottom' : 0,
			// 'left' : 0,
			'left' : -30,
			'zIndex' : 999999
		});
		
		//use different functionality for different transition
		if(options.transition === 'slide') {
			
			$this.children().css({
				'float' : 'left',
				'width' : options.element_width+'px',
				'height' : options.element_height+'px',
				'display' : 'block'
			});
			
			if(options.click) {
				$this.children().bind('click', nSlide);
			} else {
				//call the slide function
				nSlide();
			}
		
		} //end of if slide
		
		if(options.transition === 'fade') {
			$this.css({
				'left' : 0
			});
			
			$this.children().css({
				'width' : options.element_width+'px',
				'height' : options.element_height+'px',
				'position' : 'absolute',
				'left' : 0,
				'display' : 'block'
			});
			
			// reorder elements to fix z-index issue.
			for(var i = $this.children().length, y = 0; i > 0; i--, y++) { 		
				$this.children().eq(y).css('zIndex', i + 99999);
			}
			
			if(options.click) {
				$this.children().bind('click', nFade);
			} else {
				// Call the fade function. 
				nFade();
			}	
		} // end of if fade
		
		//nMoveTo function is binded to the nSlider-navigation link elements click event.
		function nMoveTo() {
			//first disable the interval so no confuse is born.
			nDisableInterval()
	
			if($(this).attr('id') === 'nSlider-navigation-prev') {
				//define the direction of animation
				animate.direction = 'right';
				//call the animation initialization function
				nSlide();
			}
			if($(this).attr('id') === 'nSlider-navigation-next') {
				//define the direction of animation
				animate.direction = 'left';
				//call the animation initialization function
				nSlide();
			}
		}
		
		//nDisableClick funtion disables all click events for the time animation takes place
		function nDisableClick() {
			$this.children().unbind('click');
			$('.nSlider-navigation-controlls a').unbind('click');
			
			options.click = false;
		}
		
		//nRecoverClick funtion recovers the click event to give user the controll back
		function nRecoverClick() {
			if(animate.click) {
				$this.children().bind('click', nSlide);
				$('.nSlider-navigation-controlls a').bind('click', nMoveTo);
				
				options.click = true;
			}
		}
		
		//nDisableInterval funtion disables the interval after click event on auto-mode to prevent confusion
		function nDisableInterval() {
			//only done if plugin is running auto-mode
			if(!options.click) {
				//event.temporal saves the main click option so that
				//plugin can reveser back to the options it is running
				event.temporal = options.click;
				options.click = true;
				animate.click = true;

				clearInterval(event.intervalId);
			}
		}
		
		//nSetInterval function sets the interval again to continue the auto-animation
		function nSetInterval() {
			//only done if plugin is running auto-mode
			//event.temporal contains the orginal value of options.click
			if(event.temporal === false) {
				options.click = event.temporal;
				animate.click = event.temporal;
				event.temporal = null;
				
				//event.intervaId is set so plugin can disable the interval for click events
				event.intervalId = setInterval(function() { nAnimate(); }, options.pause);
			}
		}
		
		
		//nSetActive funtion allways set the active element that indicates position of slider
		function nSetActive() {
				$('.nSlider-navigation a').removeClass('nSlider-active');

				if(options.transition == 'slide') {
					var element_class = $this.children().eq(1).attr('class');
				} else {
					var element_class = $this.children(':first').attr('class');
				}

				element_class = element_class.replace('nSlider-element-default', '');
				element_class = element_class.replace('nSlider-element', '');
				element_class = element_class.replace('element-', '');

				var i = parseInt(element_class);
				if (navigation.count == 2 && i > 1)
				{
					i -= 2;
				}

				// Loop two full rounds and then stop at the first slider item 
				if (i==0) {
					loopCtr = loopCtr +1;
				}
				
				if (loopCtr ==3 && i==0) {
					loopCtr = 1;
					clearInterval(event.intervalId);
				}
				
				$('#navigation-element-'+i).addClass('nSlider-active');
		}
		
		//nInitializationComplete determines if initialization is done, if not it destroys the empty element 
		//created by this plugin
		function nInitializationComplete() {
			if(!event.clicked && options.click) {
				event.clicked = true;
				
				if(animate.direction == 'right') {
					$('#nSlider-initialized').remove();
					$this.children(':last').prependTo($this);
					
					event.initilized = true;
				} 
				
			} else {
				event.clicked = true;
			}
		}
		
		//nVerfiyInitialization funtion verifys that empty element is destroyed
		function nVerifyInitialization() {
			if(!event.initialized) {
				$('#nSlider-initialized').remove();
				event.initilized = true;
			}
		}
		
		//nSlide funtion determines how the animation event is handled
		function nSlide() {
			if(options.click) {
				nInitializationComplete();
				nDisableClick();
				nAnimate();
			} else {
				event.intervalId = setInterval(function() { nAnimate(); }, options.pause);
			}
		} // end slide

		function nFade() {
			if(options.click) {
				nDisableClick();
				nAnimate();
			} else {
				event.intervalId = setInterval(function() { nAnimate(); }, options.pause);
			}
		} // end fade
		
		function nAnimate() {
			if(!event.hover) {
				if(options.transition === 'slide') {
					if(animate.direction === 'left') {
						$this.animate({ left : '-' + (2*options.element_width) + 'px' }, { duration: options.speed, easing : 'linear', complete : function() {
							// Return the "left" CSS back to 0, and append the first child to the very end of the list.
							$this.css('left', '-' + options.element_width + 'px').children(':first').appendTo($this); // move it to the end of the line.
							//Mark the active link of nSlider-navigation
							nSetActive();
							//Recove the click event if click is enabled on options
							nRecoverClick();
							//Just for to be sure we once again remove initialized element
							nVerifyInitialization();
							///We initialize the interval again if the plugin is running on auto
							nSetInterval();
						}
						});
					}
					else {
						$this.animate({ left : 0 + 'px' }, { duration: options.speed, easing : 'linear', complete : function() {
							// Return the "left" CSS back to 0, and append the first child to the very end of the list.
							//$this.css('left', 0); // move it to the end of the line.
							$this.css('left', '-' + options.element_width + 'px').children(':last').prependTo($this); // move it to the end of the line.
							//Mark the active link of nSlider-navigation
							nSetActive();
							//Recove the click event if click is enabled on options
							nRecoverClick();
							//Just for to be sure we once again remove initialized element
							nVerifyInitialization();
							//We initialize the interval again if the plugin is running on auto
							nSetInterval();
						}
						});
					}
				}
			}
			
			if(options.transition === 'fade') {
				$this.children(':first').animate({'opacity' : 0}, options.speed, function() {	
					$this
						.children(':first')
						.css('opacity', 1) // Return opacity back to 1 for next time.
					  	.css('zIndex', $this.children(':last').css('zIndex') - 1) // Reduces zIndex by 1 so that it's no longer on top.					
					   	.appendTo($this); // move it to the end of the line.
						//Mark the active link of nSlider-navigation
						nSetActive();
						//Recove the click event if click is enabled on options
						nRecoverClick();
				});
			}
		}
	});
}

})(window.jQuery);

// usage: log('inside coolFunc',this,arguments);
// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
/*----------------------------------------------------------------------
window.log = function(){
  log.history = log.history || [];   // store logs to an array for reference
  log.history.push(arguments);
  if(this.console){
    console.log( Array.prototype.slice.call(arguments) );
  }
};

// catch all document.write() calls
(function(doc){
  var write = doc.write;
  doc.write = function(q){ 
    log('document.write(): ',arguments); 
    if (/docwriteregexwhitelist/.test(q)) write.apply(doc,arguments);  
  };
})(document);
----------------------------------------------------------------------*/



