/*
 * jQuery Scroller Plugin
 * Copyright (c) 2010 Viral Ganatra
 * Version: 1.1 (02/10/2010, updated: 24/10/10)
 * Requires: jQuery v1.4.2 or later
 */
 (function($) {
	$.fn.scroller = function(params) {
    // use extend to merge input parameters and defaults
    // use an empty object literal first as it is overwritten by the extend method
	var settings = $.extend(
		{},
      	{
        	previousClass : '.previous',
			nextClass : '.next',
       		animationSpeed : 1000,
			contentClass : '.scrollable-content',
			containerToMoveClass : '.scrollable-container',
			disabledClass : '.disabled',
			direction : 'vertical',
			verticalOffset : 0,
			horizontalOffset : 0
      	},
		params
	);
	
	// enable use of console without throwing js errors in other browsers
	/*if (!console) {
		var console = {
			log: function() {}
		};
	}*/
	
	var $this = $(this);
	if ($this[0]) {
		$this.each(
			function() {
				// setup variables
				var $this = $(this);
				var $scrollableContent = $this.find(settings.contentClass);
				var $containerToMove = $this.find(settings.containerToMoveClass);
				var $previousButton = $this.find(settings.previousClass);
				var $nextButton = $this.find(settings.nextClass);
				var previousClass = settings.previousClass;
				var nextClass = settings.nextClass;
				var disabledClass = settings.disabledClass.substr(1);
				var direction = settings.direction;
				var animationSpeed = settings.animationSpeed;
				var verticalOffset = settings.verticalOffset;
				var horizontalOffset = settings.horizontalOffset;
				var scrollableContentOffset = (direction == 'vertical') ? Math.round($scrollableContent.offset().top) : Math.round($scrollableContent.offset().left);
				var scrollableDimension = (direction == 'vertical') ? $scrollableContent.height() : $scrollableContent.width();
				var positionToMove = (direction == 'vertical') ? scrollableDimension + verticalOffset : scrollableDimension + horizontalOffset;
				var cssDirection = (direction == 'vertical') ? 'top' : 'left';
				var lastStoryOffsets = (direction == 'vertical') ? $containerToMove.children(':last').offset().top : $containerToMove.children(':last').offset().left;
				
				
				// setup disabled buttons and set next button to disabled if not enough content to scroll
				$previousButton.addClass('disabled');
						
				if ((scrollableDimension + scrollableContentOffset) >= lastStoryOffsets) {
					$nextButton.addClass('disabled');
				}
			
				// observe click events via event delegation
				$this.delegate(previousClass + ', ' + nextClass, 'click',
					function(event) {
						var $this = $(this);
						
						if ($this.is('a')) {
							event.preventDefault();
						}
						
						// while animating add the class 'stop' to prevent event firing while animation is occuring
						// remove disabled class if going forward or back
						// calculate new positionToMove (whether to move backwards or forwards)
						if ($this.hasClass(nextClass.substr(1)) === true) {	
							$previousButton.removeClass(disabledClass);
							
							var $lastStory = $containerToMove.children(':last');
							var lastStoryOffsetDirection = (direction == 'vertical') ? $lastStory.offset().top : $lastStory.offset().left;
							var lastStoryOuterDimension = (direction == 'vertical') ? $lastStory.outerHeight() : $lastStory.outerWidth();
							var lastStoryOffset = Math.round(lastStoryOffsetDirection) - positionToMove + lastStoryOuterDimension;
							var scrollableContentOffsetPlusDimension = scrollableContentOffset + scrollableDimension;
							
							console.log('lastStoryOffset: ' + lastStoryOffset + ' scrollableContentOffsetPlusDimension: ' + scrollableContentOffsetPlusDimension);
							
							// check if we're at the last story in which case recalculate the var positionToMove
							if (lastStoryOffset <= scrollableContentOffsetPlusDimension) {
								// bracket is important here
								var newPositionToMove = -(positionToMove - (scrollableContentOffsetPlusDimension - lastStoryOffset) + horizontalOffset + verticalOffset);
								
								var disabled = true;
							} else {
								var newPositionToMove = -(positionToMove + horizontalOffset + verticalOffset);
							}
							
							
						} else if ($this.hasClass(previousClass.substr(1)) === true) {
							$nextButton.removeClass(disabledClass);
							
							var firstStory = $containerToMove.children(':first');
							var firstStoryOffsetDirection = (direction == 'vertical') ? firstStory.offset().top : firstStory.offset().left;
							var firstStoryOffset = Math.round(firstStoryOffsetDirection) + positionToMove;
							
							console.log('firstStoryOffset: ' + firstStoryOffset + ' scrollableContentOffset: ' + scrollableContentOffset);
		
							// check we've reached our first story in which case recalculate the var positionToMove
							if (firstStoryOffset >= scrollableContentOffset) {
								// Math.abs turns negative value into positive
								var newPositionToMove = Math.abs(firstStoryOffset - scrollableContentOffset - (positionToMove - horizontalOffset - verticalOffset));
								
								var disabled = true;
							} else {
								var newPositionToMove = positionToMove + horizontalOffset + verticalOffset;
							}					
					
						}

						
						// we can't use a variable as a property name inside an object literal
						// i.e. can't do var foo = 'top'; $containerToMove.animate({ foo : newPositionToMove });
						var animationArg = {};
						animationArg[cssDirection] = '+=' + newPositionToMove; 
						
						if ($this.hasClass('stop') === false && $this.hasClass(disabledClass) === false) {
							$this.addClass('stop');
							
							$containerToMove.animate(
								animationArg,
								animationSpeed,
								function() {
									$this.removeClass('stop');
									
									if (disabled === true) {
										$this.addClass(disabledClass);
									}
								}
							);
						}
						
					}
				);
			}
		);
	}
	
  };
})(jQuery);
