/*
	ConveyorBelt
	Author: Marty Stake <marty@ericksonbarnett.com>
	Dependencies: Prototype 1.6 / Scriptaculous effects.js
	Version: .021
	
	new ConveyorBelt('.filmstrip-group', { 
			autoPlay: true, 
			carousel: true, 
			clip: 'filmstrip-clip', 
			container: 'filmstrip-holder',
			duration: 4.5
		} );
		
		{ updater : function() {
				$$('.update')[0].update('Slide ' + parseInt(this.current + 1) + ' of ' + this.numSlides) 
			} }
	
*/

var ConveyorBelt = Class.create( { 

	initialize: function(slides, options) {
		
		this.options = {
			scroll: 1, // how many slides are scrolled.  Only '1' works correctly right now 
			visible: 1, // how many slides are visible at one time.
			speed: 1, // rate of movement
			action: 'click', 
			clip: $('conveyor'), // wrapper that has the clip width and height
			container: $('conveyor-belt'), // div that gets its axis shifted
			nextButton: $$('#next-button')[0],
			prevButton: $$('#previous-button')[0],
			group: 'conveyor',
			hideForward: true, // whether we zoom to the beginning when you get to the last slide
			disableButton: false, // whether we put a disabled class on the button, or hide it
			carousel: false,
			autoPlay: false,
			duration: 3 // duration of autoPlay
			
		} 
		
		Object.extend( this.options, options || {} );
		
		this.slides = (typeof slides == 'string') ? $$(slides) : slides;
		
		this.slideIDs = [];
		
		this.clip = typeof ( this.options.clip == 'string' ) ? $(this.options.clip) : this.options.clip;
		this.container = typeof this.options.container == 'string' ? $(this.options.container) : this.options.container;
		
		this.distance = this.options.distance || parseInt(this.slides[0].getWidth());
		this.height = this.options.height || parseInt(this.slides[0].getHeight());
		
		this.numSlides = this.slides.length;

		this.current = 0; 
		this.speed = this.options.speed;
		
		this.effectRunning = false;
		
		this.nextButton = this.options.nextButton;
		this.prevButton = this.options.prevButton;
		
		this.nextButton.setStyle( 'cursor: pointer' );
		this.prevButton.setStyle( 'cursor: pointer' );
	
		this.setup();
		
		var query = window.location.toString().toQueryParams();
		
		if( query.slide ) {	
			this.moveTo(query.slide);
		}
		
	},
	
	setup: function() {
		
		var self = this;
		
		Event.observe( this.nextButton, this.options.action, this.moveForward.bind(this) );
		Event.observe( this.prevButton, this.options.action, this.moveBackward.bind(this) );
		
		Event.observe(document, 'keypress', function(e) {
	
			if (e.keyCode == Event.KEY_RIGHT) {
				self.moveForward(e)
			}
			if (e.keyCode == Event.KEY_LEFT) {
				self.moveBackward(e)
			}
		});
		
		this.slides.each( function(slide, x) {
			self.slideIDs[x] = slide.id = slide.id || self.options.group + '-slide-' + x;
		});
		
		if (this.options.autoPlay) {
			this.setAutoPlay();
		}
		
		if (this.options.carousel) {
			var firstSlide = this.slides[0].cloneNode(true);
			firstSlide.id = 'clone-first';
			var lastSlide = this.slides[this.slides.length-1].cloneNode(true);
			lastSlide.id = 'clone-last';
			lastSlide.hide(); // prevent flash of added slide //
			this.container.insert( { bottom : firstSlide }).insert({ top : lastSlide });
			this.container.setStyle( { left: (this.current + 1) * -this.distance + 'px', position: 'relative' });
			lastSlide.show(); // prevent flash of added slide //
		}
		
		this.afterMove();
		
	},
	
	setAutoPlay: function() {
		this.player = window.setInterval(this.moveForward.bind(this), this.options.duration * 1000);
	},
	
	stopAutoPlay: function() {
		window.clearInterval(this.player);
	},
	
	moveForward: function(e) {
		if (e && e.stop) {
			e.stop();
			this.stopAutoPlay();
		}
		
		var next = this.current + this.options.scroll;
		if (this.effectRunning) return;
		
		if ( (next + this.options.visible) <= this.numSlides ) {
			this.moveTo(next, 'button');
		} else {
			if (this.options.carousel) {
				this.moveTo(next, 'button');
			} else {
				this.moveTo(0, 'button');
			}
		}
	},
	
	moveBackward: function(e) {
		if (e && e.stop) {
			e.stop();
			this.stopAutoPlay();
		}
		var next = this.current - this.options.scroll;
		
		if (this.effectRunning) return;
		
		if (next >= 0) {
			this.moveTo(next, 'button');
		} else {
			if (this.options.carousel) this.moveTo(next, 'button');
		}
	},
	
	
	
	moveTo : function(el) {
	
		if (this.effectRunning) return;
		var self = this;
		
		switch (typeof el) {
			case 'string' : 
				el = $(el);
				var newSlideIndex = this.slideIDs.indexOf(el.id);
				break;
			case 'number' :
				var newSlideIndex = el;
				break;
			default :
				var newSlideIndex = this.slideIDs.indexOf(el.id);
				break;
		}
		
		
		var scroll = this.options.scroll;
		
		if ( (newSlideIndex < 0 || newSlideIndex == this.current || newSlideIndex > (this.numSlides - 1)) && !this.options.carousel ) return false;
		
		var delta = this.current - newSlideIndex;
		var scroll = (arguments[1] == 'button') ? this.options.scroll : 1;
		var distance = delta * (this.distance * scroll);
		
		// for speedy swap //
		var jump = (delta == 1) || (delta == -1) ? 1 : 3;		
	
		this.effectRunning = new Effect.MoveBy(this.container, 0, distance, { duration: this.speed/jump, afterFinish: function(e) { self.effectRunning = null; self.afterMove(); } } );
		
		this.current = newSlideIndex;
	
	},
	
	afterMove : function() {
		
			if (this.current == 0 && !this.options.carousel) {
				this.options.disableButton ? this.prevButton.addClassName('disabled') : this.prevButton.hide();
			} else {
				this.options.disableButton ? this.prevButton.removeClassName('disabled')  : this.prevButton.show();
			}
			
			if ( this.current >= this.numSlides && this.options.carousel ) {
				this.current = 0;
				this.container.setStyle({ left: (this.current + 1) * -this.distance + 'px' });
			}
			
			if ( this.current < 0 && this.options.carousel ) {
				this.current = this.numSlides - 1;
				this.container.setStyle({ left: (this.current + 1) * -this.distance + 'px' });
			}
			
			
			if (this.options.hideForward && !this.options.carousel ) {
				if ( (this.current + this.options.visible) >= this.numSlides && !this.options.carousel ) {
					this.options.disableButton ? this.nextButton.addClassName('disabled') : this.nextButton.hide();
				} else {
					this.options.disableButton ? this.nextButton.removeClassName('disabled')  : this.nextButton.show();
				}
			}
		
			if (typeof this.options.updater == 'function') this.options.updater.apply(this)
		
	}
	
});
