//############################################################################################
// (c) 2011 Dominik Felber - http://dfelber.de/
//############################################################################################
// v 1.1


var SLIDE_BEHAVIOUR = {
	LEFT_TO_RIGHT:	'slide_behaviour_left_to_right',
	RIGHT_TO_LEFT: 	'slide_behaviour_right_to_left',
	UP_TO_BOTTOM: 	'slide_behaviour_up_to_bottom',
	BOTTOM_TO_UP: 	'slide_behaviour_bottom_to_up',
	CROSSFADE: 			'slide_behaviour_crossfade',
	RANDOM: 				'slide_behaviour_random',	
};


var Slider = new Class({

	Implements: [Options],

	options: {
		spaceBetweenSlides: 15,
		slideBehaviour: SLIDE_BEHAVIOUR.RANDOM,
		slideTime: 500,
		showTime: 1000,
		slideAlways: false,
		transition: 'linear',
		nextButton: undefined,
		lastButton: undefined,
		keysAllowed: true,
		slideOnMouseOver: false,
		slideClass: undefined
	},

	initialize: function(element, options){
		if(!element){
			return;
		}
	
		this.currentMorph = null;
		this.nextMorph = null;
		
		this.autoSlider = null;
		this.changeLock = false;
		this.currentIndex = 0;
		this.items = -1;
		this.setOptions(options);
		this.element = element;
		
		this.prepare();
		this.start();
	},
	
	prepare: function(){
		this.element.setStyles({
			'overflow': 'hidden',
			'position': 'relative'
		});
		
		this.width = this.element.getStyle('width').toInt();
		this.height = this.element.getStyle('height').toInt();

		var child;
		var children = [];
		var options = this.options;
		var slideTime = options.slideTime;
		var showTime = options.showTime;
		var transition = options.transition;
		
		while((child = ((options.slideClass) ? this.element.getFirst(options.slideClass) : this.element.getFirst()))){
			child.setStyle('position', 'absolute');
			children.push(child.dispose());
		}
		
		this.items = children.length;
		
		this.currentItem = children[0];
		this.element.adopt(this.currentItem);
		
		this.children = children;
	
		
		this.currentMorph = new Fx.Tween(this.currentItem, {
			'duration': slideTime,
			'link': 'ignore',
			'transition': transition
		});
		
		
		this.nextMorph = new Fx.Tween(this.currentItem, {
			'duration': slideTime,
			'link': 'ignore',
			'transition': transition
		});
		
		
		this.currentMorph.addEvent('complete', this._onComplete.bind(this));
		
		
		this.nextMorph.addEvent('complete', function(){
			this.changeLock = false;			
		}.bind(this));
	
		if(options.keysAllowed){
			document.addEvent('keyup', function(event) {
			    if (event.key == 'left'){
			        this.last();
			    }
			    if (event.key == 'right'){
			        this.next();
			    }
			}.bind(this));
		}
		
		if(options.nextButton){
			options.nextButton.addEvent('click', this.next.bind(this));
		}
		
		if(options.lastButton){
			options.lastButton.addEvent('click', this.last.bind(this));
		}
		
		if(options.slideOnMouseOver){
			this.element.addEvent('mouseenter', function(){
				if(this.autoSlider == null){
					this.autoSlider = this.next.periodical(options.slideTime + options.showTime, this);
					this.next();
				}
			}.bind(this));
			
			this.element.addEvent('mouseleave', function(){
				clearInterval(this.autoSlider);
				this.autoSlider = null;
			}.bind(this));
		}
	},
	
	start: function(){
		var options = this.options;
	
		if(options.slideAlways && this.items > 1){
			this.autoSlider = this.next.periodical(options.slideTime + options.showTime, this);
		}
	},
	
	_resetCurrent: function(){
		this.currentItem.setStyles({
			'z-index': 2,
			'opacity': 1,
			'margin-left': 0,
			'margin-top': 0
		});
	},
	
	_onComplete: function(){
		this.currentItem.destroy();
		this.currentItem = this.nextItem;
		this.changeLock = false;
	},
	
	next: function(){
		if(this.changeLock == true){
			return;
		}

		var behaviour = this.options.slideBehaviour;

		if(behaviour == SLIDE_BEHAVIOUR.RANDOM){
			behaviour = Object.values(SLIDE_BEHAVIOUR).getRandom();
			
			if(behaviour == SLIDE_BEHAVIOUR.RANDOM){
				this.next();
				return;
			}
		}
		
		this.changeLock = true;
		
		if(++this.currentIndex >= this.items){
			this.currentIndex = 0;
		}
		
		this.nextItem = this.children[this.currentIndex];
		this.nextMorph.element = this.nextItem;
		this.currentMorph.element = this.currentItem;
		
		this.element.adopt(this.nextItem);
		
		this._resetCurrent();
		
	
		if(this.items > 1){
			switch(behaviour){
				case SLIDE_BEHAVIOUR.LEFT_TO_RIGHT:
					this.leftToRight();
					break;
					
				case SLIDE_BEHAVIOUR.RIGHT_TO_LEFT:
					this.rightToLeft();
					break;
					
				case SLIDE_BEHAVIOUR.UP_TO_BOTTOM:
					this.topToBottom();
					break;
					
				case SLIDE_BEHAVIOUR.BOTTOM_TO_UP:
					this.bottomToTop();
					break;

				case SLIDE_BEHAVIOUR.CROSSFADE:
					this.crossfade();
					break;
				default:
					//
					break;
			}
		}
	},
	
	last: function(){
		if(this.changeLock == true){
			return;
		}
	
		var behaviour = this.options.slideBehaviour;
		
		if(behaviour == SLIDE_BEHAVIOUR.RANDOM){
			behaviour = Object.values(SLIDE_BEHAVIOUR).getRandom();
			
			if(behaviour == SLIDE_BEHAVIOUR.RANDOM){
				this.last();
				return;
			}
		}
		
		this.changeLock = true;
		
		if(--this.currentIndex < 0){
			this.currentIndex = this.items-1;
		}
		
		this.nextItem = this.children[this.currentIndex];

		this.nextMorph.element = this.nextItem;
		this.currentMorph.element = this.currentItem;
		
		this.element.adopt(this.nextItem);
		
		this._resetCurrent();
		
	
		if(this.items > 1){
			switch(behaviour){
				case SLIDE_BEHAVIOUR.LEFT_TO_RIGHT:
					this.rightToLeft();
					break;
					
				case SLIDE_BEHAVIOUR.RIGHT_TO_LEFT:
					this.leftToRight();
					break;
					
				case SLIDE_BEHAVIOUR.UP_TO_BOTTOM:
					this.bottomToTop();
					break;
					
				case SLIDE_BEHAVIOUR.BOTTOM_TO_UP:
					this.topToBottom();
					break;

				case SLIDE_BEHAVIOUR.CROSSFADE:
					this.crossfade();
					break;
				default:
					//
					break;
			}
		}
	},
	
	
	leftToRight: function(){
		var options = this.options;
		var spaceBetweenSlides = options.spaceBetweenSlides;

		this.nextItem.setStyles({
			'margin-left': -this.width - spaceBetweenSlides,
			'margin-top': 0,
			'opacity': 1
		});

		this.currentMorph.start('margin-left', this.width + spaceBetweenSlides);
		this.nextMorph.start('margin-left', 0);
	},
	
	rightToLeft: function(){
		var options = this.options;
		var spaceBetweenSlides = options.spaceBetweenSlides;
		
		this.nextItem.setStyles({
			'margin-left': this.width + spaceBetweenSlides,
			'margin-top': 0,
			'opacity': 1
		});
		
		this.currentMorph.start('margin-left', -this.width - spaceBetweenSlides);
		this.nextMorph.start('margin-left', 0);
	},
	
	topToBottom: function(){
		var options = this.options;
		var spaceBetweenSlides = options.spaceBetweenSlides;
		
		this.nextItem.setStyles({
			'margin-top': -this.height - spaceBetweenSlides,
			'margin-left': 0,
			'opacity': 1
		});
		
		this.currentMorph.start('margin-top', this.height + spaceBetweenSlides);
		this.nextMorph.start('margin-top', 0);
	},
	
	bottomToTop: function(){
		var options = this.options;
		var spaceBetweenSlides = options.spaceBetweenSlides;
		
		this.nextItem.setStyles({
			'margin-top': this.height + spaceBetweenSlides,
			'margin-left': 0,
			'opacity': 1
		});
		
		this.currentMorph.start('margin-top', -this.height - spaceBetweenSlides);
		this.nextMorph.start('margin-top', 0);
	},
	
	crossfade: function(){
		var options = this.options;
		var spaceBetweenSlides = options.spaceBetweenSlides;
		
		this.nextItem.setStyles({
			'opacity': 0,
			'z-index': 1,
			'margin-left': 0,
			'margin-top': 0
		});
		
		this.currentMorph.start('opacity', 0);
		this.nextMorph.start('opacity', 1);
	}
});
