/*******************************************************************************
*	jQuery Xbox Dashboard Style Carousel Plugin
*	Author: Phillip j Parr - http://wizpip.com
*	Client: Adrian Ricketts
*
*	This plugin is copyright 2010 Phillip Parr and Adrian Ricketts
*	If you wish to use this plugin you MUST contact the author for permission
*******************************************************************************/

(function($){
		  
	$.fn.extend({
				
		xboxCarousel: function(options) {
		
			var defaults = {
				autoScroll: true, 			// will we scroll the carousel automatically?
				autoSpeed: 5000, 			// how long in milliseconds before auto scroll
				visible: 4,				// how many items can be seen at once
				openSpeed: 250,			// how fast do the items spread out on load
				animateSpeed: 400,			// how fast do they animate when moving
				perspectiveSize: 0.825,		// used for calculating width / depth
				accuracy: 10			// iterations to calculate exact final widths. Higher is more accurate / slower,

				// openFunction: function() { alert('Text if required goes here.'); } Use <a href="#" rel="shadowbox:width=1195;"><img src="images/open.png" border="0" class="open"></a> if you want to open a page using Shadowbox

			}
			
			var options = $.extend(defaults, options);
			
			options.visible = (this.find('li').length <= options.visible) ? this.find('li').length - 1 : options.visible;
			
			var locations = new Array();
			var timer;
			
			for(var i = 0; i < this.find('li').length; i++) {
				locations[i] = new Array();
			}
			
			return this.each(function() {
				
				var o = options;
				var count = 0;
				
				$(this).wrap('<div class="xbox_container">');

				$(this).parent().append('<div class="controls"><a href="#" class="prev"></a>  <a href="#" class="next"></a></div>');
				
				var carouselWidth = $(this).parent().outerWidth();
				var width = $(this).find('li:first').outerWidth();
				var panelWidth = width;
				var panels = $(this).find('li').length;
				var left = 0;
				var top = 0;
				var perspective = 1;
				var perspectiveDistance = calculatePerspective(carouselWidth, panelWidth);

				// initial slide into place
				$(this).find('li').each(function() {
					$(this).addClass('panel'+count).css({zIndex: panels - count});//.append('<span class="testing">'+count+'</span>');
					locations[count]['left'] = left;
					locations[count]['top'] = top;
					locations[count]['width'] = width;
					locations[count]['z'] = panels - count;
					if(count < o.visible) {
						$(this).css({top: top }).animate({left: left }, count * o.openSpeed).find('img').css({width: width });
						width = width * o.perspectiveSize;
						left = left + width * perspective;
						top = (-width / 2 + panelWidth / 2) * perspectiveDistance;
						perspective *= perspectiveDistance;
					} else {
						$(this).css({top: top, left: left}).fadeTo(0,0).find('img').css({width: width });
					}
					count++;
				});
				
				var location = 0;
				
				$(this).parent().find('.next').click(function() {
					if($(this).parents('.xbox_container').find('li:animated').length) {
						var self = this;
						setTimeout(function() { $(self).trigger('click'); }, 100);
						return;
					}
					clearTimeout(timer);
					var current = location;
					for(var i = 0; i < panels; i++) {
						var prev = i - 1;
						if(prev < 0) prev = panels - 1;
						var panel = $(this).parents('.xbox_container').find('.panel'+current);
						var speed = o.animateSpeed;
						if(i == 0) {
							panel.css({zIndex: panels + 1}).animate({top: top * -perspectiveDistance , left: panelWidth * -perspectiveDistance, opacity: 0}, o.animateSpeed, 'linear').find('img').animate({width: panelWidth * (o.perspectiveSize * 2)}, o.animateSpeed, 'linear');
							speed = 0;
						} else if(i == o.visible) {
							panel.css({zIndex: locations[prev]['z']}).animate({top: locations[prev]['top'], left: locations[prev]['left'], opacity: 1}, o.animateSpeed, 'linear').find('img').animate({width: locations[prev]['width']}, o.animateSpeed, 'linear');
							speed = 0;
						}
						panel.css({zIndex: locations[prev]['z']}).animate({top: locations[prev]['top'], left: locations[prev]['left']}, speed, 'linear').find('img').animate({width: locations[prev]['width']}, speed, 'linear');
						if(++current > panels - 1) {
							current = 0;
						}
					}
					location++;
					if(location > panels - 1) location = 0;
					if(o.autoScroll) {
			        	var self = this;
			        	timer = setTimeout(function() { $(self).parents('.xbox_container').find('.next').trigger('click'); }, o.autoSpeed);
					}					
					return false;
				});

				$(this).parent().find('.prev').click(function() {
					if($(this).parents('.xbox_container').find('li:animated').length) {
						var self = this;
						setTimeout(function() { $(self).trigger('click'); }, 100);
						return;
					}
					clearTimeout(timer);
					var current = location;
					for(var i = 0; i < panels; i++) {
						var next = i + 1;
						if(next > panels - 1) next = 0;
						var panel = $(this).parents('.xbox_container').find('.panel'+current);
						var speed = o.animateSpeed;
						if(next == 0) {
							panel.css({zIndex: panels + 1, top: top * -perspectiveDistance , left: panelWidth * -perspectiveDistance}).find('img').css({width: panelWidth * (o.perspectiveSize * 2)});
							panel.css({zIndex: locations[next]['z']}).animate({top: locations[next]['top'], left: locations[next]['left'], opacity: 1}, o.animateSpeed, 'linear').find('img').animate({width: locations[next]['width']}, o.animateSpeed, 'linear');
							speed = 0;
						} else if(next == o.visible) {
							panel.css({zIndex: locations[next]['z']}).animate({top: locations[next]['top'], left: locations[next]['left'], opacity: 0}, o.animateSpeed, 'linear').find('img').animate({width: locations[next]['width']}, o.animateSpeed, 'linear');
							speed = 0;
						} else {
							panel.css({zIndex: locations[next]['z']}).animate({top: locations[next]['top'], left: locations[next]['left']}, speed, 'linear').find('img').animate({width: locations[next]['width']}, speed, 'linear');
						}
						if(++current > panels - 1) {
							current = 0;
						}
					}
					location--;
					if(location < 0) location = panels - 1; 
					if(o.autoScroll) {
			        	var self = this;
			        	timer = setTimeout(function() { $(self).parents('.xbox_container').find('.next').trigger('click'); }, o.autoSpeed);
					}										
					return false;
				});

//				$(this).parent().find('.open').click(function() {
//					// variable location contains the number of the front most panel
//					o.openFunction(location);
//					return false;
//				});
				
				if(o.autoScroll) {
		        	var self = this;
		        	timer = setTimeout(function() { $(self).parents('.xbox_container').find('.next').trigger('click'); }, o.autoSpeed);
				}

				// calculates the fraction required to make everything look right in the space available
				function calculatePerspective(carouselWidth, panelWidth) {
					var finalWidth = panelWidth * Math.pow(o.perspectiveSize, o.visible - 1);
					var perspectiveDistance = 1;
					var iterationCount = 0;
					var fraction = 0.5;
					var maxValue = 1;
					var minValue = 0;
					do {
						var perspective = 1;
						var width = panelWidth;
						var left = 0;
						for(var i = 1; i < o.visible; i++) {
							width = width * o.perspectiveSize;
							left = left + width * perspective;
							perspective *= perspectiveDistance;
						}
						if(left + finalWidth > carouselWidth) {
							maxValue = perspectiveDistance;
							if(perspectiveDistance - fraction <= minValue) {
								fraction /= 2;
							}
							perspectiveDistance -= fraction;
							
						} else if(left + finalWidth < carouselWidth) {
							minValue = perspectiveDistance;
							if(perspectiveDistance + fraction >= maxValue) {
								fraction /= 2;
							}
							perspectiveDistance += fraction;
						} else {
							// spot on!
							break;
						}
					} while(iterationCount++ < o.accuracy);
					return perspectiveDistance;
				}
			});
		}
	});
})(jQuery);

