(function($){
	
	$.fn.slideshow = function(options){
		if (options === undefined || options === null)
		{
			options = {};
		}
		
		if(!(options.constructor == String) && !(options.constructor == Number))
		{
			options = $.extend({}, $.fn.slideshow.defaults, options);
		}
		
		return this.each(function(){
			var $this = $(this);
									
			if(options.constructor == String) {
				var options2 = $this.data('options');
				
				if(options2 !== undefined && options2 !== null) {
					if(options == 'play') {
						$.fn.slideshow.play($this);
					} else if(options == 'pause') {
						$.fn.slideshow.pause($this);
					} else if(options == 'toggle') {
						$.fn.slideshow.toggle($this);
					} else if(options == 'next') {
						$.fn.slideshow.rotateImages($this, 'next');
					} else if(options == 'prev') {
						$.fn.slideshow.rotateImages($this, 'prev');
					}
				}
			} else if(options.constructor == Number) {
				var options2 = $this.data('options');
				
				if(options2 !== undefined && options2 !== null) {
					$.fn.slideshow.rotateImages($this, options);
				}
			} else {
				$this.data('options', options);
				$this.data('rotating', false);
				
				var $images = $(options.selector, $this);
				
				$images.each(function(i){
					$(this).data('offset', i);
				});
				
				$images.hide().filter(':first').show().end();
				
				if(options.imageClick != null) {
					$images.click(options.imageClick);
				}
				
				options.intervalId = setInterval(function(){$.fn.slideshow.rotateImages($this, 'next');}, options.speed); 
							
				if(options.alt !== null) {
					$(options.alt).html($('> img:visible', $this).attr('alt'));
				}	
				
				if(options.next !== null) {
					$(options.next).click(function(){
						$.fn.slideshow.rotateImages($this, 'next');
						return false;
					});
				}
				
				if(options.prev !== null) {
					$(options.prev).click(function(){
						$.fn.slideshow.rotateImages($this, 'prev');
						return false;
					});
				}
				
				if(options.toggle !== null) {
					$(options.toggle).addClass('pause').click(function(){
						$.fn.slideshow.toggle($this);					
						return false;
					});
				}
				
				if(options.pager !== null) {
					var html = '';
					
					$images.each(function(i){
						var $this2 = $(this);
						html += '<img';
									
						var rel = $this2.attr('rel');
						if(rel !== undefined && rel !== null && rel != '') {
							html += ' src="' + rel + '"';  
						} else {
							html += ' src="' + $this2.attr('src') + '"';
						}
						
						if(options.thumbWidth !== null) {
							html += ' width="' + options.thumbWidth + '"';
						}
						
						if(options.thumbHeight !== null) {
							html += ' height="' + options.thumbHeight + '"';
						}
						
						html += ' />';
					});
					
					$pager = $(options.pager);
					$pager.css('position', 'relative').css('overflow-x', 'hidden');
					$pager.html(html);
					$pager.children().filter(':first').addClass('current').end();
					
					var left = 0;
					$pager.children().each(function(i){
						var $this2 = $(this);
						
						$this2.css('position', 'absolute').css('left', left);
						left += $this2.width() + options.thumbSpacing;
						
						$this2.click(function(){
							$.fn.slideshow.rotateImages($this, i);						
							return false;
						});
					});
					
					options.pagerWidth = left;
				}
				
				if(options.afterSetUp !== null) {
					options.afterSetUp();
				}
				
				$this.data('options', options);
			}
		});
	};
	
	$.fn.slideshow.defaults = {
		selector: '> img',
		speed: 4000,
		random: false,
		transitionFluid: false,
		transitionIn: 'fadeIn',
		transitionOut: 'fadeOut',
		transitionSpeed: 'slow',
		alt: null,
		next: null,
		prev: null,
		toggle: null,
		pager: null,
		thumbWidth: null,
		thumbHeight: null,
		thumbSpacing: 0,
		afterSetUp: null,
		imageClick: null,
		
		// Not setable
		intervalId: null,
		pagerWidth: null
	};
	
	$.fn.slideshow.rotateImages = function($this, nextImage){
		var options = $this.data('options');
		var rotating = $this.data('rotating');
		
		if(options !== undefined && options !== null && !rotating) {
			$this.data('rotating', true);
			
			var $images = $(options.selector, $this);
			
			var resetInterval = function()
			{
				clearInterval(options.intervalId);
				options.intervalId = setInterval(function() { $.fn.slideshow.rotateImages($this, 'next'); }, options.speed);
			};
			
			var transition = function($this2)
			{
				if($this2 === undefined || $this2 === null) {
					$this2 = $(this);
				}
				
				var offset = $this2.data('offset');
				
				if(!options.random)
				{
					if(nextImage == 'next')
					{
						if($this2.next().length != 0)
						{
							offset = $this2.next()[options.transitionIn](options.transitionSpeed, resetInterval).data('offset');
						}
						else
						{
							offset = $images.filter(':first')[options.transitionIn](options.transtionSpeed, resetInterval).data('offset');
						}
					}
					else if(nextImage == 'prev')
					{
						if($this2.prev().length != 0 && $this2.prev().is('img'))
						{
							offset = $this2.prev()[options.transitionIn](options.transitionSpeed, resetInterval).data('offset');
						}
						else
						{
							offset = $images.filter(':last')[options.transitionIn](options.transtionSpeed, resetInterval).data('offset');
						}
					}
					else
					{
						if($images.filter(':eq(' + nextImage + ')').length == 1) {
							offset = $images.filter(':eq(' + nextImage + ')')[options.transitionIn](options.transitionSpeed, resetInterval).data('offset');
						}
					}
				}
				else
				{
					var rand = offset;
					
					while(rand == offset) {
						 rand = Math.ceil(Math.random() * ($images.length - 1));
					}
					
					var $image = $images.filter(':eq(' + rand + ')');
					
					if($image.length != 0) {
						$image[options.transitionIn](options.transitionSpeed, resetInterval);
					}
					
					offset = rand;
				}
				
				if(options.alt !== null) {
					$(options.alt).html($images.filter(':eq(' + offset + ')').attr('alt'));
				}
				
				if(options.pager !== null)
				{
					var $pager = $(options.pager);
													
					$pager.children().removeClass('current').filter(':eq(' + offset + ')').addClass('current').end();
					
					$image = $pager.children().filter('.current');
															
					$pager.animate({
						scrollLeft: offset * (options.pagerWidth - $pager.width()) / $pager.children().length + offset * options.thumbSpacing
					}, 'fast', 'linear');
				}
				
				$this.data('rotating', false);
			};
									
			if(!options.transitionFluid)
			{
				$images.filter(':visible')[options.transitionOut](options.transitionSpeed, transition);
			}
			else
			{
				var $image = $images.filter(':visible');
				$image[options.transitionOut](options.transitionSpeed);
				transition($image);
			}
						
			$this.data('options', options);
		}
	};
	
	$.fn.slideshow.pause = function($this){
		var options = $this.data('options');
		
		if(options !== undefined && options !== null) {
			if(options.intervalId !== null) {
				clearInterval(options.intervalId);
				options.intervalId = null;
			}
			
			if(options.toggle !== null) {
				$(options.toggle).removeClass('pause').addClass('play');
			}
			
			$this.data('options', options);
		}
	};
	
	$.fn.slideshow.play = function($this){
		var options = $this.data('options');
		
		if(options !== undefined && options !== null) {
			if(options.intervalId === null) {
				options.intervalId = setInterval(function(){$.fn.slideshow.rotateImages($this, 'next');}, options.speed);
			}
				
			if(options.toggle !== null) {
				$(options.toggle).removeClass('play').addClass('pause');
			}
			
			$this.data('options', options);
		}
	};
	
	$.fn.slideshow.toggle = function($this){
		var options = $this.data('options');
		
		if(options !== undefined && options !== null) {
			if(options.intervalId !== null) {
				$.fn.slideshow.pause($this);				
			} else {
				$.fn.slideshow.play($this);	
			}
		}
	};
	
})(jQuery);