(function($){
	$.fn.ticker = function(o){
		return new $.ticker(this, o);
	}
	
	var defaults = {
		delay: 7
		,animationSpeed: 500
		,autoplay: true
		,scrollSpeed: .05
		,scrollPauseDelay: 1.5
		,scrollToZero: false
	};
	
	$.ticker = function(e, o){
		var $this = this;
		
		this.options = $.extend(defaults, o); 
		
		this.setup(e); 
	}
	
	var $t = $.ticker;
	
	$t.fn = $t.prototype = {
		ticker: '0.0.1'
	}
	
	$t.fn.extend = $t.extend = $.extend;
	
	$t.fn.extend({
		setup: function(e){
			this.node = $(e);
			this.list = $(this.node).find("ul");
			this.elements = $(this.list).find("li");
			this.width = $(e).width();
			this.currentIndex = 0;
			this.interval;
			this.wasPlaying = false;
			
			if(this.options.autoplay){
				this.start();
				this.isPlaying = true;
				this.loadElement();
			}
			else {
				this.isPlaying = false;
			}
		}
				 
		//Starts the Ticker
		,start: function(){
			if(!this.isPlaying && this.elements.length > 1){
				$(this).everyTime(this.options.delay*1000, "tick", this.step);
				this.isPlaying = true;
			}
		}
		
		//Stops the Ticker
		,stop: function(){
			$(this.elements[this.currentIndex]).stop();
			if(this.isPlaying){
				$(this).stopTime("tick");
				this.isPlaying = false;
			}
		}
		
		,playPause: function(){
			if(this.isPlaying){
				this.stop();
			}
			else{
				this.step('forward');
				this.start();
			}
			return this.isPlaying;
		}
		
		//Resets the Ticker
		,reset: function(){
			this.currentIndex = 0;
			$(this).stopTime("tick");
			$(this).everyTime(this.options.delay*1000, "tick", this.step);
		}
		
		//Shows the Previous Element
		,prev: function(){
			if(this.isPlaying){
				this.stop();
			}
			this.step('back')
		}
		
		//Shows the Next Element
		,next: function(){
			if(this.isPlaying){
				this.stop();
			}
			this.step('forward');
		}
		
		,step: function(direction){
			$(this).stopTime("scroll");
			if(!direction){
				direction = 'forward';
			}
			var $this = this;
			$(this.elements[this.currentIndex]).stop(true).animate({ opacity: 0 }, this.options.animationSpeed, function(){
				$($this.elements[$this.currentIndex]).css({ display: 'none' });
				$this.currentIndex = (direction == 'back') ? ($this.currentIndex+$this.elements.length-1) % $this.elements.length : ($this.currentIndex+1) % $this.elements.length;
				$this.loadElement();
			});
		}
		
		,loadElement: function(){
			var $this = this;
			$(this.elements[this.currentIndex]).css({ display: 'block', opacity:0, left:0 }).animate({ opacity: 1 }, this.options.animationSpeed, function(){
				if($($this.elements[$this.currentIndex]).width() > $this.width){
					$($this).stopTime("tick");
					$($this).oneTime($this.options.scrollPauseDelay*1000, "scroll", $this.scroll);
				}
			});
		}
		
		//Scrolls the Current Element
		,scroll: function(){
			var $this = this;
			var offset = (this.options.scrollToZero) ? $(this.elements[this.currentIndex]).width() : ($(this.elements[this.currentIndex]).width()-this.width);
			var duration = offset/this.options.scrollSpeed;
			$(this.elements[this.currentIndex]).animate({ left: -offset }, duration, "linear", function(){
				$($this).oneTime($this.options.scrollPauseDelay*1000, "restart", function(){
					if($this.isPlaying){
						$this.step('forward');
						$($this).everyTime($this.options.delay*1000, "tick", $this.step);
					}
					else{
						$this.loadElement();
					}
				});
			});
		}
	});
})(jQuery);  



/**
 * jQuery.timers - Timer abstractions for jQuery
 * Written by Blair Mitchelmore (blair DOT mitchelmore AT gmail DOT com)
 * Licensed under the WTFPL (http://sam.zoy.org/wtfpl/).
 * Date: 2009/10/16
 *
 * @author Blair Mitchelmore
 * @version 1.2
 *
 **/

jQuery.fn.extend({
	everyTime: function(interval, label, fn, times) {
		return this.each(function() {
			jQuery.timer.add(this, interval, label, fn, times);
		});
	},
	oneTime: function(interval, label, fn) {
		return this.each(function() {
			jQuery.timer.add(this, interval, label, fn, 1);
		});
	},
	stopTime: function(label, fn) {
		return this.each(function() {
			jQuery.timer.remove(this, label, fn);
		});
	}
});

jQuery.extend({
	timer: {
		global: [],
		guid: 1,
		dataKey: "jQuery.timer",
		regex: /^([0-9]+(?:\.[0-9]*)?)\s*(.*s)?$/,
		powers: {
			// Yeah this is major overkill...
			'ms': 1,
			'cs': 10,
			'ds': 100,
			's': 1000,
			'das': 10000,
			'hs': 100000,
			'ks': 1000000
		},
		timeParse: function(value) {
			if (value == undefined || value == null)
				return null;
			var result = this.regex.exec(jQuery.trim(value.toString()));
			if (result[2]) {
				var num = parseFloat(result[1]);
				var mult = this.powers[result[2]] || 1;
				return num * mult;
			} else {
				return value;
			}
		},
		add: function(element, interval, label, fn, times) {
			var counter = 0;
			
			if (jQuery.isFunction(label)) {
				if (!times) 
					times = fn;
				fn = label;
				label = interval;
			}
			
			interval = jQuery.timer.timeParse(interval);

			if (typeof interval != 'number' || isNaN(interval) || interval < 0)
				return;

			if (typeof times != 'number' || isNaN(times) || times < 0) 
				times = 0;
			
			times = times || 0;
			
			var timers = jQuery.data(element, this.dataKey) || jQuery.data(element, this.dataKey, {});
			
			if (!timers[label])
				timers[label] = {};
			
			fn.timerID = fn.timerID || this.guid++;
			
			var handler = function() {
				if ((++counter > times && times !== 0) || fn.call(element, counter) === false)
					jQuery.timer.remove(element, label, fn);
			};
			
			handler.timerID = fn.timerID;
			
			if (!timers[label][fn.timerID])
				timers[label][fn.timerID] = window.setInterval(handler,interval);
			
			this.global.push( element );
			
		},
		remove: function(element, label, fn) {
			var timers = jQuery.data(element, this.dataKey), ret;
			
			if ( timers ) {
				
				if (!label) {
					for ( label in timers )
						this.remove(element, label, fn);
				} else if ( timers[label] ) {
					if ( fn ) {
						if ( fn.timerID ) {
							window.clearInterval(timers[label][fn.timerID]);
							delete timers[label][fn.timerID];
						}
					} else {
						for ( var fn in timers[label] ) {
							window.clearInterval(timers[label][fn]);
							delete timers[label][fn];
						}
					}
					
					for ( ret in timers[label] ) break;
					if ( !ret ) {
						ret = null;
						delete timers[label];
					}
				}
				
				for ( ret in timers ) break;
				if ( !ret ) 
					jQuery.removeData(element, this.dataKey);
			}
		}
	}
});

jQuery(window).bind("unload", function() {
	jQuery.each(jQuery.timer.global, function(index, item) {
		jQuery.timer.remove(item);
	});
});