(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
    };
	
	var timer;
	var slides;
	var numOfSlides;
	var carouselWidth;
	var carouselHeight;
	
	var slide;
	
	var setup = function(carousel){
		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});	
			});
		} else if(settings.effect == 'slideLeft') {
			slides.show().each(function(num){
				$(this).css({left: (num + 1 - slide) * carouselWidth,top: 0});
			});
		} else if(settings.effect == 'fade'){
			slides.css({left: 0,top: 0}).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.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(){
				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;
				}
				
				if(settings.effect == 'fade'){
					slides.fadeOut(settings.speed*1000);
					slides.eq(newSlide-1).fadeIn(settings.speed*1000);
				} else if(settings.effect == 'slideDown') {
					slides.each(function(num){
						$(this).animate({
							'top': - (num + 1 - newSlide) * carouselHeight
						},settings.speed*1000);
					});
				} else if(settings.effect == 'slideLeft'){
					slides.each(function(num){
						$(this).animate({
							'left': (num + 1 - newSlide) * carouselWidth
						},settings.speed*1000);
					});
				} else {
					$.error('Effect ' +  settings.effect + ' does not exist in jquery-nworx-carousel');
				}

				slide = newSlide;
				
				// 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);
