// Written by Andy LeMay - http://www.andylemay.com/
//
// Assumptions:
//
// 1) Provided elements are of a consistent width and height


;(function($){
	
	// Class definition:
	
	var IndexAwardRotator = function(pElements, pSettings){
		
		var _elements = $(pElements);
		var _settings = pSettings;
		var _minVisibleItems = Math.ceil(_settings.viewportWidth  / _settings.itemWidth);
		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('IndexAwardRotator', 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 we have enough elements to justify scrolling
			if(_elements.length > _minVisibleItems){
				
				var __pointer, i, __onComplete;
				
				// create an array of items, each of which will be moved to the left when the transition begins
				var __motionTargets = [];
				
				// store a reference to the item in the left-most spot
				var __currentItem = $(_elements[_currentItemIndex]);
				
				// we know it will need to move, so add it to our motion targets
				__motionTargets.push(__currentItem);
				
				// if the current item is the last in the group
				if(_currentItemIndex == _elements.length - 1){
					// roll over to the first item
					_currentItemIndex = 0;
					__pointer = _currentItemIndex;
				}
				// otherwise
				else{
					// increment the item index by 1
					_currentItemIndex++;
					__pointer = _currentItemIndex;
				}
				
				// we need to tag more items for motion
				for(i = 0; i < _minVisibleItems; i++){
					__motionTargets.push($(_elements[__pointer]));
					if(__pointer == _elements.length - 1){
						__pointer = 0;
					}
					else{
						__pointer++;	
					}
				}
				
				// now we need to position these elements
				for(i = 0; i < __motionTargets.length; i++){
					__motionTargets[i].css("left", i * _settings.itemWidth);
				}
				
				// and move them
				for(i = 0; i < __motionTargets.length; i++){
					var __animateOptions = {};
					__animateOptions.left = -_settings.itemWidth + (i * _settings.itemWidth);
					if(i == __motionTargets.length - 1){
						__onComplete = _obj.onTransitionComplete;
					}
					else{
						__onComplete = function(){};	
					}
					__motionTargets[i].animate(__animateOptions, {duration: _settings.transitionDuration, easing: "easeInOutCubic", complete:__onComplete});
				}
			}
		};
		
		this.onTransitionComplete = function(){
			if(_settings.autoplay){
				setTimeout(_obj.showNextItem, _settings.autoplayInterval);
			}
		};
		
		// private
		
		var debug = function(pSource, pMessage, pLevel) {
			if(window.console && window.console.log){
				window.console.log("[" + pLevel + "]: " + pSource + ": " + pMessage);
			}
		};
		
		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");
		
		// arrange the elements horizontally
		_elements.each(
			function(pIndex){
				var __xPosition = pIndex * _settings.itemWidth;
				$(this).css("left", __xPosition);
			}
		);
		
		if(_settings.autoplay){
			this.startAutoRotation();
		}
	}

	// jQuery Wrapper:
	jQuery.fn.indexAwardRotator = function(pOptions){
		
		var defaultSettings = {
			id: "indexAwardRotator",
			viewportWidth: 600,
			viewportHeight: 120,
			itemWidth: 150,
			itemHeight: 120,
			autoplay: true,
			autoplayInterval: 3000,
			transitionDuration: 1000,
			onComplete: function(){},
			tweenResolution: 16 // 60fps
		};
		
		// apply any passed-in properties to this object
		var settings = $.extend(defaultSettings, pOptions);
		
		// return a new instance of this class
		return new IndexAwardRotator(this, settings);
	}
	
})(jQuery);