(function () {
    $.fn.infiniteCarousel = function (options) {
        function repeat(str, n) {
            return new Array( n + 1 ).join(str);
        }
		
		var defaults = {			
			speed: 			800,
			auto:			false,
			pause:			2000,
			numericId: 		'pagination'
		};
		
		var options = $.extend(defaults, options);  
        
        return this.each(function () {			
			var $this = $(this),
				$wrapper = $('> div', this).css('overflow', 'hidden'),
                $slider = $wrapper.find('> ul').width(9999),
                $items = $slider.find('> li'),
                $single = $items.filter(':first')
                
                singleWidth = $single.outerWidth(),
                visible = Math.ceil($wrapper.innerWidth() / singleWidth),
                $this.data('pages', Math.ceil($items.length / visible));
				$this.data('currentPage', 1);
                
            /* TASKS */
            
            // 1. pad the pages with empty element if required
            if ($items.length % visible != 0) {
                // pad
                $slider.append(repeat('<li class="empty" />', visible - ($items.length % visible)));
                $items = $slider.find('> li');
            }
			
			// 1.5 add the numeric navigation
			
				var temphtml = '<ol class="numeric" id="'+ options.numericId +'"></ol>';
				$this.append(temphtml);
				
				var numitems = $("li", $this).length;
				for(var i=0;i<numitems;i++){						
					$(document.createElement("li"))
						.attr('id',options.numericId + (i+1))
						.html('<a rel='+ i +' href="">'+ (i+1) +'</a>')
						.appendTo($("#"+ options.numericId))
						.click(function(event){
							event.preventDefault();		
							event.stopPropagation();
							gotoPage(parseInt($("a",$(this)).attr('rel'))+1);
							return false;
						}); 	
				};
				
				if (numitems==1){
					$("#"+ options.numericId).hide();
				}
				
				// 5. insert the back and forward link after the numeric navigation
				$("#"+ options.numericId).prepend('<li><a href="#" class="back">&lt;</a></li>');
				$("#"+ options.numericId).append('<li><a href="#" class="forward">&gt;</a></li>');
				
					            
            // 2. create the carousel padding on left and right (cloned)
            $items.filter(':first').before($items.slice(-(visible*2)).clone().addClass('cloned'));
            $items.filter(':last').after($items.slice(0, (visible*2)).clone().addClass('cloned'));
            $items = $slider.find('> li');
            
            // 3. reset scroll
            $wrapper.scrollLeft(singleWidth * (visible+1));
            
			$('#'+options.numericId+'1').addClass('current');

            // 4. paging function
            function gotoPage(page) {
				$('.current',$this).removeClass('current');
				
				if (page > ($this.data('pages'))) {
					$('#'+options.numericId+'1').addClass('current');						
				} else if (page < 1) {
					$('#'+options.numericId+$this.data('pages')).addClass('current');
				}else {
					$('#'+options.numericId+page).addClass('current');	
				}
				
                var dir = page < $this.data('currentPage') ? -1 : 1,
                    n = Math.abs($this.data('currentPage') - page),
                	left = singleWidth * dir * visible * n;

 		           	$wrapper.filter(':not(:animated)').animate(
					{ scrollLeft : '+=' + left }, // what we are animating
					{
						duration: options.speed, // how fast we are animating
						easing: 'swing', // the type of easing
						complete: function() { // the callback
							// if page == last page - then reset position
							if (page > ($this.data('pages'))) {
								$wrapper.scrollLeft(singleWidth * (visible * 2));
								page = 1;								
							} else if (page < 1) {
								page = $this.data('pages');
								$wrapper.scrollLeft(singleWidth * ($this.data('pages') + 1));
							}
							$this.data('currentPage',page);
							
						}
				});
			}
			
            
            // 6. bind the back and forward links
            $('a.back', this).click(function () {
                gotoPage(parseInt($this.data('currentPage')) - 1);
                return false;
            });
            
            $('a.forward', this).click(function () {
                gotoPage(parseInt($this.data('currentPage')) + 1);
                return false;
            });
            
            $(this).bind('goto', function (event, page) {
                event.stopPropagation();
				gotoPage(page);
				return false;
            });
            
            // THIS IS NEW CODE FOR THE AUTOMATIC INFINITE CAROUSEL
            $(this).bind('next', function () {
                gotoPage(parseInt($this.data('currentPage')) + 1);
            });
			
			if (options.auto && numitems>1) {
				var autoscrolling = true;
	
				$(this).mouseover(function () {
					autoscrolling = false;
				}).mouseout(function () {
					autoscrolling = true;
				});
				
				setInterval(function () {
					if (autoscrolling) {
						$this.trigger('next');
					}
				}, options.pause);
			}
			
        });
    };

	
	
	
})(jQuery);