(function($) {
	$.fn.infiniteCarousel = function() {
		
		function repeat(str, n) {
			return new Array( n + 1).join(str);
		}
		
		return this.each(function() {
			
			var $wrapper = $('#wrapper', this).css('overflow', 'hidden'),
				$slider = $wrapper.find('> ul').width(9999),
				$items = $slider.find('> li'),
				$single = $items.filter(':first')
				
				singleWidth = $single.outerWidth(),
				visible = Math.round($wrapper.innerWidth() / singleWidth),
				currentPage = 1,
				pages = Math.round($items.length / visible);
				
				/* Tasks */
				
				// Pad pages with empty elements if required
				if($items.length % visible != 0) {
					$slider.append(repeat('<li class="empty" />', visible - ($items.length % visible)));
					$items = $slider.find('> li');
				}
				
				// Create the carousel padding on the left and right (cloned)
				$items.filter(':first').before($items.slice(-visible).clone().addClass('cloned'));
				$items.filter(':last').after($items.slice(0, visible).clone().addClass('cloned'));
				$items = $slider.find('> li');
				
				// reset scroll bar
				$wrapper.scrollLeft(singleWidth * visible);
				
				// Paging function
				function gotoPage(page) {
					var dir = page < currentPage ? -1 : 1,
						n = Math.abs(currentPage - page),
						left = singleWidth * dir * visible * n;
						
					$wrapper.filter(':not(:animated)').animate({
						scrollLeft : '+=' + left
					}, '', function() {
						if(page > pages) {
							$wrapper.scrollLeft(singleWidth * visible);
							page = 1;
						}else if(page == 0) {
							page = pages;
							$wrapper.scrollLeft(singleWidth * visible * pages);
						}
						currentPage = page;
					});
				}
				
				window.gotoPage = gotoPage;
				
				// Insert the back and foward images
				$wrapper.after('<a href="#" class="arrow back">&lt;</a><a href="#" class="arrow forward">&gt;</a>');
				
				// Bind the back and foward links
				$('a.back', this).click(function() {
					gotoPage(currentPage - 1);
					return false
				});
				$('a.forward', this).click(function() {
					gotoPage(currentPage + 1);
					return false;
				});
		});
		
	};
})(jQuery);