// Andy LeMay - May 2010 - Steal at will!
//
// Assumptions:
//
// 1) Provided elements are of a consistent width and height


;(function($){
	
	// Class definition:
	
	var ASLImageRotator = function(pElements, pSettings){
		
		var _elements = $(pElements);
		var _settings = pSettings;
		var _isAutoRotating = false;
		var _currentItemIndex = 0;
		var _lastRotationTimestamp = new Date().getTime();
		
		// add this instance to the DOM node of the parent element
		_elements.parent().data('ASLImageRotator', this);
		
		// used to call public methods from internal private methods
		var _obj = this;
		
		this.startAutoRotation = function(){
			if(!_isAutoRotating){
				_isAutoRotating = true;
				setTimeout(this.showNextItem, _settings.autoplayInterval);
			}
		};
		
		this.stopAutoRotation = function(){
			if(_isAutoRotating){
				_isAutoRotating = false;
			}
		};
		
		this.showNextItem = function(){
			
			if(_elements.length > 1){
				
				var __currentItem = $(_elements[_currentItemIndex]);
				if(_currentItemIndex == _elements.length - 1){
					_currentItemIndex = 0;
				}
				else{
					_currentItemIndex++;	
				}
				var __newItem = $(_elements[_currentItemIndex]);
				
				//move the new item to the top of the stack
				__newItem.appendTo(__newItem.parent());
				
				// initialize some animate() options
				var __newItemAnimateOptions = {};
				
				// preposition the forthcoming element
				if(_settings.scrollIn){
					// figure out where it needs to scroll from
					switch(_settings.scrollFrom){
						case "top":
							__newItem.css("top", -_settings.viewportHeight + "px");
							break;
						case "bottom":
							__newItem.css("top", _settings.viewportHeight);
							break;
						case "left":
							__newItem.css("left", -_settings.viewportWidth);
							break;
						case "right":
							__newItem.css("left", _settings.viewportWidth);
							break;	
					}
					__newItemAnimateOptions.top = 0;
					__newItemAnimateOptions.left = 0;
				}
				else{
					__newItem.css({"top": 0 + "px", "left": 0 + "px"});
				}
				
				if(_settings.fadeIn){
					__newItem.css("opacity", 0);
					__newItemAnimateOptions.opacity = 1;
				}
				else{
					__newItem.css("opacity", 1);
				}
				
				__newItem.animate(__newItemAnimateOptions, {duration: _settings.transitionDuration, easing: "easeInOutCubic", complete:_settings.onComplete});
				
				// initialize some animate() options
				var __currentItemAnimateOptions = {};
				
				if(_settings.scrollOut){
					// figure out where it needs to scroll to
					switch(_settings.scrollFrom){
						case "top":
							__currentItemAnimateOptions.top = _settings.viewportHeight;
							break;
						case "bottom":
							__currentItemAnimateOptions.top = -_settings.viewportHeight;
							break;
						case "left":
							__currentItemAnimateOptions.top = _settings.viewportWidth;
							break;
						case "right":
							__currentItemAnimateOptions.top = -_settings.viewportWidth;
							break;	
					}

				}
				else{
					__currentItem.css({"top": 0 + "px", "left": 0 + "px"});
				}
				
				if(_settings.fadeOut){
					__currentItem.css("opacity", 1);
					__currentItemAnimateOptions.opacity = 0;
					
				}
				else{
					__currentItem.css("opacity", 1);
				}
				
				__currentItem.animate(__currentItemAnimateOptions, {duration: _settings.transitionDuration, easing: "easeInOutCubic"});
			}
		};
		
		this.showPrevItem = function(){
			if(_elements.length > 1){
				
			}
		};
		
		// private
		
		var debug = function(pSource, pMessage, pLevel) {
			if(window.console && window.console.log){
				window.console.log("[" + pLevel + "]: " + pSource + ": " + pMessage);
			}
		};
		
		var tweenElementOpacity = function(pElement, pOpacityTarget, pTotalTime){
			
			var __element = pElement;
			var __targetValue = pOpacityTarget;
			var __totalTime = pTotalTime;
			var __startTimestamp = new Date().getTime();
			var __initialValue = Number(pElement.css("opacity"));
			var __totalValueChange = pOpacityTarget - __initialValue;
			var __intervalID = setInterval(
				function(){
					var __timeIn = new Date().getTime() - __startTimestamp;
					var __newValue = easingEquations.cubicOut(__timeIn, __initialValue, __totalValueChange, __totalTime);
					if(Math.abs(pOpacityTarget - __newValue) < .01){
						__element.css("opacity", __targetValue);
						clearInterval(__intervalID);
					}
					else{
						__element.css("opacity", __newValue);
					}			
				},
				_settings.tweenResolution
			);

		};
		
		var easingEquations = {

			cubicIn: function(t, b, c, d){
				return c * (t /= d) * t * t + b;
			},

			cubicOut: function(t, b, c, d){
				return c * ((t = t / d - 1) * t * t + 1) + b;
			},

			cubicInOut: function(t, b, c, d){
			
				return ((t /= d / 2) < 1) ? c / 2 * t * t * t + b : c / 2 * ((t -= 2) * t * t + 2) + b;
			}

		};

		// init
		debug(_settings.id, "Instanced with " + _elements.length + " items...", "INFO");
		
		// reverse the order of our <li> items so that the first listed item is sitting on the top of the stack
		_elements.each(
			function(){
				$(this).prependTo($(this).parent());
			}
		);
		
		if(_settings.autoplay){
			this.startAutoRotation();
		}
	}

	// jQuery Wrapper:
	jQuery.fn.aslImageRotator = function(pOptions){
		
		var defaultSettings = {
			id: "aslImageRotator",
			viewportWidth: 200,
			viewportHeight: 200,
			autoplay: false,
			autoplayInterval: 2000,
			pauseAndResumeOnMouse: true,
			fadeIn: true,
			fadeOut: false,
			scrollIn: false,
			scrollOut: false,
			scrollFrom: "bottom",
			scrollAmount: 100,
			transitionDuration: 1000,
			onComplete: function(){},
			tweenResolution: 16 // 60fps
		};
	
		var settings = $.extend(defaultSettings, pOptions);
		
		return new ASLImageRotator(this, settings);
	}
	
})(jQuery);