

(function($) {
	$.fn.novurotator = function(o) {
		return this.each(function() {
			if(typeof o == 'object' ||typeof o == 'undefined' && typeof this.novurotator == 'undefined') {
				this.novurotator = new $nr(this, o);
			} else if (typeof o == 'string') {
				switch(o) {
					case 'pause':
						this.novurotator.pauseAuto();
						break;
					case 'unpause':
						this.novurotator.unpauseAuto();
						break;
					default:
						break;
				}			
			}
		});
	};
	
	var fade = function(self, o, i) {
		if (o == i) return;
		$(o).fadeOut(self.options.animationspeed * 1000, function() { $(this).hide(); });
		$(i).fadeIn(self.options.animationspeed * 1000).show();
	};
	
	var none = function(self, o, i) {
		if (o == i) return;
		$(o).hide();
		$(i).show();
	};
	
	var defaults = {
		speed: 1.5,
		autostop: true,
		random: false,
		wrap: true,
		animationspeed: 0.5,
		animation: fade
	};
	
	$.novurotator = function(e, o) {
		this.options = $.extend({}, defaults, o || {});	
		
		if (e.nodeName == 'UL' || e.nodeName == 'OL') {
			this.list = $(e);
			this.list.css({padding: 0, margin: 0});
			
			this.container = this.list.wrap('<div></div>').parent();			
			this.container.css({position: 'relative', overflow: 'hidden'});
		} else { //does nothing when the elements are not a list
			return;
		}
		
		var li = this.list.children('li');
		
		var self = this;
		
		var maxHeight = 0;
		if (li.size() > 0) {
			li.each(function() {
				var it = $(this);				
				it.hide();
				it.css({
					position: 'absolute',
					top: '0px',
					left: '0px',
					listStyle: 'none'
				});
				maxHeight = Math.max(it.outerHeight(true), maxHeight);
			});		
		}
		
		this.list.css('height', maxHeight); //find height from el
		
		this.setup();		
		this.init();
	};
	
	var $nr = $.novurotator;

	$nr.fn = $nr.prototype = {
		novurotator: '0.1'
	};

	$nr.fn.extend = $nr.extend = $.extend;
	
	$nr.fn.extend({
		setup: function() {
			this.animating = false;
			this.timer     = null;
			this.pausing   = false;			
			
			this.last = this.list.children('li').size() - 1; //zero-base
		},
		
		init: function() {		    
		    if(this.list.children('li').size() > 0) {
			    this.current = this.options.random ? Math.floor(Math.random()*this.last+1) : 0;
			    $(this.list.children('li')[this.current]).show();
			    this.startAuto();
			}
		},
		
		animate: function(p) {
			if (this.animating)
				return;

			this.animating = true;

			var self = this;			
			var move = function() { //callback after animation
				self.animating = false;

				if (self.options.wrap || self.current < self.last)
					self.startAuto();
			};
		
			/* check if item exists */			
			if($(this.list.children('li')[p]) < 1) 
				return;

			// Animate
			this.options.animation(this, this.list.children('li')[this.current], this.list.children('li')[p]);
			move();							
		},
		
		startAuto: function() {
		if (this.options.framespeed == 0)
				return this.stopAuto();

			if (this.timer != null)
				return;

			var self = this;
			this.timer = setTimeout(function() { 			
				if((self.options.autostop && $(self.list.children('li')[self.current]).hasMouse()) || self.pausing) {
					self.stopAuto();
					self.startAuto();
				} else {
					self.next(); 
				}
            }, this.options.framespeed * 1000);
		},		
		
		stopAuto: function() {
			if (this.timer == null)
				return;

			clearTimeout(this.timer);
			this.timer = null;
		},
		
		pauseAuto: function() {
			this.pausing = true;
		},
		
		unpauseAuto: function() {
			this.pausing = false;
		},
		
		next: function() {
			this.stopAuto();
			
			var p = this.current + 1;
			if(this.options.random) {
				p = Math.floor(Math.random()*this.last+1);
			} else {
				if (this.current == this.last) {
					if (this.options.wrap) {
						p = 0;
					} else {
						return; //no next available
					}
				}
			}

			this.animate(p);
			this.current = p;					
		},
		
		prev: function() {
			this.stopAuto();
			
			var p = this.current - 1;		
			if(this.options.random) {
				p = Math.floor(Math.random()*this.last+1);
			} else {			
				if (this.current == 0) {
					if (this.options.wrap) {
						p = this.last;
					} else {
						return; //no prev available
					}
				}
			}
			
			this.animate(p);		
			this.current = p;
		}	
	});
})(jQuery);