// Scroller v1.0 done by Ben Munson 2/6/2010
// Please leave this at the top if you use it thanks

var Scroller = Class.create({
	initialize: function(hash) {		
		this.direction = (hash.direction ? hash.direction : 'horizontal');
		this.scrollArea = (hash.scrollArea ? $(hash.scrollArea) : '');
		this.filmstripControls = (hash.filmstrip ? $(hash.filmstrip) : '');
		this.scrollPaneClass = (hash.scrollPaneClass ? hash.scrollPaneClass : 'scroll_pane');
		this.scrollPreviousClass = (hash.scrollPreviousClass ? hash.scrollPreviousClass : 'scroll_previous');
		this.scrollNextClass = (hash.scrollNextClass ? hash.scrollNextClass : 'scroll_next');
		
		//auto-scrolling stuff
		this.keepScrolling = (hash.keepScrolling ? hash.keepScrolling : false);
		this.scrollPause = (hash.scrollPause ? hash.scrollPause : 3000);
		this.cyclePanes = (hash.cyclePanes ? hash.cyclePanes : false);
		this.numberOfCycles = (hash.numberOfCycles ? hash.numberOfCycles : 0);
		this.cycleIndex = 0;
		
		//handles stuff
		this.handleContainer = (hash.handleContainer ? hash.handleContainer : '');
		this.handleClass = (hash.handleClass ? hash.handleClass : 'handle');
		this.handleDirection = (hash.handleDirection ? hash.handleDirection : 'left');
		this.handleColor = (hash.handleColor ? hash.handleColor : '');
		this.handleImage = (hash.handleImage ? hash.handleImage : '');
		
		//callback functions
		this.onScrollBegin = (hash.onScrollBegin ? hash.onScrollBegin : null);
		this.onScroll = (hash.onScroll ? hash.onScroll : null);
		this.onScrollEnd = (hash.onScrollEnd ? hash.onScrollEnd : null);
		
		this.isScrolling = false;
		
		this.scrollanim = { 
			time:0, 
			begin:0, 
			change:0.0, 
			duration:(hash.duration ? hash.duration : 20), 
			element:this.scrollArea, 
			timer:null,
			direction:this.direction
		};
		
		this.from_pane = '';
		this.to_pane = '';
		this.panes = Array();
		this.paneIndex = 0;
		this.handles = Array();
		
		this.scrollingTimer = '';

		this.scrollArea.select('.' + this.scrollPaneClass).each(function(item){
			this.panes.push(item);
			var previous = item.down('.' + this.scrollPreviousClass);
			if (previous)
			{
				previous.observe('click', this.manualScrollToPrevious.bind(this));
			}
			var next = item.down('.' + this.scrollNextClass);
			if (next)
			{
				next.observe('click', this.manualScrollToNext.bind(this));
			}
		}, this);
		
		if (this.keepScrolling)
		{
			this.setAutoScrollStep();
		}
		
		this.from_pane = this.panes[this.paneIndex];

		//reset for Firefox
		switch(this.direction)
		{
			case 'vertical':
				this.scrollArea.scrollTop = 0;
			break;
			case 'horizontal':
				this.scrollArea.scrollLeft = 0;
			break;
		}
		
		if (this.handleContainer)
		{
			this.setupHandles();
		}
	},
	setupHandles: function()
	{
		if (this.handleColor != '')
		{
			$(this.handleContainer).addClassName(this.handleColor);
		}
		else
		{
			this.setHandleColor();
		}
	 	if (this.handleDirection == 'left')
	 	{
	 		for(x=0;x<this.panes.length;x++)
	 		{
	 			this.setupHandle(this.panes[x], x);
	 		}
	 	}
	 	else if (this.handleDirection == 'right')
	 	{
	 		Builder.node('a', { className:'handle' }, '>').observe('click',this.arrowScrollToNext.bind(this)).place(this.handleContainer); 
	 		for(x=this.panes.length-1;x>=0;x--)
	 		{
	 			this.setupHandle(this.panes[x], x);
	 		}
	 		Builder.node('a', { className:'handle' }, '<').observe('click',this.arrowScrollToPrevious.bind(this)).place(this.handleContainer);
	 	}
	 	this.handles[0].addClassName('active');
	},
	setupHandle: function(item, index)
	{		 	
		var x = this.doHandle.bind(this);
		if (this.handleImage)
		{
			var h = Builder.node('img', { src:this.handleImage, border:0 });
		}
		else
		{
			var h = Builder.node('div', { className:this.handleClass }, index+1);
		}
		
		h.observe('click', function() {
			x(index);
		});
		$(this.handleContainer).appendChild(h);	
		this.handles[index] = h;
	},
	doHandle: function(i)
	{
		if (!this.isScrolling)
		{
			this.from_pane = this.panes[this.paneIndex];
			this.paneIndex = i;
			this.to_pane = this.panes[i];
			this.scroll();
			if (this.keepScrolling)
			{
				this.keepScrolling = false;
				clearTimeout(this.scrollingTimer);
			}
			this.from_pane = this.panes[i];
		}		
	},
	lightHandle: function(i)
	{
		this.handles.each(function(item) {
			item.removeClassName('active');
		});
		this.handles[i].addClassName('active');
	},
	setAutoScrollStep: function() {
		if (this.to_pane == '')
		{
			this.from_pane = this.panes[0];
		}
		else
		{
			this.from_pane = this.to_pane;
		}
		var x = this.scrollToNext.bind(this);
		
		this.scrollingTimer = setTimeout(x, this.scrollPause);
	},
	cancelAutoScroll: function()
	{
		this.keepScrolling = false;
		clearTimeout(this.scrollingTimer);
	},
	manualScrollToPrevious: function(e) {
		if (!this.isScrolling)
		{
			this.cancelAutoScroll();
			this.from_pane = e.element().up('.' + this.scrollPaneClass);
			this.scrollToPrevious();
		}		
	},
	handleScrollToPrevious: function(e) {
		if (!this.isScrolling)
		{
			this.cancelAutoScroll();
			this.from_pane = this.to_pane;
			this.scrollToPrevious();
		}
	},
	arrowScrollToPrevious: function(event) {
		if (!this.isScrolling)
		{
			this.cancelAutoScroll();
			this.from_pane = this.panes[this.paneIndex];
			this.scrollToPrevious();
		}
	},
	scrollToPrevious: function() {
		if (this.paneIndex == 0)
		{
			if (this.cyclePanes)
			{
				this.paneIndex = this.panes.length-1;
				this.to_pane = this.panes[this.paneIndex];
			}
			else
			{
				this.to_pane = '';
			}
		}
		else
		{
			this.paneIndex--;
			this.to_pane = this.panes[this.paneIndex];
		}
		
		if (this.to_pane)
		{
			this.scroll();
		}
		if (this.keepScrolling)
		{
			this.setAutoScrollStep();
		}
	},
	manualScrollToNext: function(event) {
		if (!this.isScrolling)
		{
			this.cancelAutoScroll();
			this.from_pane = event.element().up('.' + this.scrollPaneClass);
			this.scrollToNext();
		}
	},
	handleScrollToNext: function(event) {
		if (!this.isScrolling)
		{
			this.cancelAutoScroll();
			this.from_pane = this.to_pane;
			this.scrollToNext();		
		}
	},
	arrowScrollToNext: function(event){
		if (!this.isScrolling)
		{
			this.cancelAutoScroll();
			this.from_pane = this.panes[this.paneIndex];
			this.scrollToNext();
		}
	},
	scrollToNext: function() {
		if (this.paneIndex == this.panes.length-1)
		{
			if (this.cyclePanes)
			{
				if (this.numberOfCycles > 0)
				{
					this.cycleIndex++;
					if ((this.numberOfCycles > 0) && (this.cycleIndex == this.numberOfCycles))
					{
						this.cancelAutoScroll();
					}
				}

				this.paneIndex = 0;
				this.to_pane = this.panes[this.paneIndex];
			}
			else
			{
				this.to_pane = '';
			}
		}
		else
		{
			if (this.cyclePanes)
			{
				if ((this.keepScrolling) && (this.numberOfCycles > 0) && (this.cycleIndex == this.numberOfCycles))
				{
					this.to_pane = '';
				}
				else
				{
					this.paneIndex++;
					this.to_pane = this.panes[this.paneIndex];
				}
			}
			else
			{
				this.paneIndex++;
				this.to_pane = this.panes[this.paneIndex];
			}
		}
		
		if (this.to_pane != '')
		{
			this.scroll();
		}
		else
		{
			this.keepScrolling = false;
		}
		
		if (this.keepScrolling)
		{
			this.setAutoScrollStep();
		}
	},
	sineInOut: function(t, b, c, d)	{
		return -c/2 * (Math.cos(Math.PI*t/d) - 1) + b;
	},
	animateScrolling: function()	
	{
		if (this.scrollanim.time > this.scrollanim.duration) {
			this.isScrolling = false;
			clearInterval(this.scrollanim.timer);
			this.scrollanim.timer = null;
			if (this.onScrollEnd)
			{
				this.onScrollEnd();
			}
			if (this.handleContainer)
			{
				this.setHandleColor();
				this.lightHandle(this.paneIndex);
			}
		}
		else {
			this.isScrolling = true;
			move = this.sineInOut(this.scrollanim.time, this.scrollanim.begin, this.scrollanim.change, this.scrollanim.duration);
			switch(this.scrollanim.direction)
			{
				case 'horizontal':
					this.scrollanim.element.scrollLeft = move;
					break;
				case 'vertical':
					this.scrollanim.element.scrollTop = move;
					break;	
			}
			this.scrollanim.time++;
			if (this.onScroll)
			{
				this.onScroll();
			}
		}
	},
	scroll: function() 	{
		if (!this.isScrolling)
		{
			var scroller = this;
	
			var from = 0;
			var current = 0;
			var to = 0;
		
			switch(this.direction)
			{
				case 'horizontal':
					var from = this.from_pane.positionedOffset()['left'];
					var current = this.scrollArea.scrollLeft;
					var to = this.to_pane.positionedOffset()['left'];
					break;
				case 'vertical':
					var from = this.from_pane.positionedOffset()['top'];
					var current = this.scrollArea.scrollTop;
					var to = this.to_pane.positionedOffset()['top'];
					break;
			}
			
			if (this.scrollanim.timer != null) {
				clearInterval(this.scrollanim.timer);
				this.scrollanim.timer = null;
			}		
			
			this.scrollanim.time = 0;
			this.scrollanim.begin = current;
			this.scrollanim.change = to - from;
			this.scrollanim.timer = setInterval(function() { scroller.animateScrolling()}, 10);
						
			if (this.onScrollBegin)
			{
				this.onScrollBegin();
			}
		}
	},
	setHandleColor: function()
	{
		var hc = $(this.handleContainer);
		var p = (this.to_pane != '' ? this.to_pane : this.from_pane);
		if (this.handleColor == '') {
			if (p.hasClassName('handle-dark'))
			{
				if (hc.hasClassName('light')) { hc.removeClassName('light'); }
				hc.addClassName('dark');
			}
			else if(p.hasClassName('handle-light'))
			{
				if (hc.hasClassName('dark')) { hc.removeClassName('dark'); }			
				hc.addClassName('light');
			}
			else
			{
				if (hc.hasClassName('dark')) { hc.removeClassName('dark'); }			
				if (hc.hasClassName('light')) { hc.removeClassName('light'); }
			}
		}
	}
});