$.fn.slideshow = function(slideshowOptions) {
	var container = $(this);
	
	// options
	container.data("slideshowOptions", slideshowOptions);
	container.data("slideshowCurrentSlideIndex", 0);
	container.data("slideshowIsTransitioning", false);
	
	// setup functions
	container.slideshowGetOptions = function() {
		return container.data("slideshowOptions");
	};
	
	container.slideshowCancelEvent = function() {
		if (container.data("slideshowTimeout")) {
			clearTimeout(container.data("slideshowTimeout"));
		}
	}
	
	container.slideshowScheduleAutoScroll = function() {
		var slideshowOptions = container.slideshowGetOptions();
		
		this.slideshowCancelEvent();
		
		if (slideshowOptions.autoScroll.delay) {
			container.data("slideshowTimeout", setTimeout(container.slideshowScrollAndSchedule, slideshowOptions.autoScroll.delay));
		}
	};
	
	container.slideshowScrollAndSchedule = function() {
		container.slideshowScroll(container.slideshowGetOptions().autoScroll.direction);
		container.slideshowScheduleAutoScroll();
	};
	
	container.slideshowScroll = function(direction) {
		container.slideshowScrollTo(container.slideshowGetCurrentSlideIndex() + direction);
	}
	
	container.slideshowGetCurrentSlideIndex = function() {
		return container.data("slideshowCurrentSlideIndex");
	};
	
	container.slideshowGetSlides = function() {
		if (container.slideshowGetOptions().transition.type == "slide") {
			return container.data("slideshowSlideHolder").children();
		}
		
		return container.children();
	};
	
	container.slideshowTransitionInit = function() {
		if (container.slideshowGetOptions().transition.type == "slide") {
			container.css("overflow", "hidden");
			var slideHolder = $(document.createElement("div"));
			
			slideHolder.css({
				position: "relative",
				width: "960px",
				height: "300px"
			});
			
			slideHolder.append(container.children());
			container.append(slideHolder);
			
			var i = 0;
			
			$.each(slideHolder.children(), function() {
				$(this).css("left", (i * container.width()) + "px");
				i ++;
				
				$(this).show();
			});
			
			container.data("slideshowSlideHolder", slideHolder);
		}
	}
	
	container.slideshowTransitionStop = function() {
		container.data("slideshowIsTransitioning", true);
		
		if (container.slideshowGetOptions().transition.type == "slide") {
			var slideHolder = container.data("slideshowSlideHolder");
			slideHolder.stop(true);
		} else if (container.slideshowGetOptions().transition.type == "fade") {
			container.children().stop(true);
		}
	};
	
	container.slideshowShowSlide = function(slideIndex, isFirst) {
		var oldSlideIndex = container.slideshowGetCurrentSlideIndex();
		var oldSlide = $(container.slideshowGetSlides()[oldSlideIndex]);
		
		var newSlide = $(container.slideshowGetSlides()[slideIndex]);
		
		if (container.slideshowGetOptions().transition.type == "slide") {
			container.data("slideshowIsTransitioning", true);
			
			var slideHolder = container.data("slideshowSlideHolder");
			var position = slideHolder.position();
			var currentX = position.left;
			
			var neededX = - (container.width() * slideIndex);
			
			if (isFirst) {
				slideHolder.css("left", neededX + "px");
				container.data("slideshowIsTransitioning", false);
			} else {
				slideHolder.animate({
					left: neededX + "px"
				}, 1500, "easeOutExpo", function() {
					container.data("slideshowIsTransitioning", false);
				});
			}
			return;
		} else if (container.slideshowGetOptions().transition.type == "fade") {
			if (oldSlideIndex != slideIndex) {
				var duration = container.slideshowGetOptions().transition.duration;
				
				oldSlide.fadeOut(duration);
				newSlide.fadeIn(duration);
			} else {
				newSlide.show();
			}
			
			return;
		}
		
		if (oldSlide) {
			oldSlide.hide();
		}
		
		newSlide.show();
	};
	
	container.slideshowScrollTo = function(oldIndex) {
		if (container.data("slideshowIsTransitioning")) {
			container.slideshowTransitionStop();
		}
		
		// test index to see if it's out of bounds
		var index = oldIndex;
		var slides = container.slideshowGetSlides();
		
		if (index < 0) {
			index = index % slides.length;
			index = slides.length + index;
		}
		
		var newIndex = index % slides.length;
		
		if (oldIndex != newIndex) {
			return container.slideshowScrollTo(newIndex);
		}
		
		// now, scroll
		container.slideshowShowSlide(index, false);
		
		// set new index
		container.data("slideshowCurrentSlideIndex", index);
	}
	
	// some CSS
	container.css({
		position: "relative"
	});
	
	// setup the images to display
	$.each(container.children(), function() {
		// basic image properties
		$(this).css({
			position: "absolute",
			top: "0px",
			left: "0px",
			width: container.width() + "px",
			height: container.height() + "px",
			backgroundImage: "url(" + $(this).children("img").attr("src") + ")"
		});
		
		$(this).children("img").remove();
		$(this).hide();
	});
	
	// transition setup
	container.slideshowTransitionInit();
	
	// button setup
	if (slideshowOptions.navButtons) {
		slideshowOptions.navButtons.left.click(function(e) {
			container.slideshowScroll((- 1));
			
			container.slideshowCancelEvent();
			container.slideshowScheduleAutoScroll();
			
			e.preventDefault();
			return false;
		});
		
		slideshowOptions.navButtons.right.click(function(e) {
			container.slideshowScroll(1);
			
			container.slideshowCancelEvent();
			container.slideshowScheduleAutoScroll();
			
			e.preventDefault();
			return false;
		});
	}
	
	// show the first image
	container.slideshowShowSlide(0, true);
	
	if (slideshowOptions.autoScroll.delay) {
		container.slideshowScheduleAutoScroll();
	}
}
