/*
 * authors of changes: robert schulte and christoph schmidt
 *  * We made following changes to this class:
 * 	- this.current was set with an slide object, we changed it to only a numeric index (there for we modify some functions)
 *  - you could set a class in dom with the wished transition effect, we delete this possibility because it works to slow and we don't want some dom loops :)
 *  - we add a possibility to give some effects for the seperated sliders in the given options (name: slideFx)
 *  	- slideFx needs something like that: slideFx : [{transition:fade, duration:500},{transition:blindLeft, duration:400}] (=> this were for slider index 0 and 1)
 * 
---

script: SlideShow.js

description: Easily extendable, class-based, slideshow widget. Use any element, not just images. Comes with packaged transitions but is easy to extend and create your own transitions.  The class is built to handle the basics of a slideshow, extend it to implement your own navigation piece and custom transitions.

license: MIT-style license.

authors: Ryan Florence

docs: http://moodocs.net/rpflo/mootools-rpflo/SlideShow

requires:
  - Loop

provides: [SlideShow]

...
*/


var SlideShow = new Class({
	
	Implements: [Options, Events, Loop],
		
		options: {
			/*
			onShow: $empty,
			onShowComplete: $empty,
			onReverse: $empty,
			onPlay: $empty,
			onPause: $empty
			*/
			slidersSelector: 'li',
			delay: 7000,
			transition: 'crossFade',
			duration: 500,
			autoplay: false,
			slideFx: []
		},
	
			/**
			 * slideFx = [{durataion: 123, transition: 'foo'}, ...]
			 */
	initialize: function(element, options){
		this.setOptions(options);
		this.setLoop(this.showNext, this.options.delay);
		this.element = document.id(element);
		this.slides = this.element.getElements(this.options.slidersSelector);
		this.current = 0;
		this.setup();
		if(this.options.autoplay) this.startLoop();
	},
	
	setup: function(){
	  this.setupElement();
	  this.setupSlides();
		return this;
	},
	
	setupElement: function(){
		var el = this.element;
		if(el.getStyle('position') != 'absolute' && el != document.body) el.setStyle('position','relative');
		return this;
	},
	
	setupSlides: function(){
		this.slides.each(function(slide, index){
			this.storeTransition(slide, index).reset(slide);
			if(index != 0) slide.setStyle('display','none');
		}, this);
		return this;
	},
	
	storeTransition: function(slide, index){

		var transition = this.options.transition;
		var duration = this.options.duration;
		
		if (this.options.slideFx[index]) {
			transition = this.options.slideFx[index].transition || this.options.transition;
			duration = this.options.slideFx[index].duration || this.options.duration;
		}

		slide.store('ssTransition', transition);
		slide.store('ssDuration', duration);
		return this;
	},
	
	getTransition: function(slide){
		return slide.retrieve('ssTransition');
	},
	
	getDuration: function(slide){
		return slide.retrieve('ssDuration');
	},
	
	show: function(slideIndex){

		if(slideIndex != this.current){
			var slide = this.slides[slideIndex];
			this.fireEvent('show', [slide, slideIndex]);
			var transition = this.getTransition(slide);
			var duration = this.getDuration(slide);
			var previous = this.slides[this.current].setStyle('z-index', 1);
			var next = this.reset(slide);
			
			this.transitions[transition](previous, next, duration, this);
			
			(function() { 
				previous.setStyle('display','none');
				this.fireEvent('showComplete', [slide, slideIndex]);
			}).bind(this).delay(duration);
			
			this.current = slideIndex;
		}
		return this;
	},
	
	reset: function(slide){
		return slide.setStyles({
			'position': 'absolute',
			'z-index': 0,
			'display': 'block',
			'left': 0,
			'top': 0
		}).fade('show');
	},
	
	nextSlide: function(){
		var next = this.current + 1;
		return (next >= this.slides.length) ? 0 : next;
	},

	previousSlide: function(){
		var previous = this.current - 1;
		return (previous <= 0) ? (this.slides.length - 1) : previous;
	},
	
	showNext: function(){
		this.show(this.nextSlide());
		return this;
	},
	
	showPrevious: function(){
		this.show(this.previousSlide());
		return this;
	},
	
	play: function(){
		this.startLoop();
		this.fireEvent('play');
		return this;
	},
	
	pause: function(){
		this.stopLoop();
		this.fireEvent('pause');
		return this;
	},
	
	reverse: function(){
		var fn = (this.loopMethod == this.showNext) ? this.showPrevious : this.showNext;
		this.setLoop(fn, this.options.delay);
		this.fireEvent('reverse');
		return this;
	}
	
});

