(function($) {
	$.fn.slipstream = function (options) {
		return this.each(function (i) {
			// select our list
			var imageList = $(this);
			
			// get/set the properties for our slideshow
			var imageProps = {
				 height: $(imageList.find('img')[0]).height()
				,width: $(imageList.find('img')[0]).width()
				,count: imageList.find('li').size()
				,listClass: imageList.attr('class')
				,unique: 'ul_slipstream_' + i
			};
			
			// define some slideshow control variables
			controlVars = $.extend({}, $.fn.slipstream.defaults, options);
			
			// define our default CSS rules
			var containerCSS = {
				 width: imageProps.width + 50
				,height: imageProps.height
				,position: 'relative'
			}
			var viewportCSS = {
				 width: imageProps.width
				,height: imageProps.height
				,margin: '0 auto'
				,overflow: 'hidden'
				,position: 'relative'
				,zIndex: '99999'
			}
			var controlsCSS = {
				 position: 'absolute'
				,height: imageProps.height
				,width: imageProps.width + 50
				,top: 0
			}
			var controlLinkCSS = {
				 display: 'block'
				,width: (imageProps.width/4)
				,height: imageProps.height
				,outline: 'none'
				,position: 'absolute'
				,textIndent: '-9999em'
				,zIndex: '1'
			}
			var imageListCSS = {
				 listStyle: 'none'
				,margin: '0'
				,padding: '0'
				,left: '0'
				,clear: 'both'
				,display: 'block'
				,position: 'relative'
				,width: (imageProps.width * imageProps.count)
				,height: imageProps.height
			}
			var imageListItemCSS = {
				 display: 'block'
				,float: 'left'
				,width: imageProps.width
				,height: imageProps.height
			}
	
			// define our container
			var container = $('<div class="slipstreamObject">').addClass(imageProps.listClass);
			// define our viewport
			var viewport = $('<div class="slipstreamViewport">');
			// define our controls
			var controls = $('<div class="controls clearfix"><a class="prev CM_pngFix" title="View Previous Image" href="">Previous Image</a><a class="next CM_pngFix" title="View Next Image" href="">Next Image</a>');
			$('a', controls).attr('rel', imageProps.unique);
			
			// append our viewport and controls to our container
			viewport.appendTo(container);
			controls.appendTo(container);
			
			// apply the css to our items
			controls.css(controlsCSS);
			$('a', controls).css(controlLinkCSS);
			container.css(containerCSS);
			viewport.css(viewportCSS);
			imageList.attr('id', imageProps.unique).css(imageListCSS);
			$('li', imageList).css(imageListItemCSS);
			
			// wrap the image list with the viewport div
			imageList.wrap(container);
			
			// set some assorted slide control vars
			isChanging = false;
			
			// captions
			$.fn.slipstream.addCaptions($('li', imageList));

			// binding makes the magic happen...
			$('.slipstreamObject .controls a').bind('click', $.fn.slipstream.slide);
		});
	};
	
	// the actual sliding function
	$.fn.slipstream.slide = function (e) {
		// make sure to only move the appropriate list (in case there are multiples)
		var target = $('#'+$(this).attr('rel'));
		var slipper = target.find('li');
		controlVars.origSpeed = $.fn.slipstream.defaults.speed;
		// size controls...
		var width = slipper.width();
		var count = slipper.size();
		var maxOffset = -(width * (count - 1));
		// previous or next?
		var action = jQuery(this).attr('class');
		// where are we in the photostream?
		var currOffset = parseInt(target.css('left'));
		// if we're going to a previous image...
		if (action.match('prev')) {offset = currOffset + width;}
		// else, if we're going to the next image...
		else {offset = currOffset - width;}
		// if we try to go to the previous image from the first, go to the end (as quick as possible)
		if (offset > 0){offset = maxOffset; controlVars.speed = 0;}
		// if we try to go to the next image from the last, go to the beginning (as quick as possible)
		else if (offset < maxOffset){offset = 0; controlVars.speed = 0;}
		// make sure we didn't somehow get stuck 'between' two pictures (fast user clicking *may* cause this)
		var change = (offset/width);
		if (change != Math.round(change)){offset = Math.round(change)*width;}
		// now, move our photostream
		if (!isChanging){
			isChanging = true;
			target.animate({left:offset}, controlVars.speed, controlVars.easing, function() {isChanging = false;});
			controlVars.speed = controlVars.origSpeed;
		}
		e.preventDefault();
	};
	
	// caption adding
	$.fn.slipstream.addCaptions = function ($list) {
		$list.each(function () {
			var $this	= $(this);
			var $img	= $('img', $this);
			var $desc	= $img.attr('longdesc');
			if (typeof $desc != 'undefined' && $desc != '') {
				var $caption = $('<span class="caption"></span>')
					.html($desc)
					.hide();
				$this
					.bind('mouseenter mouseleave', $.fn.slipstream.showCaption)
					.append($caption);
			}
		});
	};
	
	// show caption
	$.fn.slipstream.showCaption = function (e) {
		var $this	= $(e.currentTarget);
		var $caption= $('.caption', $this);
		if (e.type == 'mouseenter') {
			$caption.fadeIn(250);
		}
		else {
			$caption.fadeOut(250);
		}
	}
	
	// default options
	$.fn.slipstream.defaults = {
		 speed: 750
		,easing: 'swing'
	};
})(jQuery);