(function ($) {
	$.fn.slideshow = function (args) {
	  	var options = $.extend({}, $.fn.slideshow.defaults, args);	
		
	    
		return $(this).each(function(src) {
			$(this).html("");
			var cont = function(n) {
				to = setTimeout(nextImage, options.duration, null, false);
				n();
			}
			var animations = {
				"crossfade": function($current, $next, speed, direction, n) {
					if (speed > 0) {
						$current.css("top", $current.position().top).css("left", $current.position().left).css("position","absolute").fadeOut(speed);
						$next.fadeIn(speed, function() { cont(n); });
					} else {
						$next.fadeIn(0);
						cont(n);
					}
				},
		
				"slide": function($current, $next, speed, direction, n) {
					if (speed > 0) {
						var w = $current.width();
						var h = $current.height();
						if (direction == "left") {
							$next.show();
							$current.animate({ marginLeft: '-=' + w }, speed, "swing", function() { $(this).hide().css("margin-left","");cont(n); }) 
						} else if (direction == "right") {
							$next.css("margin-left",(-1*w)).show();
							$next.animate({ marginLeft: '+=' + w }, speed, "swing", function() { $current.hide();cont(n); }) 
						} else if (direction == "up") {
							$next.show();
							$current.animate({ marginTop: '-=' + h }, speed, "swing", function() { $(this).hide().css("margin-top","");cont(n); }) 
						} else if (direction == "down") {
							$next.css("margin-top",(-1*h)).show();
							$next.animate({ marginTop: '+=' + h }, speed, "swing", function() { $current.hide();cont(n); }) 
						}
					} else {
						$next.show();
						cont(n);
					}
				}
			}
			
			var opposite = {
				"left": "right",
				"right": "left",
				"up": "down",
				"down": "up"
			}
			var $this = $("<ul class=\"ss-wrapper\"></ul");
			if ((options.direction == "left") || (options.direction == "right")) $this.width((options.width * 3) + "px");
			$this.height(options.height + "px");
			$(this).css("position", "relative").append($this);
			
			var current = -1;
			var previous = -1;
			var to;
			
			if (options.hoverPause) {
				$this.hover(function() {
					clearTimeout(to);	
					$this.addClass("ss-hover");
				}, function() {
					to = setTimeout(nextImage, options.duration, null, false);
					$this.removeClass("ss-hover");
				});
			}
			
			var pickNext = function(current, limit, isRandom, rev)  {
				var c = 0;
				if ((isRandom) && (current == -1)) {
					var rand = current;
					while (rand == current) {
						rand = Math.floor(Math.random()*(options.images.length));
					}
					c = rand;
				} else {
					if (current == -1) {
						c = 0;
					} else if (rev) {
						c = current - 1;
						if (c < 0) c = limit - 1;
					} else {
						c = (current + 1) % limit;
					}
				}
				return c;
			};

			
			var nextImage = function(instant, rev) {
				$this.queue(function(next) {
					clearTimeout(to);
					var s = (instant) ? 0 : options.speed;
					var dir = (rev) ? opposite[options.direction] : options.direction;
					
					previous = current;
					current = pickNext(current, options.images.length, options.random, rev);
	
					if (!(options.images[current]["image"] instanceof jQuery)) {
						var img = new Image();					
						$(img).load(function () {
							var $currentSlide = (previous > -1) ? options.images[previous]["image"] : null;
							var $wrapper = $("<li class=\"slide-wrapper\"></li>"); //style=\"filter:alpha(opacity=100)\"
							
							var $headline;
							if (options.images[current]["headline"]) {
								$headline = $("<div class=\"slide-headline\">" + options.images[current]["headline"]["content"] + "</div>");
								$headline.css("position", "absolute").css(options.images[current]["headline"]["css"]);
							}
							
							var $caption;
							if (options.images[current]["caption"]) {
								$caption = $("<div class=\"slide-caption\">" + options.images[current]["caption"]["content"] + "</div>");
								$caption.css("position", "absolute").css(options.images[current]["caption"]["css"]);
							}
							
							(dir == "right" || dir == "down") ? $this.prepend($wrapper.hide().append(this).append($caption).append($headline)) : $this.append($wrapper.hide().append(this).append($caption).append($headline));
							
							animations[options.animation]($currentSlide, $wrapper, s, dir, next);
							options.images[current]["image"] = $wrapper;
						}).error(function () {
						
						}).attr("src", options.images[current]["image"]).attr("height",options.height).attr("width",options.width);	
					} else {
						var $currentSlide = (previous > -1) ? options.images[previous]["image"] : null;
						(dir == "left" || dir == "up") ? $this.append(options.images[current]["image"]) : $this.prepend(options.images[current]["image"]);
						animations[options.animation]($currentSlide,options.images[current]["image"], s, dir, next);
					}
					
					//next();
				});
			};
		
			if (options.buttons) {
				var $nextButton = $("<div class=\"next-button\"></div>").click(function() { 
					clearTimeout(to);
					nextImage(false, false);
				});
				var $prevButton = $("<div class=\"prev-button\"></div>").click(function() { 
					clearTimeout(to);
					nextImage(false, true); 
				});
			
				$(this).append($nextButton).append($prevButton);
			}
		
			nextImage(true, false);	
		});
	};
	
	$.fn.slideshow.defaults = {
		animation: "slide",
		direction: "down",
		speed: "slow",
		duration: 5000,
		images: [],
		height: 323,
		width: 620,
		random: false,
		buttons: true,
		hoverPause: false
	};
})(jQuery);
