
(function ($) {
	/* Add carousel to jQuery namespace */
	$.extend({
	caro : new function() {
		/* Write the initial numbered slide chooser */
		function writeChoose(c, slides) {
			for(i=0; i<c.totalSlides; i++) {
				if(c.currentSlide == i) {
					$(c.navChoose, c.carousel).append('<span style="font-weight: bold;">'+(i+1)+'</span> - ');
				}
				else {
					if(i < c.totalSlides-1) {
						$(c.navChoose, c.carousel).append('<a href="javascript:;" rel="'+i+'">'+(i+1)+'</a> - ');
					}
					else {
						$(c.navChoose, c.carousel).append('<a href="javascript:;" rel="'+i+'">'+(i+1)+'</a>');
					}
					
					$((c.navChoose + ' > *:eq('+i+')'), c.carousel).click(function() {
						changeToSlide(c, slides, $(this).attr('rel'));
						return false;
					});
				}
			}
		}
	
		/* Update the numbered slide chooser */
		function updateChoose(c, slides) {
			var nums = $((c.navChoose + ' > *'), c.carousel);
			
			for(i=0; i<c.totalSlides; i++) {
				if(c.currentSlide == i) {
					$(nums[i]).replaceWith('<span style="font-weight: bold;">'+(i+1)+'</span>');
				}
				else if(prevSlide == i) {
					$(nums[i]).replaceWith('<a href="javascript:;" rel="'+i+'">'+(i+1)+'</a>');
					
					$((c.navChoose + ' > *:eq('+i+')'), c.carousel).click(function() {
						changeToSlide(c, slides, $(this).attr('rel'));
						return false;
					});
				}
			}
		}

		/* Turn a slide off without animating */
		function hideSlide(c, slides) {
			$(slides[c.currentSlide]).hide();
		}
		
		/* Turn a slide on without animating */
		function showSlide(c, slides) {
			$(slides[c.currentSlide]).show();
		}
		
		/* Manually change display to given slide */
		function changeToSlide(c, slides, index) {
			config.autoScroll = false;
			
			if(isAnimating) {
				$(slides[c.currentSlide]).stop(true, true);
				isAnimating = false;
			}
			
			hideSlide(c, slides);
			
			prevSlide = c.currentSlide;
			c.currentSlide = index;
			
			showSlide(c, slides);
			updateChoose(c, slides);
		}
		
		/* Fade given slide in with callback */
		function fadeSlideIn(c, slides, index, callback) {
			$(slides[index]).fadeIn(c.fadeSpeed, callback);
		}
		
		/* Fade given slide out */
		function fadeSlideOut(c, slides, index) {
			$(slides[index]).fadeOut(c.fadeSpeed);
		}
		
		/* Handle manual selection of next slide */
		function nextSlide(c, slides) {
			config.autoScroll = false;
			
			if(isAnimating) {
				$(slides[c.currentSlide]).stop(true, true);
				isAnimating = false;
			}
			else {
				hideSlide(c, slides);
				
				prevSlide = c.currentSlide;
				
				if(c.currentSlide == c.totalSlides-1) {
					c.currentSlide = 0;
				}
				else {
					c.currentSlide++;
				}
				
				showSlide(c, slides);
				updateChoose(c, slides);
			}
		}
		
		/* Handle manual selection of previous slide */
		function previousSlide(c, slides) {
			config.autoScroll = false;
			
			if(isAnimating) {
				$(slides[c.currentSlide]).stop(true, true);
				isAnimating = false;
			}
			else {
				hideSlide(c, slides);
				
				prevSlide = c.currentSlide;
				
				if(c.currentSlide == 0) {
					c.currentSlide = c.totalSlides-1;
				}
				else {
					c.currentSlide--;
				}
				
				showSlide(c, slides);
				updateChoose(c, slides);
			}
		}
		
		/* Handle the automatic circular transition of slides */
		function animateSlide(c, slides) {			
			$(slides[c.currentSlide]).animate({top:'1'}, c.autoScrollDelay, null, function() {
				/* Check if we still want to animate */
				if(!c.autoScroll) {
					return false;
				}
				
				prevSlide = c.currentSlide;
				
				if(c.currentSlide == c.totalSlides-1) {
					c.currentSlide = 0;
				}
				else {
					c.currentSlide++;
				}
				
				isAnimating = true;
				
				fadeSlideOut(c, slides, prevSlide);

				fadeSlideIn(c, slides, c.currentSlide, function() {
					isAnimating = false;
					updateChoose(c, slides);
				});							
				
				/* Check if we want to animate next slide */
				if(c.autoScroll) {
					animateSlide(c, slides);
				}
			});
		}
		
		/* internal vars */
		var isAnimating = false;
		var prevSlide = 0;
	
		/* publicly configurable vars */
		this.defaults = {
			navBox : '.carousel-nav',
			slidesBox : '.carousel-slides',
			slide : '.slide',
			navChoose : '.choose',
			navPrev : '.carousel-prev',
			navNext : '.carousel-next',
			currentSlide : 0,
			totalSlides : 3,
			fadeSpeed : 2000,
			autoScroll : true,
			autoScrollDelay : 5000
		};
		
		/* Constructor */
		this.construct = function(settings) {
			/* Return object */
			return this.each(function() {
				/* make config */
				config = $.extend(this.config, $.caro.defaults, settings);
				
				config.carousel = this; 
				slides = $(config.slide, config.carousel);
				
				showSlide(config, slides);
				writeChoose(config, slides);
				
				$(config.navNext, config.carousel).click(function() {
					nextSlide(config, slides);
					return false;
				});
				
				$(config.navPrev, config.carousel).click(function() {
					previousSlide(config, slides);
					return false;
				});
				
				/* auto scroll */
				if(config.autoScroll) {
					animateSlide(config, slides);
				}
			});
		}
	}
	});

	/* Add constructor to function namespace */
	$.fn.extend({
	caro : $.caro.construct
	});
  
})(jQuery);