/* 
 * traceBox Plugin
 * v. 1.0 
 * Jon Cazier
 * 10/14/09
 *
 */

jQuery.fn.ninjaGallery = function(options) {
	//-----------------------------------------------------------------------------------------------
	// Configuration Defaults and Options
	//-----------------------------------------------------------------------------------------------
	
	var defaults = {
		wrapperClass: "ninjaGallery", // Sets the class that wraps around the Ninja Gallery
		spacerWidth: 10, // Adds a margin to the sides of each item
		smallSize: 100, // Sets the size of the inactive items
		largeSize: 200, // Sets the size of the active item
		startOn: "random", // Sets which item is active at page load. 
						   //Available options are "random", "first", "last", or the index position of the item as an integer value. Starts at 0.
		offset: "center", // Sets the x position where the active item is displayed.
						  // Available options are "random", "first", "last", or the x position as any positive integer value.
		verticalOffset: 0, // Sets the y position of the active item. Use any integer value.
		moveSpeed: 500, // Speed at which the gallery slides. In milliseconds as an integer value.
		resizeSpeed: 200, // Speed at which the gallery items resize. In milliseconds as an integer value.
		useKeyboard: false, // Boolean value that determines if keyboard navigation is active.
		objToAnimate: "img", // Sets which items inside of the li are resized. Can have multiple values. eg: "img, h2, p".
		extraContentId: null, // Class or ID of additional content within the li that needs to be animated seperately.
		offActiveCss: null, // CSS for extra content on inactive items. eg {display: "none", border: "solid 1px red"}.
		offActiveAnimation: null, // Animation for extra content on inactive items. eg {top: "100px", opacity: ".5"}.
		onActiveCss: null, // CSS for extra content on the active item. eg {display: "none", border: "solid 1px red"}.
		onActiveAnimation: null // Animation for extra content on the active item. eg {top: "-100px", opacity: "1"}.
	};
	
	var d = jQuery.extend(defaults, options)
	
	jQuery(this).each(function(){
		
		var $this = jQuery(this);
		
		//-----------------------------------------------------------------------------------------------
		// Build Additional Layout
		//-----------------------------------------------------------------------------------------------
		
		jQuery(this)
			.wrap("<div class='"+d.wrapperClass+"'></div>")
			.before("<a href='#' class='movebutton left'>&lt;</a>")
			.after("<a href='#' class='movebutton right'>&gt;</a>");
		
		//-----------------------------------------------------------------------------------------------
		// Private Variables
		//-----------------------------------------------------------------------------------------------
		
		var totalItems = jQuery(this).children().length;
		var wrapperSize = jQuery(this).parent().width();
		var currentImage = d.startOn;
		
		//-----------------------------------------------------------------------------------------------
		// Methods
		//-----------------------------------------------------------------------------------------------
		
		jQuery(this).find("li").each(function(){
			jQuery(this).css({margin: "0 "+d.spacerWidth+"px"});
			shrinkItem(jQuery(this));
		});
		
		function shrinkItem(obj){
			obj.removeClass("active");
			var w = obj.find("li").width();
			obj.find(d.objToAnimate)
				.stop()
				.animate({width: d.smallSize, top: 0}, offActive(obj));
		};
		
		function enlargeItem(obj){
			resetActive();
			var w = obj.find("*").width();
			obj
				.addClass("active")
				.find(d.objToAnimate)
				.stop()
				.animate({width: d.largeSize, top: getVerticalOffset()}, function(){onActive(obj)});
		};
		
		function offActive(obj){
			d.offActiveAnimation = d.offActiveAnimation || {};
			d.offActiveCss = d.offActiveCss || {};
			
			if(d.extraContentId){
				obj
					.find(d.extraContentId)
					.stop()
					.animate(d.offActiveAnimation)
					.css(d.offActiveCss)
			};
		};
		
		function onActive(obj){
			d.onActiveAnimation = d.onActiveAnimation || {};
			d.onActiveCss = d.onActiveCss || {};
			
			if(d.extraContentId){
				obj
					.find(d.extraContentId)
					.css(d.onActiveCss)
					.stop()
					.animate(d.onActiveAnimation);
			};
		};
		
		function moveIt(num){
			shrinkItem($this.find(".active"));
			$this
				.stop()
				.animate(
					{left: -((num*(d.smallSize+(d.spacerWidth*2)))+getOffset())}, 
					d.moveSpeed, 
					function(){enlargeItem($this.find("li").eq(num));}
				), d.resizeSpeed;
			
			currentImage = num;
		};
		
		// Removes the "active" class from all items
		function resetActive(){
			$this.find("li.active").removeClass("active");
		};
		
		//get
		
		// Return an integer that determines where the active item appears within the panel. 
		// Available options are "center", "left", "right", or any integer value.
		function getOffset(){
			var o = 0;
			switch(d.offset){	
				case "center":
					o = (d.largeSize - wrapperSize)/2;
					break;
				case "left":
					o = 0;
					break;
				case "right":
					o = (d.largeSize - wrapperSize) + d.spacerWidth*2;
					break;
				default:
					o = d.offset;
			};
			return o;
		};
		
		// Return an integer that determines the active items vertical position.
		function getVerticalOffset(){
			var vo = 0;
			switch(d.verticalOffset){	
				case "middle":
					vo = -(d.largeSize - d.smallSize)/2;
					break;
				case "top":
					$.trace($this.find("li").height());
					vo = -(d.smallSize);
					break;
				case "bottom":
					vo = 0;
					break;
				default:
					vo = d.verticalOffset;
			};
			return vo;
		};
		
		// Return an integer that determines which item is shown as the default. 
		// Available options are "random", "first", "last", or any positive integer value.
		function getStartOn(){
			var s = 0;
			switch(d.startOn){	
				case "random":
					s = Math.floor(Math.random()*totalItems);
					break;
				case "first":
					s = 0;
					break;
				case "last":
					s = totalItems-1;
					break;
				default:
					if(d.startOn > totalItems-1){
						s = totalItems-1;
						$.trace(s);
					} else if(d.startOn < 0) {
						s = 0;
					} else {
						s = d.startOn;
					};
			};
			return s;
		};
		
		// Moves gallery one step to the left
		function moveLeft(){
			if(currentImage > 0){
				moveIt(currentImage-1);
			};
		};
		
		// Moves gallery one step to the right
		function moveRight(){
			if(currentImage < totalItems-1){
				moveIt(currentImage+1);	
			};
		};
		
		//-----------------------------------------------------------------------------------------------
		// Navigational Methods
		//-----------------------------------------------------------------------------------------------
		
		// Navigates to the item that has been clicked on
		jQuery(this).find("li").click(function(){
			if(!jQuery(this).hasClass("active")){
				moveIt(jQuery(this).parent().find("li").index(this));
			};
		});
		
		// Moves gallery when the left button is clicked
		jQuery(this).parent().find("a.left").click(function(){
			moveLeft();
			return false;
		});
		
		// Moves gallery when the right button is clicked
		jQuery(this).parent().find("a.right").click(function(){
			moveRight();
			return false;
		});
		
		// Uses keyboard keys to navigate gallery
		jQuery(window).keydown(function(event){
			if(d.useKeyboard) {					
				switch (event.keyCode) {
					case 13: //enter
						moveRight();
						break;
					case 32: //space
						moveRight();
						break;
					case 37: //left arrow
						moveLeft();
						break;
					case 39: //right arrow
						moveRight();
						break;
				};
			};
		});
		
		//-----------------------------------------------------------------------------------------------
		// Init
		//-----------------------------------------------------------------------------------------------
		
		// Sets the default active item on startup
		moveIt(getStartOn());
	});
};
