/**
 * @author jallen
 */
;(function($){
	$.fn.extend({
		svScroll: function(options) {
			var defaults = {
				'windowClass' : 'window'
				,'trackClass': 'track'
				,'itemClass': 'item'
				,'prvClass': 'prv'
				,'nxtClass': 'nxt'
				,'sliderClass' : 'slider'
				,'orientation': 'left' // 'left' or 'top' indicate relevant anchor
				,'speed': '400'
				,'items': 1 // number of items shown in the window
				,'delay': 0 // milliseconds of delay
				,'loop': false
			};
			
			var options = $.extend(defaults, options);
			
			
			var _scrollPrev = function(el,options) {
				var o = options;
				// only go if active
				if (!$(el).hasClass('active')) return false;

				var prvBttn = $(el);
				var nxtBttn = prvBttn.siblings('.' + o.nxtClass);
				var slider = prvBttn.siblings('.' + o.sliderClass);
				var win = prvBttn.siblings('.' + o.windowClass);

				nxtBttn.unbind('scrolling').removeClass('active');
				prvBttn.unbind('scrolling').removeClass('active');
				slider.unbind('scrolling').removeClass('active');

				var winData = _winData(win,o);

				return _scroll( win , prvBttn , nxtBttn , slider , winData.prvPos , winData.maxPos , o );
			};

			var _scrollNext = function(el,options) {
				var o = options;
				// only go if active
				if (!$(el).hasClass('active')) return false;

				var nxtBttn = $(el);
				var prvBttn = nxtBttn.siblings('.' + o.prvClass);
				var slider = nxtBttn.siblings('.' + o.sliderClass);
				var win = nxtBttn.siblings('.' + o.windowClass);

				nxtBttn.unbind('scrolling').removeClass('active');
				prvBttn.unbind('scrolling').removeClass('active');
				slider.unbind('scrolling').removeClass('active');

				var winData = _winData(win,o);

				return _scroll( win , prvBttn , nxtBttn , slider , winData.nxtPos , winData.maxPos , o );
			};

			var _scrollTo = function(el,idx,options) {
				var o = options;
				// only go if control is active
				if (!$(el).hasClass('active')) return false;
				
				slider = $(el);
				var nxtBttn = slider.siblings('.' + o.nxtClass);
				var prvBttn = slider.siblings('.' + o.prvClass);
				var win = slider.siblings('.' + o.windowClass);

				nxtBttn.unbind('scrolling').removeClass('active');
				prvBttn.unbind('scrolling').removeClass('active');
				slider.unbind('scrolling').removeClass('active');

				var winData = _winData(win,o);

				var newPos = -(winData.itemSize * Math.min(idx,winData.itemCount));

				return _scroll( win , prvBttn , nxtBttn , slider , newPos , winData.maxPos , o );
			};

			var _scroll = function(win,prvBttn,nxtBttn,slider,newPos,maxPos,options) {
				var o = options;

				var winData = _winData(win,o);

				var animation = o.orientation == 'top'
						? {top: newPos+"px"}
						: {left: newPos+"px"};
				win.find('.' + o.trackClass).animate(animation,o.speed);

				nxtBttn.bind('scrolling',function(){
					return _scrollNext(this,o);
				});
				prvBttn.bind('scrolling',function(){
					return _scrollPrev(this,o);
				});
				slider.addClass('active').bind('scrolling',function(event, idx){
					return _scrollTo(this,idx,o);
				}).slider("value",-(newPos/winData.itemSize));

				if (newPos > maxPos || o.loop) nxtBttn.addClass('active');
				if (newPos < 0 || o.loop) prvBttn.addClass('active');

				return false;
			}

			var _winData = function(el,options,force) {
				var o = options;
				var win = $(el);

				// must be passed to window
				if (!win.hasClass(o.windowClass)) return false;
				
				var winData = win.data('scroll');
				if ( typeof winData !=  'object' || winData == null ) {
					force = true;
					winData = {'winSize' : 0 , 'itemCount' : 0 , 'itemSize' : 0 , 'maxPos' : 0};
				}
				if ( force || typeof winData.winSize == 'undefined' ) {
					winData.winSize = o.orientation == 'top'
							? win.innerHeight()
							: win.innerWidth();
				}
				if ( force || typeof winData.itemCount == 'undefined' ) {
					winData.itemCount = win.find('.' + o.itemClass).length;
				}
				if ( force || typeof winData.itemSize == 'undefined' ) {
					winData.itemSize = o.orientation == 'top'
						? win.find('.' + o.itemClass).outerHeight(true)
						: win.find('.' + o.itemClass).outerWidth(true);
				}
				if ( force || typeof winData.maxPos == 'undefined' ) {
					winData.maxPos = -(winData.itemCount * winData.itemSize)
							+ winData.itemSize * Math.floor(winData.winSize / winData.itemSize);
				}
				winData.curPos = o.orientation == 'top'
						? win.find('.' + o.trackClass).position().top
						: win.find('.' + o.trackClass).position().left;

				winData.nxtPos = winData.curPos - (winData.itemSize * o.items);
				if ( winData.nxtPos < winData.maxPos ) {
					winData.nxtPos = o.loop && (winData.curPos == winData.maxPos)
						? 0 : winData.maxPos;
				}

				winData.prvPos = winData.curPos + (winData.itemSize * o.items)
				if ( winData.prvPos > 0 ) {
					winData.prvPos = o.loop && (winData.curPos == 0)
						? winData.maxPos : 0;
				}

				win.data('scroll',winData);
				return winData;
			};

			var _setDelay = function(el,o) {
				if (o.delay <= 0) return false;

				var nxtBttn = $(el).find('.' + o.nxtClass);
				var win = $(el).find('.' + o.windowClass);

				var nxtID = win.data('nxtID');
				if ( typeof nxtID != 'undefined' ) window.clearInterval(nxtID);

				nxtID = window.setInterval(function() {
						nxtBttn.trigger('scrolling');
					}
					,o.delay
				);

				win.data('nxtID',nxtID);
			}

			return this.each(function() {
				var o = options;
				
				var $this = $(this);
				// figure out initial state information
				var winData = _winData($this.find('.' + o.windowClass),o);
				
				// no point in all this if all the items are visible already
				if ( winData.itemCount * winData.itemSize <= winData.winSize )
					return this;

				_setDelay($this,o);

				// previous button
				var prvBttn = $this.find('a.' + o.prvClass).show().bind('scrolling',function() {
						return _scrollPrev(this,o);
					}).bind('click',function() {
						$(this).trigger('scrolling');
						_setDelay($this,o);
						return false;
					});
				if (winData.curPos < 0 || o.loop ) {
					prvBttn.addClass('active');
				}
				
				// next button
				var nxtBttn = $this.find('a.' + o.nxtClass).show().bind('scrolling',function() {
						return _scrollNext(this,o);
					}).bind('click',function() {
						$(this).trigger('scrolling');
						_setDelay($this,o);
						return false;
					});
				if (winData.curPos > winData.maxPos || o.loop ) {
					nxtBttn.addClass('active');
				}

				// slider
				var slider = $this.find('.' + o.sliderClass).bind('scrolling',function(event, idx){
					return _scrollTo(this,idx,o);
				}).slider({
					min: 0
					,max: winData.itemCount - 1
					,slide: function(event, ui) {
						$(this).trigger('scrolling' , [ui.value]);
						_setDelay($this,o);
					}
				}).addClass('active');
			});

			return this;
		}
	});
})(jQuery);

