(function($) {
	$.fn.rotate = function(options) {
		var self = this;
		
		var settings = {
			items: self.find('.slide'),
			width: $(this).width(),
			displayTime: 6000,
			duration: 500, // transition duration
			nextButton: '#next_button',
			prevButton: '#previous_button',
			debug: false,
			transition: 'fade', // 'slide' or 'fade'
			autorotate: true
		};
		
		$.extend(settings, options);
		
		var working = false;
		var cur = 0;
		var crop_width;
		var items = settings.items;
		var intervalID;
		
		var debug = function(logMessage) {
			if (settings.debug == true && window.console) console.log(logMessage);
		}
		
		var next = function() {
			if (cur < (items.length - 1)) return cur + 1;
			else return 0;
		}
		
		var prev = function() {
			if (cur == 0) return items.length - 1;
			else return cur - 1;
		}
		
		var goNext = function() {
			if (!working)
			{
				working = true;
				debug('goNext called');
				if (settings.transition == 'fade') crossFade();
				else if (settings.transition == 'slide') slideLeft();
			}
		};
		
		var goPrev = function() {
			if (!working)
			{
				working = true;
				debug('goPrev() triggered' + Date());
				if (settings.transition == 'fade') crossFade(true);
				else if (settings.transition == 'slide') slideRight();
			}
		}
		
		var crossFade = function(backwards) {
			var nxt;
			if (backwards) nxt = prev();
			else nxt = next();
			
			var transIn = function() {
				$(items[nxt]).hide().css({top: 0, left: 0, position: 'absolute'}).fadeIn(settings.duration, function() {
					cur = nxt;
					working = false;
				});	
			};
			$(items[cur]).fadeOut(settings.duration, transIn);
		}
		
		var slideLeft = function() {
			var nxt = next();
			
			$(items[nxt]).css({
				top: 0,
				left: crop_width + 5
			}).show();
			
			var dest1 = crop_width * -1;
			var dest2 = 0;
			
			doSlide(nxt,dest1,dest2);
		}
		
		var slideRight = function() {
			var nxt = prev();
			$(items[nxt]).css({
				top: 0,
				left: 0 - crop_width - 5
			}).show();
			
			dest1 = crop_width + 5;
			dest2 = 0;
			
			doSlide(nxt,dest1,dest2);
		}
		
		var doSlide = function(nxt,dest1,dest2) {
			$(items[cur]).animate({
				left: dest1
			},settings.duration,'linear');
			$(items[nxt]).animate({
				left: dest2
			},settings.duration,'linear',function() {
				// callback
				cur = nxt;
				working = false;
			});
		}
		
		
		var begin = function() {
			debug('begin called');			
			intervalID = setInterval(goNext,settings.displayTime + settings.duration * 2); 
		};
		
		var halt = function() {
			debug('stopping');
			clearInterval(intervalID);
		};


		var init = function() {
			items.each( function(i) {
				if (i != cur) $(this).hide();
				$(this).css({ 'position': 'absolute' });
			});
			
			crop_width = $(items[0]).parent().width();
			
			self.find(settings.nextButton).click( function() {
				goNext();
			});

			self.find(settings.prevButton).click( function() {
				goPrev();
			});

			if (settings.autorotate == true) {
				begin();
				if (settings.hoverPause == true)
				{
					$(self).bind("mouseenter",function(){
						debug('mouse enter');
						halt();
					}).bind("mouseleave",function(){
						debug('mouse leave');
						begin();
					});
				}
			}
			
			debug('succesfully initiated');
		};
		
		
		this.stop = function() {
			halt();
		};
		
		this.start = function() {
			goNext();
			begin();
		}
		
		this.next = function() {
			goNext();
		}
		
		this.previous = function() {
			goPrev();
		}
				
		init();
		return this;
	};
})(jQuery);
