(function($){
	$.fn.slideShow = function(options) {
		
		// multiple elements
		if (this.length > 1) {
			this.each(function() { $(this).slideShow(options)});
			return this;
		}

		// private vars
		this.defaults = {
			start: 			0,		// start index, set to 'random' or 'rnd' to random start
			interval: 		3,		// interval, autoplay, set to false for no auto-play, in seconds
			repeat: 		true,	// repeat at the end
			transition: {
				mode: 'fade',
				speed: 1000
			},
			gotoSlide: 		false	// slide change callback
		};
		this.options = $.extend({}, this.defaults, options);
		
		// internal vars
		this.numSlides = this.find('.slide').length;
		if (this.options.start == 'random' || this.options.start == 'rnd') {
			this.current = Math.floor(Math.random() * this.numSlides) + 1;
		} else {
			this.current = this.options.start;
		}
		if (this.current >= this.numSlides) {
			this.current = this.numSlides - 1;
		}
		this.last = false;
		this.elm = $(this);
		this.interval = false;
		this.mouse = {over: false};
		
		// init slideshow
		this.init = function(){
			this.find('.slides').mouseenter(function(){ $("ul.navigation_slides").css("visibility","visible");});
			this.find('.slides').mouseleave(function(){ $("ul.navigation_slides").css("visibility","hidden");});

			// set slides to be positioned absolute
			this.find('.slide').css('position','absolute');
			// hide slides if not hidden allready
			this.find('.slide:not(:eq(' + this.current + '))').hide();
			
			// navigation_slides shortcuts
			this.find('#first, #next, #prev, #last, #page, .slide, .slides, .navigation_slides').data('slideShow', this);
			this.find('#first').click(this.first);
			this.find('#next').click(this.next);
			this.find('#prev').click(this.previous);
			this.find('#last').click(this.last);
			
			// init pagínation buttons if available
			this.find('.navigation_slides #page:eq(' + this.current + ')').addClass('selected');
			this.find('#page').click(function() {
				if (!(slideShow = $(this).data('slideShow'))) {
					var slideShow = this;
				}
				// determine position in navigation_slides
				var index = $(this).html();
				if (!(index = parseInt($(this).html()))) {
					var index = $(this).parents('.navigation_slides').find('#page').index($(this));
				}
				slideShow.gotoSlide(index);
			});
			
			// mouse enter handler

			this.find('.slides').mouseenter(function() {
				var slideShow = $(this).data('slideShow');
				slideShow.mouse.over = true;
				slideShow.stopAuto();
			});
			
			// mouse leave handler
			this.find('.slides').mouseleave(function() {
				var slideShow = $(this).data('slideShow');
				slideShow.mouse.over = false;
				slideShow.auto();
			});

			g = this.current;
			this.current = -1;
			this.gotoSlide(g);
			// start interval for auto animation
			if (this.options.interval > 0) {
				this.auto();
			}
			return this;
		};
		
		// public methods
		this.auto = function() {
			if (!(slideShow = $(this).data('slideShow'))) {
				var slideShow = this;
			}
			if (!slideShow.interval && slideShow.options.interval > 0.001) {
				slideShow.interval = window.setInterval(function() {
					slideShow.next();
				}, slideShow.options.interval * 1000);
			}
			return this;
		}
		// check if slideshow is running
		this.isPlaying = function() {
			if (!(slideShow = $(this).data('slideShow'))) {
				var slideShow = this;
			}
			return slideShow.interval;
		}
		// stop/play slideshow automatic 
		this.togglePlayback = function() {
			if (!(slideShow = $(this).data('slideShow'))) {
				var slideShow = this;
			}
			if (slideShow.isPlaying()) {
				slideShow.stopAuto();
			} else {
				slideShow.auto();
			}
		},
		// stop automatic slideshow
		this.stopAuto = function() {
			if (!(slideShow = $(this).data('slideShow'))) {
				var slideShow = this;
			}
			if (slideShow.interval) {
				window.clearInterval(slideShow.interval);
				slideShow.interval = false;
			}
			return this;
		}
		// goto first slide
		this.first = function(elm) {
			if (!(slideShow = $(this).data('slideShow'))) {
				var slideShow = this;
			}
			return slideShow.gotoSlide(0);
		};
		// goto last slide
		this.next = function() {
			if (!(slideShow = $(this).data('slideShow'))) {
				var slideShow = this;
			}
			return slideShow.gotoSlide(slideShow.current + 1);
		};
		this.previous = function() {
			if (!(slideShow = $(this).data('slideShow'))) {
				var slideShow = this;
			}
			return slideShow.gotoSlide(slideShow.current - 1);
		};
		this.last = function() {
			if (!(slideShow = $(this).data('slideShow'))) {
				var slideShow = this;
			}
			return slideShow.gotoSlide(slideShow.numSlides);
		};
		this.gotoSlide = function(index, noanimation) {			
			if (index < 0) {
				index = this.numSlides - 1;
			}
			if (index >= this.numSlides) {
				index = 0;
			}
			if (index === this.current) return this;
			// get slide elements
			var oldSlide = this.find('.slide:eq(' + this.current +')');
			var newSlide = this.find('.slide:eq(' + index +')');
			// callbacks for animation finished
			oldFinished = function () {
				$(this).removeClass('selected');
				if (!(slideShow = $(this).data('slideShow'))) {
					var slideShow = this;
				}
				slideShow.elm.find('.navigation_slides #page:eq(' + slideShow.current + ')').addClass('selected');
				if (!slideShow.mouse.over) {
					slideShow.auto();
				}
			}
			newFinished = function() {
				if (!(slideShow = $(this).data('slideShow'))) {
					var slideShow = this;
				}
				slideShow.elm.find('.navigation_slides #page:not(:eq(' + slideShow.current + '))').removeClass('selected');
				$(this).addClass('selected');
			}
			// get slideshow
			if (!(slideShow = $(this).data('slideShow'))) {
				var slideShow = this;
			}
			slideShow.stopAuto();
			// call callback
			if (typeof(this.options.gotoSlide) == 'function') {
				this.options.gotoSlide(slideShow, index);
			}
			// start transition
			if (noanimation) {
				oldSlide.hide(1, oldFinished);
				newSlide.show(1, newFinished);
			} else {
				if (typeof(this.options.transition.mode) == 'function') {
					this.call(this.options.transition.mode, newSlide, oldSlide);
				} else {
					switch(this.options.transition.mode) {
						default:
						case 'fade':
							oldSlide.fadeOut(this.options.transition.speed, oldFinished);
							newSlide.fadeIn(this.options.transition.speed, newFinished);
							break;
					}
				}
			}
			this.last = this.current;
			this.current = index;
			return this;
		};
		
		return this.init();
	}
	
})(jQuery);