;(function($)
{
	
$.fn.interactiveBanner = function(options)
{
	var defaults = 
	{
		slideAnimationTime: 400
	};
	var settings = $.extend(defaults, options);
	
	$(this).each(function()
	{
		var $viewport = $(this);
		
		// Initialise the width and position of the list.
		$(this).find('.slides').width(function()
		{
			var width = 0;
			$(this).find('.slideItem').each(function()
			{
				width += $(this).width();
			});
			return width;
		}).css('left', 0);
		
		// Set initial position of previous button.
		$(this).find('.pager.prev').addClass('disabled').css('left', function()
		{
			return $(this).width() * -1;
		});
		
		// Set initial position of next button.
		var $slides = $viewport.find('.slides');
		
		if(0 <= $viewport.outerWidth() - $slides.width())
		{
			$(this).find('.pager.next').addClass('disabled').css('right', function()
			{
				return $(this).width() * -1;
			});
		}
		
		// Events.
		(function($viewport)
		{
			// Prev/next click throughs.
			$viewport.find('.pager').click(function(e)
			{
				e.preventDefault();
				
				// Don't do anything if it's animating.
				if($viewport.find('.slides:not(:animated)').length == 0) return false;
				
				// Get direction.
				var direction = $(this).hasClass('prev') ? -1 : 1;
				
				// See if we need to move.
				var $slides = $viewport.find('.slides');
				var doMovement = false;
				if(direction == -1)
					doMovement = $slides.position().left < 0;
				else
					doMovement = $slides.position().left > $viewport.width() - $slides.width();
				
				if(!doMovement) return false;
				
				if(direction == -1)
					$viewport.trigger('scrollprev');
				else
					$viewport.trigger('scrollnext');
			});
			
			// Thumbnail clicks.
			$viewport.next('.bannerThumbs').find('ul a').click(function(e)
			{
				e.preventDefault();
				
				var $thumb = $(this).parents('li');
				
				// Don't do anything if it's animating.
				if($viewport.find('.slides:not(:animated)').length == 0) return false;
				
				// Don't do anything if we've clicked on the current item.
				if($thumb.hasClass('current')) return false;
				
				var $thumbs    = $thumb.parents('.bannerThumbs').find('li');
				var thumbIndex = $.inArray($thumb.get(0), $thumbs);
				
				// Find corresponding banner item.
				var $slideItem = $($viewport.find('.slides .slideItem').get(thumbIndex));
				
				// Mark current thumb as 'current'.
				$thumbs.removeClass('current');
				$thumb.addClass('current');
				
				// Trigger scrollto event.
				$viewport.trigger('scrollto', [$slideItem]);
			});
			
			// scrollprev event: Move to the previous slide. 
			$viewport.bind('scrollprev', function()
			{
				var direction = -1;
				var $slides   = $viewport.find('.slides');
				
				// Get current item.
				var $currItem = $viewport.find('.slideItem.current');
				
				// Get displacement item, the item which will determine the banner movement amount.
				var $displacementItem = $currItem.prev('.slideItem');
				
				var displacement;
				if($displacementItem.size() == 1)
					displacement = $displacementItem.width();
				
				// Perform animations.
				var currPosition = $slides.position().left;
				var newPosition = currPosition - displacement * direction;
				
				// Change 'current' item.
				$currItem.removeClass('current');
				$displacementItem.addClass('current');
				
				// Move slides.
				$slides.animate(
				{
					left: newPosition
				}, settings.slideAnimationTime);
				
				// hide buttons in/out where applicable.
				$viewport.trigger('updatepagerstate', [newPosition]);
				$viewport.trigger('updatethumbstate');
				$viewport.trigger('updatethumbpagestate');
				$viewport.trigger('updatethumbpagerstate');
			});
			
			// scrollnext event: Move to the next slide. 
			$viewport.bind('scrollnext', function()
			{
				var direction = 1;
				var $slides   = $viewport.find('.slides');
				
				// Get current item.
				var $currItem = $viewport.find('.slideItem.current');
				
				// Get displacement item, the item which will determine the banner movement amount.
				var $displacementItem = $currItem.next('.slideItem');
				
				var displacement;
				if($displacementItem.size() == 1)
					displacement = $displacementItem.width();
				
				// Perform animations.
				var currPosition = $slides.position().left;
				var newPosition = currPosition - displacement * direction;
				
				// Move slides.
				$slides.animate(
				{
					left: newPosition
				}, settings.slideAnimationTime);
				
				// Change 'current' item.
				$currItem.removeClass('current');
				$displacementItem.addClass('current');
				
				// hide buttons in/out where applicable.
				$viewport.trigger('updatepagerstate', [newPosition]);
				$viewport.trigger('updatethumbstate');
				$viewport.trigger('updatethumbpagestate');
				$viewport.trigger('updatethumbpagerstate');
			});
			
			// scrollto event: Move to the specified slide.
			$viewport.bind('scrollto', function(e, $destItem)
			{
				var $slides   = $viewport.find('.slides');
				var $currItem = $viewport.find('.slideItem.current');
				
				// Determine direction.
				var $items = $viewport.find('.slideItem');
				var currItemIndex = $.inArray($currItem.get(0), $items);
				var destItemIndex = $.inArray($destItem.get(0), $items);
				
				var direction;
				switch(true)
				{
					case currItemIndex < destItemIndex:
						direction = 1;
						break;
					case currItemIndex > destItemIndex:
						direction = -1;
						break;
					default:
						direction = 0;
						break;
				}
				
				// Get displacement distance.
				var $displacementItems = $items.filter(function(index)
				{
					if(direction == 1)
						return index >= currItemIndex && index < destItemIndex; // Between (including) current item and next item.
					else
						return index < currItemIndex && index >= destItemIndex; // Between current item and (including) prev item.
				});
				
				var displacement = 0;
				$displacementItems.each(function()
				{
					displacement += $(this).width();
				});
				
				// Perform animations.
				var currPosition = $slides.position().left;
				var newPosition = currPosition - displacement * direction;
				
				// Move slides.
				$slides.animate(
				{
					left: newPosition
				}, settings.slideAnimationTime);
				
				// Change 'current' item.
				$currItem.removeClass('current');
				$destItem.addClass('current');
				
				// hide buttons in/out where applicable.
				$viewport.trigger('updatepagerstate', [newPosition]);
				$viewport.trigger('updatethumbstate');
				$viewport.trigger('updatethumbpagestate');
				$viewport.trigger('updatethumbpagerstate');
			});
			
			// jumpto event: Move to the specified slide.
			$viewport.bind('jumpto', function(e, $destItem)
			{
				var $slides   = $viewport.find('.slides');
				var $currItem = $viewport.find('.slideItem.current');
				
				// Determine direction.
				var $items = $viewport.find('.slideItem');
				var currItemIndex = $.inArray($currItem.get(0), $items);
				var destItemIndex = $.inArray($destItem.get(0), $items);
				
				var direction;
				switch(true)
				{
					case currItemIndex < destItemIndex:
						direction = 1;
						break;
					case currItemIndex > destItemIndex:
						direction = -1;
						break;
					default:
						direction = 0;
						break;
				}
				
				// Get displacement distance.
				var $displacementItems = $items.filter(function(index)
				{
					if(direction == 1)
						return index >= currItemIndex && index < destItemIndex; // Between (including) current item and next item.
					else
						return index < currItemIndex && index >= destItemIndex; // Between current item and (including) prev item.
				});
				
				var displacement = 0;
				$displacementItems.each(function()
				{
					displacement += $(this).width();
				});
				
				// Perform animations.
				var currPosition = $slides.position().left;
				var newPosition = currPosition - displacement * direction;
				
				// Move slides.
				$slides.css(
				{
					left: newPosition
				});
				
				// Change 'current' item.
				$currItem.removeClass('current');
				$destItem.addClass('current');
				
				// hide buttons in/out where applicable.
				$viewport.trigger('updatepagerstate', [newPosition]);
				$viewport.trigger('updatethumbstate');
				$viewport.trigger('updatethumbpagestate');
				$viewport.trigger('updatethumbpagerstate');
			});
			
			// updatepagerstate event: Update the next/previous buttons and whether they will show.
			$viewport.bind('updatepagerstate', function(e, newPosition)
			{
				var $slides = $viewport.find('.slides');
				
				var buttonWidth = $viewport.find('.pager').width();
				
				// Show/Hide previous button.
				var disablePrev = (newPosition == 0);
				$viewport.find('.prev').toggleClass('disabled', disablePrev).animate(
				{
					left: disablePrev ? buttonWidth * -1 : 0
				}, settings.slideAnimationTime);
		
				// Show/Hide next button.
				var disableNext = (newPosition <= $viewport.outerWidth() - $slides.width());
				$viewport.find('.next').toggleClass('disabled', disableNext).animate(
				{
					right: disableNext ? buttonWidth * -1 : 0
				}, settings.slideAnimationTime);
			});
			
			// updatethumbstate event: Update the state of the slide thumbnails.
			$viewport.bind('updatethumbstate', function(e)
			{
				var $items    = $viewport.find('.slideItem');
				var $currItem = $viewport.find('.slideItem.current');
				
				// Get index of current item.
				var itemIndex = $.inArray($currItem.get(0), $items);
				
				if(itemIndex != -1)
				{
					// Change 'current' state of thumbs.
					var $thumbs = $viewport.next('.bannerThumbs').find('li');
					$thumbs.removeClass('current');
					
					// Update thumb at the current index to be the 'current' thumb.
					var $slideThumb = $($viewport.next('.bannerThumbs').find('li').get(itemIndex));
					$slideThumb.addClass('current');
				}
			});
			
			// updatethumbpagestate event: Update the page of the slide thumbnails.
			$viewport.bind('updatethumbpagestate', function(e)
			{
				var $thumbList;
				if($viewport.next('.bannerThumbs').find('.collection').size() > 0)
					$thumbList = $viewport.next('.bannerThumbs').find('.collection');
				else
					$thumbList = $viewport.next('.bannerThumbs').find('ul');
				var $thumbViewport = $viewport.next('.bannerThumbs').find('.viewport');
				
				var orientation = $viewport.next('.bannerThumbs').hasClass('orientation-horizontal') ? 'horizontal' : 'vertical';
				
				var currOffset;
				var viewportSize;
				if(orientation == 'horizontal')
				{
					currOffset   = $thumbList.position().left;
					viewportSize = $thumbViewport.width();
				}
				else
				{
					currOffset   = $thumbList.position().top;
					viewportSize = $thumbViewport.height();
				}
				
				// Determine page number.
				var currPageNumber = parseInt(currOffset * -1 / viewportSize) + 1;
				
				// Get current index.
				var $thumbs    = $viewport.next('.bannerThumbs').find('ul li');
				var $currThumb = $thumbs.filter('.current');
				var currThumbIndex = $.inArray($currThumb.get(0), $thumbs);
				
				// Get target page.
				//var pageSize = 6;
				var pageSize = $viewport.data('pageSize');
				
				var targetPage = Math.ceil((currThumbIndex + 1) / pageSize);
				
				// Get direction based on target and current pages.
				if(currPageNumber == targetPage) return false;
				
				var direction = currPageNumber < targetPage ? 1 : -1;
				
				if(direction == 1)
					$viewport.next('.bannerThumbs').find('.pager.next').trigger('click');
				else
					$viewport.next('.bannerThumbs').find('.pager.prev').trigger('click');
			});
			
			// updatethumbpagerstate event: Update the state of the slide thumbnail pagers.
			$viewport.bind('updatethumbpagerstate', function(e)
			{
				// Animate viewport.
				var $thumbList;
				if($viewport.next('.bannerThumbs').find('.collection').size() > 0)
					$thumbList = $viewport.next('.bannerThumbs').find('.collection');
				else
					$thumbList = $viewport.next('.bannerThumbs').find('ul');
				var $thumbViewport = $viewport.next('.bannerThumbs').find('.viewport');
				
				// Reenable pagers.
				$viewport.next('.bannerThumbs').find('.pager').removeClass('disabled');
				
				var orientation = $viewport.next('.bannerThumbs').hasClass('orientation-horizontal') ? 'horizontal' : 'vertical';
				
				var currOffset;
				var viewportSize;
				var listSize;
				if(orientation == 'horizontal')
				{
					currOffset   = $thumbList.position().left;
					viewportSize = $thumbViewport.width();
					listSize     = $thumbList.width();
				}
				else
				{
					currOffset   = $thumbList.position().top;
					viewportSize = $thumbViewport.height();
					listSize     = $thumbList.height();
				}
				
				// Disable appropriate pagers.
				if(currOffset == 0)
					$viewport.next('.bannerThumbs').find('.pager.prev').addClass('disabled');
				if(viewportSize >= listSize + currOffset)
					$viewport.next('.bannerThumbs').find('.pager.next').addClass('disabled');
				
				// Animate pagers in/out.
				$viewport.next('.bannerThumbs').find('.pager:not(.disabled)').animate({opacity: 1});
				$viewport.next('.bannerThumbs').find('.pager.disabled').animate({opacity: 0.2});
			});
		})($viewport);
	});
	return this;
};
	
})(jQuery);