SlideShow.adders = {
	
	transitions:{},
	
	add: function(className, fn){
		this.transitions[className] = fn;
		this.implement({
			transitions: this.transitions
		});
	},
	
	addAllThese : function(transitions){
		$A(transitions).each(function(transition){
			this.add(transition[0], transition[1]);
		}, this);
	}
	
}

$extend(SlideShow, SlideShow.adders);
SlideShow.implement(SlideShow.adders);

SlideShow.add('fade', function(previous, next, duration, instance){
	previous.set('tween',{duration: duration}).fade('out');
	return this;
});

SlideShow.addAllThese([

	['none', function(previous, next, duration, instance){
		previous.setStyle('display','none');
		return this;
	}],

	['crossFade', function(previous, next, duration, instance){
		previous.set('tween',{duration: duration}).fade('out');
		next.set('tween',{duration: duration}).fade('in');
		return this;
	}],
	
	['fadeThroughBackground', function(previous, next, duration, instance){
		var half = duration/2;
		next.set('tween',{
			duration: half
		}).fade('hide');
		previous.set('tween',{
			duration: half,
			onComplete: function(){
				next.fade('in');
			}
		}).fade('out');
	}],

	['pushLeft', function(previous, next, duration, instance){
		var distance = instance.element.getStyle('width').toInt();
		next.setStyle('left', distance);
		[next, previous].each(function(slide){
			var to = slide.getStyle('left').toInt() - distance;
			slide.set('tween',{duration: duration}).tween('left', to);
		});
		return this;
	}],
	
	['pushRight', function(previous, next, duration, instance){
		var distance = instance.element.getStyle('width').toInt();
		next.setStyle('left', -distance);
		[next, previous].each(function(slide){
			var to = slide.getStyle('left').toInt() + distance;
			slide.set('tween',{duration: duration}).tween('left', to);
		});
		return this;
	}],
	
	['pushDown', function(previous, next, duration, instance){
		var distance = instance.element.getStyle('height').toInt();
		next.setStyle('top', -distance);
		[next, previous].each(function(slide){
			var to = slide.getStyle('top').toInt() + distance;
			slide.set('tween',{duration: duration}).tween('top', to);
		});
		return this;
	}],
	
	['pushUp', function(previous, next, duration, instance){
		var distance = instance.element.getStyle('height').toInt();
		next.setStyle('top', distance);
		[next, previous].each(function(slide){
			var to = slide.getStyle('top').toInt() - distance;
			slide.set('tween',{duration: duration}).tween('top', to);
		});
		return this;
	}],
	
	['blindLeft', function(previous, next, duration, instance){
		var distance = instance.element.getStyle('width').toInt();
		next
			.setStyles({
				'left': distance,
				'z-index': 1
			})
			.set('tween',{duration: duration})
			.tween('left', 0);
		return this;
	}],

	['blindRight', function(previous, next, duration, instance){
		var distance = instance.element.getStyle('width').toInt();
		next
			.setStyles({
				'left': -distance,
				'z-index': 1
			})
			.set('tween',{duration: duration})
			.tween('left', 0);
		return this;
	}],
	
	['blindUp', function(previous, next, duration, instance){
		var distance = instance.element.getStyle('height').toInt();
		next
			.setStyles({
				'top': distance,
				'z-index': 1
			})
			.set('tween',{duration: duration})
			.tween('top', 0);
		return this;
	}],
	
	['blindDown', function(previous, next, duration, instance){
		var distance = instance.element.getStyle('height').toInt();
		next
			.setStyles({
				'top': -distance,
				'z-index': 1
			})
			.set('tween',{duration: duration})
			.tween('top', 0);
		return this;
	}],
	
	['blindDownFade', function(previous, next, duration, instance){
		this.blindDown(previous, next, duration, instance).fade(previous, next, duration, instance);
	}],
	
	['blindUpFade', function(previous, next, duration, instance){
		this.blindUp(previous, next, duration, instance).fade(previous, next, duration, instance);
	}],
	
	['blindLeftFade', function(previous, next, duration, instance){
		this.blindLeft(previous, next, duration, instance).fade(previous, next, duration, instance);
	}],
	
	['blindRightFade', function(previous, next, duration, instance){
		this.blindRight(previous, next, duration, instance).fade(previous, next, duration, instance);
	}]
	
]);
