/*

		scroller.js
		
		Mootools-based class to provide customizable scrolling functionality
		
		Written by:		Ken Kolodziej
		Created on:		April 6, 2009
		
		USAGE:			Instantiate a new Scroller and pass two arrays in the options object (rollout div ids and
					trigger object ids).  The two arrays MUST be synchronized for the rollouts to be effective.
*/

var Scroller = new Class({
	options: {
		els: null,
		className: '',
		container: null,
		mode: 'horizontal',
		lensLength: 400,
		scrollDist: 0,
		autoScroll: true,
		delay: 3000,
		startDelay: 6000,
		smoothScroll: false,
		backButton: null,
		forwardButton: null,
		separatorLength: 20,
		randomize: false
	},
	initialize: function(options){
		this.setOptions(options);
		
		if(!this.options.els)
			this.options.els = new Array();
		
		// Set up divs
		if(this.options.els.length == 0
		   && this.options.className != '')
			this.options.els = this.options.container.getElements('div.' + this.options.className);
		
		// Set up class variables
			this.direction = 0;
			this.currentIndex = 0;
			this.doAutoScroll = true;
			this.autoScrollTimer = null;
			this.viewportSize = 0;		// Number of elements that are visible in the viewport at any given time
			
			if(this.options.scrollDist > this.options.els.length - 1)
				this.options.scrollDist = this.options.els.length - 1;
		
		// Set up container styles
			this.containerLength = 0;
			
			this.options.container.setStyles({
				overflow: 'hidden'
			});
			
			// Get container dimensions
			this.contDims = this.options.container.getCoordinates();
		
		
		// Set up transparent container inside main container
			this.containerFilm = new Element('div', {
				'styles': {
					position: 'relative'
				}
			}).inject(this.options.container);
			
			// Set height or width (depending on orientation) to size of one element
			if(this.options.els.length > 0) {
				var elDims = this.options.els[0].getSize();
				
				if(this.options.mode == 'horizontal')
					this.containerFilm.setStyle('height', elDims.y + 'px');
				else
					this.containerFilm.setStyle('width', elDims.x + 'px');
				
				// Randomize if necessary
				if(this.options.randomize == true)
					fisherYates(this.options.els);
			}
		
		// Inject child divs into container
			for(var i = 0; i < this.options.els.length; i++) {
				// Set style
				if(this.options.mode == 'horizontal') {
					this.options.els[i].setStyles({
						'float': 'left',
						'margin-left': this.options.separatorLength / 2,
						'margin-right': this.options.separatorLength / 2
					});
				}
				
				if(this.options.mode == 'horizontal')
					var theVal = this.options.els[i].getSize().x;
				else
					var theVal = this.options.els[i].getSize().y;
				
				this.containerLength += theVal + this.options.separatorLength;
				
				this.options.els[i].inject(this.containerFilm);
				
				// Get viewport size
				if(i == 1) {
					if(this.options.mode == 'horizontal')
						this.viewportSize = Math.round(this.contDims.width / (theVal + this.options.separatorLength));
					else
						this.viewportSize = Math.round(this.contDims.height / (theVal + this.options.separatorLength));
				}
			}
			
			if(this.options.mode == 'horizontal')
				this.containerFilm.setStyle('width', this.containerLength + 'px');
			else
				this.containerFilm.setStyle('height', this.containerLength + 'px');
		
		// Set up bars
			if(this.options.backButton)
				this.options.backButton.addEvent('click', function(e) {
					this.doAutoScroll = false;
					this.clearTimer();
					this.startScrollOne();
				}.bind(this));
			if(this.options.forwardButton)
				this.options.forwardButton.addEvent('click', function(e) {
					this.doAutoScroll = false;
					this.clearTimer();
					this.startScrollTwo();
				}.bind(this));
			
			// Set up FX
			this.scrollOne = new Fx.Scroll(this.options.container);
			this.direction = 1;
			
			// Set up scroll distance
			if(this.options.scrollDist == 0)
				this.options.scrollDist = this.viewportSize;
			
			if(this.options.els.length >= this.currentIndex + 1
			   && this.containerLength > this.contDims.width) {
				this.scrollOne.toElement(this.options.els[this.currentIndex]);
				
				// Start scrolling, if necessary
				if(this.options.autoScroll == true) {
					var theFunc = function() { this.startScrollTwo(); };
					theFunc.delay(this.options.startDelay, this);
				}
			}
			
			this.containerFilm.addEvents({
				'mouseenter': function() {
					this.pause();
				}.bind(this),
				'mouseleave': function() {
					this.unpause();
				}.bind(this)
			});
	},
	doScroll: function() {
		// Perform scroll
		if(this.options.els[this.currentIndex]) {
			this.scrollOne.toElement(this.options.els[this.currentIndex]);
		}
		
		//Set timeout again
		if(this.doAutoScroll == true) {
			if(this.direction == -1)
				this.autoScrollTimer = this.startScrollOne.delay(this.options.delay, this);
			else
				this.autoScrollTimer = this.startScrollTwo.delay(this.options.delay, this);
		}
	},
	startScrollOne: function() {
		// Determine which element we need to scroll to
		if(this.currentIndex == 0) {
			// We've reached the beginning...switch direction if we're on autoscroll
			if(this.doAutoScroll == true) {
				this.direction = 1;
				this.currentIndex = this.options.scrollDist - 1;
			}
			else	// Manual scroll...let's return since we're at the end
				return;
		}
		else if(this.currentIndex - this.options.scrollDist < 0)
			this.currentIndex = 0;
		else
			this.currentIndex -= this.options.scrollDist;
		
		this.doScroll();
	},
	startScrollTwo: function() {
		// Determine which element we need to scroll to
		if(this.currentIndex >= (this.options.els.length - this.viewportSize - 1)) {
			// We've reached the end...switch direction if we're on autoscroll
			if(this.doAutoScroll == true) {
				this.direction = -1;
				this.currentIndex = this.options.els.length - this.options.scrollDist;
			}
			else	// Manual scroll...let's return since we're at the end
				return;
		}
		else if(this.currentIndex + this.options.scrollDist > this.options.els.length - 1)
			this.currentIndex = this.options.els.length - 1;
		else
			this.currentIndex += this.options.scrollDist;
		
		this.doScroll();
	},
	clearTimer: function() {
		// Destroy timer hook
		$clear(this.autoScrollTimer);
	},
	pause: function() {
		this.clearTimer();
	},
	unpause: function() {
		this.doScroll();
	}
});
Scroller.implement(new Options, new Events);