
(function(){
	var $ = jQuery,
		esf = (typeof window.esf !== "object") ? window["esf"] = {widget:{}} : window.esf;	
			
			
	/**
	 * @class DisplaySequence
	 * @author Stephen Rushing, eSiteful
	 */
	esf.widget.DisplaySequence=function(opts){
		$.extend(this, opts);
		
		this._timeouts = {};
		
		if(this.items === null) this.items = this.ul.children("li");
		
		if(this.autoPlay && this.items.length>1) this.play();
		else if(this.autoPlay && this.items.length===1)	this.index(0);
	};
	
    esf.widget.DisplaySequence.prototype = {
		_timeouts:null,
		autoPlay:true,
		autoLoop:true,
		ul:null,
		items:null,
		displayTime:3000,
		state:"paused",
		
		//http://api.jquery.com/animate/	.animate(properties, options) with added options.delay and options.before()
		transitionInArgs:[{opacity:1}, {delay:0, duration:1500, queue:false, easing:"linear",
			before:function(){				
				var $item = $(this);	
				$item.css({display:"block", visibility:"visible", opacity: (($item.css("opacity") > 0.1 && $item.css("opacity") < 1) ? $item.css("opacity") : 0.1) });
			},
			complete:function(){
				$(this).css("opacity", null);
			}
		}],
		//http://api.jquery.com/animate/	.animate(properties, options) with added options.delay and options.before()
		transitionOutArgs:[{opacity:"hide"}, {delay:0, duration:3000, queue:false, easing:"linear", 
			complete:function(){
				$(this).css({display:"none"});
			}
		}],
		
		play:function(){
    		this.state = "playing";
			this.index(this._index+1);			
			$(this).trigger("play.Sequence");
			return this;
		},
		
		_index:-1,
		index:function(newIndex){
			//set index
			if(typeof newIndex === "number"){
				if(this._index===newIndex) return this;
				//show the requested item 
				if(newIndex<this.items.length){
					var I = this,
						$prevItem = this._index > -1 ? this.items.eq(this._index).stop() : null,
						$item = this.items.eq(newIndex).stop(),
						outArgs = this.transitionOutArgs,
						inArgs = this.transitionInArgs,
						displayTime = $item.attr("data-displayTime") ? parseInt($item.attr("data-displayTime")) : this.displayTime;
					
					this.clearTimeouts();
					
					//fade previous item out
					if($prevItem!==null && $prevItem.length){					
						if($.isFunction(outArgs[1].before)){
							outArgs[1].before.call($prevItem);
						}
						//we have to make copies of the animation arguments because jquery changes callbacks for queuing, which causes a stack overflow.
						var doPrevItem = function(){
							$.fn.animate.apply($prevItem, $.extend(true, [], outArgs));
						};
						if(outArgs[1].delay > 0){
							this._timeouts.outDelay = setTimeout(function(){
								doPrevItem.call(this);
							}, outArgs[1].delay);
						}else{	
							outArgs[1].delay=0;
							doPrevItem.call(this);
						}
					}
					//fade requested item in
					if($.isFunction(inArgs[1].before)){
						inArgs[1].before.call($item);
					}
					var doItem = function(){
						$.fn.animate.apply($item, $.extend(true, [], inArgs));
					};
					if(inArgs[1].delay > 0){
						this._timeouts.inDelay = setTimeout(function(){
							doItem.call(this);
						}, inArgs[1].delay);
					}else{						
						inArgs[1].delay=0;
						doItem.call(this);
					}
					
					if(this.state === "playing"){
						//set the timer for the next item
						//clearTimeout(this._timeouts.nextItem);					
						this._timeouts.nextItem = setTimeout(function(){
							I.index(I._index+1);								
						}, displayTime + inArgs[1].duration + inArgs[1].delay);
					}
					
					this._index=newIndex;						
					
					$(this).trigger("index.Sequence");
					
				}else if(this.autoLoop && this.items.length>1){
					this.index(0);
					
				}else{
					this.pause();
					this._index=0;
				}
				return this;
			}
			//get index
			return this._index;	
		},
		
		pause:function(){
			clearTimeout(this._timeouts.nextItem);
			this.state = "paused";
			//this.clearTimeouts();
			$(this).trigger("pause.Sequence");
			return this;
		},
		
		clearTimeouts:function(){
			$.each(this._timeouts, function(name, timeout){
				clearTimeout(timeout);
			});
		}
	};
	
	
	
	
    
    
    
    /**
	 * @class DisplaySequenceControlBar
	 * @author Stephen Rushing, eSiteful
	 */
	esf.widget.DisplaySequenceControlBar = function(opts){
		var I = this;
		$.extend(I, opts);
		//Create proxies for certain methods
		$(["onSequencePlay", "onSequencePause", "onSequenceIndex"]).each(function(i, funcName){
			if(typeof I[funcName] === "function"){
				I[funcName+"$proxy"] = $.proxy(I[funcName], I);
			}
		});
		
		//Bind to some of the sequence's events.
		$(this.sequence).bind("play.Sequence", this.onSequencePlay$proxy);
		$(this.sequence).bind("pause.Sequence", this.onSequencePause$proxy);
		$(this.sequence).bind("index.Sequence", this.onSequenceIndex$proxy);		
		
		//Create a number for each sequence item.
		if(this.btnNumbers===null) this.btnNumbers = $([]);
		this.sequence.items.each(function(i, li){
			I.btnNumbers = I.btnNumbers.add(
				$("<li></li>").append($("<a href='javascript:;'>"+(i+1)+"</a>").click(function(){ I.sequence.index(i); })).appendTo(I.ul)
			);
		});
		
		//Force the index event to fire so we have correct initial highlighting.
		$(this.sequence).trigger("index");
		
		//Bind play & pause buttons.
		this.btnPlay.click($.proxy(this.sequence.play, this.sequence));
		this.btnPause.click($.proxy(this.sequence.pause, this.sequence));
		
		//Set play & pause button init classes.
		if(this.sequence._timeouts.nextItem > 0){
			this.btnPlay.addClass(this.activeClass);
		}else{
			this.btnPause.addClass(this.activeClass);
		}
	};
	
	
	esf.widget.DisplaySequenceControlBar.prototype = {
		activeClass:"active",
		btnPlay:null,
		btnPause:null,
		btnNumbers:null,
		sequence:null,
		ul:null,		
		
		onSequencePlay:function(){
			if(this.sequence.state !== "playing") return;	
			this.btnPlay.addClass(this.activeClass);
			this.btnPause.removeClass(this.activeClass);
		},
		onSequencePause:function(){
			this.btnPlay.removeClass(this.activeClass);
			this.btnPause.addClass(this.activeClass);
		},
		onSequenceIndex:function(){
			this.btnNumbers.removeClass(this.activeClass).eq(this.sequence.index()).addClass(this.activeClass); 
		}
	};
	   			
    			
	
	
	
	
	
	
	
	
	
	
	
	/* =========== JAVASCRIPT SAMPLE ========================================
	
	
	var div = $("div.features-banner"),
		ulBanners = div.children("ul.banners"),
		ulControls = div.children("ul.controls");
	
	var sequence = new esf.widget.DisplaySequence({
		ul: ulBanners,
		displayTime: 3000
	});
	
	var controlBar = new esf.widget.DisplaySequenceControlBar({
		sequence: sequence,
		ul: ulControls,
		btnPlay: ulControls.children("li.item-play").addClass(this.activeClass),
		btnPause: ulControls.children("li.item-pause")
	});
	
	*/
	
	
	/* =========== HTML SAMPLE =================================================
	
	<div class="features-banner">
		<ul class="banners">
			<li data-displayTime="90000"> <a href="#"><img src="" alt="" /></a> </li>			
			<li> <a href="#"><img src="" alt="" /></a> </li>
			<li> <a href="#"><img src="" alt="" /></a> </li>
			<li> <a href="#"><img src="" alt="" /></a> </li>
			<li> <a href="#"><img src="" alt="" /></a> </li>
		</ul>
		<ul class="controls">
			<li class="item-play"><a href="javascript:;">play</a></li>
			<li class="item-pause"><a href="javascript:;">pause</a></li>		
		</ul>
	</div>
	
	
	*/
	
	
	/* =========== CSS SAMPLE ==================================================
	 
	.features-banner {border:1px solid #999;margin:0 0 8px 0;}
	.features-banner ul {}
	.features-banner ul li {float:left;}
	
	.features-banner ul.banners {height:326px;position:relative;}
	.features-banner ul.banners li {display:none;height:100%;width:100%;overflow:hidden;position:absolute;top:0;left:0;}
	.features-banner ul.banners li:first-child {display:block;}
	
	.features-banner ul.controls {border-top:none;padding:3px 6px;font-family:Arial,sans-serif;font-size:10px;height:17px;clear:both;background:#CCCCFF;}
	
	div.features-banner ul.controls li.item-play a,
	div.features-banner ul.controls li.item-pause a {}
	
	div.features-banner ul.controls li.item-pause a {background-position:-12px 0px;margin-right:15px;}
	
	.features-banner ul.controls li a {float:left;padding:3px 5px;color:#666;line-height:10px;text-decoration:none;}
	.features-banner ul.controls li.active a {border:1px solid #666;background:#fff;padding:2px 4px;} 
	 
	*/

	
})();
