(function($){
	// Set the default settings
	var settings = {
		effect: 'fade',		// Transition effect: fade, slideDown, slideLeft
		speed: 3,			// Speed of effect transition in sec
		delay: 7,			// Time each slide is shown in sec
		slide: 1, 			// Starting slide number
		play: 'forward', 	// Automatic play: forward, reverse, pause
		loop: 'reset',		// Type of loop: continuous, reset
		dots: true			// Create the slide dots
    };
	
	var timer;
	var slides;
	var numOfSlides;
	var carouselWidth;
	var carouselHeight;
	var dots;
	
	var slide;
	
	var setup = function(carousel){
		carousel.css({position: 'relative'});
		carouselWidth = carousel.width();
		carouselHeight = carousel.height();
		slides = carousel.children();
		numOfSlides = slides.size();
		initialiseSlides();
	}
	
	var initialiseSlides = function(){
		if(settings.effect == 'slideDown'){
			slides.show().each(function(num){
				$(this).css({top: - (num + 1 - slide) * carouselHeight,left: 0,position: 'absolute'});	
			});
		} else if(settings.effect == 'slideLeft') {
			slides.show().each(function(num){
				$(this).css({left: (num + 1 - slide) * carouselWidth,top: 0,position: 'absolute'});
			});
		} else if(settings.effect == 'fade'){
			slides.css({left: 0,top: 0,position: 'absolute'}).not(':eq('+(slide-1)+')').hide();
			slides.eq(slide-1).fadeIn(settings.speed * 1000);
		} else {
			$.error('Effect ' +  settings.effect + ' does not exist in jquery-nworx-carousel');
		}
	}
	
	// Declare the plugin methods
	var methods = {
		// Initialise the carousel
	    init : function(options){
			// Merge the default and optional settings
			if(options){ 
				$.extend(settings,options);
		    }
			slide = settings.slide;
			
			return this.each(function(){
				var carousel = $(this);
				setup(carousel);
				
				if(settings.dots){
					dots = $('<ul class="carousel-dots"></ul>');
					slides.each(function(index){
						var active = '';
						if(slide == index+1){
							active = ' active';
						}
						dots.append('<li class="carousel-dot dot-'+(index+1)+active+'"><a href="#" title="'+(index+1)+'">&bull;</a></li>');
						dots.children(':eq('+index+')').children('a').click(function(){
							if(!$(this).parent().hasClass('disabled')){
								carousel.carousel('step',index+1);
							}
							return false;
						});
					});
					dots.insertAfter(carousel);
				}
				
				if(settings.play == 'forward'){
					$(this).carousel('play');
				} else if(settings.play == 'reverse'){
					$(this).carousel('reverse');
				} else {
					$.error('Play setting ' +  settings.play + ' does not exist in jquery-nworx-carousel');
				}
			});
			
		},
		update : function(options){
			// Merge the default and optional settings
			if(options){ 
				$.extend(settings,options);
		    }
			
			return this.each(function(){
				var carousel = $(this);
				setup(carousel);
			});
		},
		loop: function(){
			return this.each(function(){
				if(settings.play == 'reverse'){
					$(this).carousel('prev');
				} else {
					$(this).carousel('next');
				}
			});
		},
		// Play the carousel
	    play : function(){
			return this.each(function(){
				clearTimeout(timer);
				$(this).carousel('update',{
					play: 'forward'
				})
				timer = setTimeout(function(){$(this).carousel('loop');},settings.delay*1000);
			});
		},
		// Play the carousel backwards
	    reverse : function(){
			return this.each(function(){
				clearTimeout(timer);
				$(this).carousel('update',{
					play: 'reverse'
				})
				timer = setTimeout(function(){$(this).carousel('loop');},settings.delay*1000);
			});
		},
		// Pause the carousel
	    pause : function(){
			return this.each(function(){
				clearTimeout(timer);
				settings.play == 'pause';
			});
		},
		// Step the carousel onwards
	    rewind : function(){
			return this.each(function(){
				$(this).carousel('step',settings.slide);
			});
		},
		// Step the carousel onwards
	    next : function(){
			return this.each(function(){
				$(this).carousel('step',slide + 1);
			});
		},
		// Step the carousel backwards
	    prev : function(){
			return this.each(function(){
				$(this).carousel('step',slide - 1);
			});
		},
		// Step the carousel to a slide
	    step : function(toSlide){
			return this.each(function(){
				dots.children().addClass('disabled');
				clearTimeout(timer);
				var carousel = $(this);
				var newSlide;
				if(slide == numOfSlides && toSlide > numOfSlides){
					if(settings.loop == 'continuous'){
						slide = 1;
						initialiseSlides();
						newSlide = numOfSlides + 1;
					} else {
						newSlide = 1;
					}
				} else if(slide == 1 && toSlide < 1){
					if(settings.loop == 'continuous'){
						slide = numOfSlides;
						initialiseSlides();
						newSlide = 0;
					} else {
						newSlide = numOfSlides;
					}
				} else if(toSlide > numOfSlides){
					newSlide = numOfSlides;
				} else if(toSlide < 1){
					newSlide = 1;
				} else {
					newSlide = toSlide;
				}
				
				slide = newSlide;
				
				if(settings.effect == 'fade'){
					slides.fadeOut(settings.speed*1000);
					slides.eq(slide-1).fadeIn(settings.speed*1000,function(){
						dots.children().removeClass('disabled');
					});
				} else if(settings.effect == 'slideDown') {
					slides.each(function(num){
						$(this).animate({
							'top': - (num + 1 - slide) * carouselHeight
						},settings.speed*1000,
						function(){
							dots.children().removeClass('disabled');
						});
					});
				} else if(settings.effect == 'slideLeft'){
					slides.each(function(num){
						$(this).animate({
							'left': (num + 1 - slide) * carouselWidth
						},settings.speed*1000,
						function(){
							dots.children().removeClass('disabled');
						});
					});
				} else {
					$.error('Effect ' +  settings.effect + ' does not exist in jquery-nworx-carousel');
				}

				dots.children().removeClass('active').eq(slide-1).addClass('active');
				
				// Create the next step transition if required
				if(settings.play == 'forward' || settings.play == 'reverse'){
					timer = setTimeout(function(){$(this).carousel('loop');},settings.delay*1000);
				}
				//console.log(slide);
			});
		},
		slideLeft : function(direction){
			if(!direction){
				direction = 'forward';
			}
			return this.each(function(){
				$(this).carousel('update',{
					effect: 'slideLeft',
					play: direction
				});
			});
		},
		slideDown : function(direction){
			if(!direction){
				direction = 'forward';
			}
			return this.each(function(){
				$(this).carousel('update',{
					effect: 'slideDown',
					play: direction
				});
			});
		},
		fade : function(direction){
			if(!direction){
				direction = 'forward';
			}
			return this.each(function(){
				$(this).carousel('update',{
					effect: 'fade',
					play: direction
				});
			});
		}
		
	};
		
	$.fn.carousel = function(method){
		// Method calling logic
	    if(methods[method]) {
	      return methods[method].apply(this, Array.prototype.slice.call(arguments,1));
	    } else if(typeof method === 'object' || ! method ) {
	      return methods.init.apply(this, arguments);
	    } else {
	      $.error('Method ' +  method + ' does not exist in jquery-nworx-carousel');
	    }
	};
})(jQuery);
