(function(){
	/*
	 * jQuery Carousel
	 * Infinite Carousel
	 *
	 * @author Lee Boonstra
	 *
	 * @uses jQuery 1.2.6, <http://www.jquery.com>
	 */
	$.fn.Carousel = function(){
		
		function repeat(str,i){
			return new Array(i + 1).join(str);
		}
		
		return this.each(function(){	
			var $elWrapper = $('> div', this).css('overflow','hidden'),
				$elSlider = $elWrapper.find('> ul').width(9999),
				$arrItems = $elSlider.find('> li'),
				$elItem = $arrItems.filter(':first'),
			
				intItemWidth = $elItem.outerWidth(),
				intViewportItems = Math.ceil($elWrapper.innerWidth() / intItemWidth),
				intCurrentPage = 1,
				intTotalPages = Math.ceil($arrItems.length / intViewportItems)


							
				/* Seperate all the items with empty blocks, and then clone the whole list in DOM */
				if($arrItems.length % intViewportItems != 0){
					var intNrEmptyItems = intViewportItems - ($arrItems.length % intViewportItems);
					$elSlider.append(repeat('<li class="empty" />',intNrEmptyItems));
					$arrItems = $elSlider.find('> li');
				}					
				$arrItems.filter(':first').before($arrItems.slice(- intViewportItems).clone().addClass('cloned'));
				$arrItems.filter(':last').after($arrItems.slice(0, intViewportItems).clone().addClass('cloned'));
				
				//update the items
				$arrItems = $elSlider.find('> li');
				//reset scroll
				$elWrapper.scrollLeft(intItemWidth * intViewportItems);
				
				/*
				 * Paging function, animate to the next 'page'.
				 * @param nextPage - int next page number
				 */
				function goToPage(nextPage){
					var direction = 1;
					if(nextPage < intCurrentPage){
						direction = -1;
					}
					var intNrOfPages = Math.abs(intCurrentPage - nextPage),
						intLeftPos = intItemWidth * direction * intViewportItems * intNrOfPages;
					
					$elWrapper.filter(':not(:animated)').animate({
						scrollLeft: '+=' + intLeftPos
					}, 500, function(){
					
						if (nextPage == 0) {
							$elWrapper.scrollLeft(intItemWidth * intViewportItems * intTotalPages);
							nextPage = intTotalPages;
						} else if (nextPage > intTotalPages) {
							$elWrapper.scrollLeft(intItemWidth * intViewportItems);
							nextPage = 1;
						}
						intCurrentPage = nextPage;
					})
				}
				

				/*
				 * Bind the back, forward and paginator functions
				 */
				$elWrapper.after('<a href="#" class="arrow back">&lt;</a><a href="#" class="arrow forward">&gt;</a>')
				
				$('a.back', this).click(function(){
					goToPage(intCurrentPage-1);
					return false;
				})	
				$('a.forward', this).click(function(){
					goToPage(intCurrentPage+1);
					return false;
				})	
				// paginator
				$(this).bind('paginator', function(e,page){
					goToPage(page);
				})			
		
		});
	};
})(jQuery);
