(function($){
	$.fn.ticker = function(o){
		return new $.ticker(this, o);
	}
	
	var defaults = {
		delay: 7
		,animationSpeed: 400
		,autoplay: true
		,scrollSpeed: .05
		,scrollPauseDelay: 1.5
		,scrollToZero: false
		,sections: [{ id: 'weather_alerts', title: 'Weather Alerts'}]
		,progressBar: true
		,progressBarWidth: 180
	};
	
	$.ticker = function(e, o){
		var $this = this;
		
		this.options = $.extend(defaults, o);
		this.sections = this.options.sections;
		this.setup(e);
	}
	
	var $t = $.ticker;
	
	$t.fn = $t.prototype = {
		ticker: '0.2.0'
	}
	
	$t.fn.extend = $t.extend = $.extend;
	
	$t.fn.extend({
		setup: function(e){
			this.node = $(e);
			this.mainElement = this.node.parent(); //holder of the clip element
			this.width = $(e).width();
			this.currentIndex = 0;
			this.currentSection = 0;
			this.interval;
			this.wasPlaying = false;
			this.isPlaying = false;
			this.setupNavigationNode();
			this.setupSectionNode();
			if(this.options.progressBar){
				this.setupProgressBar();
			}
		}
		
		//Starts the Ticker
		,start: function(){
			//Updates progressbar
			var percentage = (this.currentIndex + 1) / this.elements.length;
			$(this).trigger("progressUpdate", [percentage]);
			
			if(!this.isPlaying && (this.elements.length > 1 || this.sections.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 != 'back'){
				direction = 'forward';
			}
			
			if(this.sections.length > 1 && direction == 'forward' && (this.elements.length == 1 || (this.currentIndex == (this.elements.length - 1)))) {
				this.nextSection();
			} 
			else if(this.sections.length > 1 && direction == 'back' && this.currentIndex == 0){
				this.prevSection();
			}
			else{
				var $this = this;
				$(this.elements[this.currentIndex]).stop(true).animate({ top: 0 }, this.options.animationSpeed, function(){
					$($this.elements[$this.currentIndex]).animate({ top: -23 }, $this.options.animationSpeed, function(){
						$(this).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', top: 23, left:0 }).animate({ top: 0 }, this.options.animationSpeed, function(){
				if($($this.elements[$this.currentIndex]).width() > $this.width){
					$($this).stopTime("tick");
					$($this).oneTime($this.options.scrollPauseDelay*1000, "scroll", $this.scroll);
				}				
			});			
			//Updates progressbar
			var percentage = (this.currentIndex + 1) / this.elements.length;
			$(this).trigger("progressUpdate", [percentage]);
		}
		
		//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();
					}
				});
			});
		}
		
		,setupProgressBar: function(){
			$this = this;
			this.progressBar = $('<div id="alerts_ticker_progressbar" class="progressbar"></div>');
			this.mainElement.append(this.progressBar);
			$(this).bind('progressUpdate', function(e, percentage){
				$this.progressBar.animate({width:percentage * $this.options.progressBarWidth}, 200);
			});
		}
		
		//Sets up the Item navigation
		,setupNavigationNode: function(){
			var $this = this;
			
			this.navigationNode = $('<div id="'+this.mainElement.attr('id')+'_navigation" class="nav"></div>');
			this.nextItemButton = $('<a href="#" title="Next">Next</a>');
			this.prevItemButton = $('<a href="#" title="Previous">Previous</a>');
			this.pausePlayButton = $('<a href="#" class="pause" title="Pause">Pause</a>');
			this.closeButton = $('<a href="#" title="Close">Close</a>');
			
			this.nextItemButton.click(function(){
				$this.next();
				$this.pausePlayButton.attr('title','Play').removeClass('pause').addClass('play');
				return false;
			});
			
			this.prevItemButton.click(function(){
				$this.prev();
				$this.pausePlayButton.attr('title','Play').removeClass('pause').addClass('play');						
				return false;
			});
			
			this.pausePlayButton.click(function(){
				title = ($this.playPause()) ? 'Pause' : 'Play';
				cssClass = (title == 'Pause') ? 'pause' : 'play';
				otherClass = (cssClass == 'pause') ? 'play' : 'pause';
				$this.pausePlayButton.attr('title',title).removeClass(otherClass).addClass(cssClass);
				return false;
			});
			
			this.closeButton.click(function(){
				$this.stop();								 
				$this.mainElement.fadeOut("slow");
				return false;
			});
			
			this.mainElement.append(this.navigationNode.append(this.nextItemButton).append(this.prevItemButton).append(this.pausePlayButton).append(this.closeButton));
		}
		
		,showNavigation: function(){
			this.nextItemButton.show();
			this.prevItemButton.show();
			this.pausePlayButton.show();
		}
		
		,hideNavigation: function(){
			this.nextItemButton.hide();
			this.prevItemButton.hide();
			this.pausePlayButton.hide();
		}
		
		//Sets the Section Title
		,setSection: function(direction){
			this.list = $(this.node).find('ul#'+this.sections[this.currentSection].id);
			this.elements = $(this.list).find('li');
			// Set the current index equaled to the last element if you're moving backwards or the first element if you're moving forwards.
			this.currentIndex = (direction == 'back') ? this.elements.length - 1 : 0;
			this.sectionNode.find("span").text(this.sections[this.currentSection].title);
			this.showNavigation();
			if(this.elements.length == 1 && this.sections.length == 1){
				this.hideNavigation();
			}			
			// Fix for z-index
			$(this.node).find('ul').css('z-index', 0);
			this.list.css('z-index', 1);
		}
		
		//Shows the Previous Section
		,prevSection: function(){
			if(this.isPlaying){
				this.stop();
			}
			this.stepSection('back');
		}
		
		//Shows the Next Section
		,nextSection: function(){
			if(this.isPlaying){
				this.stop();
			}
			this.stepSection('forward');
		}
		
		//Steps the Section One Way or Another
		,stepSection: function(direction){
			$(this).stopTime("scroll");
			//console.log("stepSection",direction);
			if(!direction){
				direction = 'forward';
			}
			$(this.elements[this.currentIndex]).stop(true).animate({ top: 0 }, $this.options.animationSpeed, function(){
				$($this.elements[$this.currentIndex]).animate({ top: -23 }, $this.options.animationSpeed, function(){
					$(this).css({ display: 'none' });
				});
				$this.currentSection = (direction == 'back') ? ($this.currentSection+$this.sections.length-1) % $this.sections.length : ($this.currentSection+1) % $this.sections.length;
				$this.setSection(direction);
				$this.start();
				$this.loadElement();
			});
		}
		
		//Sets up the Section Node
		,setupSectionNode: function(){
			this.sectionNode = $('<div id="'+this.node.attr('id')+'_section" class="section"><span></span></div>');
			if(this.sections.length > 1){
				this.nextSectionButton = $('<a href="#" title="Next">Next</a>');
				this.prevSectionButton = $('<a href="#" title="Previous">Previous</a>');
				var $this = this;
				this.nextSectionButton.click(function(){
					$this.nextSection();
					return false;
				});
				this.prevSectionButton.click(function(){
					$this.prevSection();
					return false;
				});
				this.sectionNode.append(this.nextSectionButton);
				this.sectionNode.append(this.prevSectionButton);
			}
			this.mainElement.append(this.sectionNode);
			this.setSection();
		}
		
	});
})(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);
	});
});

(function($){
  $.nano = function(template, data){
    return template.replace(/\{([\w\.]*)}/g, function(str, key){
      var keys = key.split("."), value = data[keys.shift()]
      $.each(keys, function(){ value = value[this] })
      return value
    })
  }
})(jQuery)
