/*
---

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 <http://ryanflorence.com>

requires:
- /Loop
- more:1.2.4.4:Fx.Elements

provides: [SlideShow, Element.playSlideShow, Element.pauseSlideShow]

...
*/


var SlideShow = new Class({
	
	Implements: [Options, Events, Loop],
		
	options: {
		/*
		onShow: $empty,
		onShowComplete: $empty,
		onReverse: $empty,
		onPlay: $empty,
		onPause: $empty,
		*/
		delay: 7000,
		transition: 'crossFade',
		duration: '500',
		autoplay: false
	},

	initialize: function(element, options){
		this.setOptions(options);
		this.setLoop(this.showNext, this.options.delay);
		this.element = document.id(element);
		
		// ghooghe - Do we need to activate the carousel ?
        var images = this.element.getChildren('img');
        if (images != null) {
			if (images.length > 1) {
				this.prepareItems();
				this.addDoubleMask();
				this.slides = this.element.getChildren();
				this.current = this.slides[0];
				this.transitioning = false;
				this.setup();
				this.addPager();
				if (this.options.autoplay) this.play();
			} else if (images.length == 1) {
				// ghooghe - add element for rounded corned display
				var className = 'carouselmask-small';
				if (images[0].getSize().y != null && (images[0].getSize().y).toInt() > 120) {
					className = 'carouselmask-large'
				}
				var mask = new Element('div', {
					'class': className
				});
				mask.inject(this.element, 'after');
			}
		}
	},
	
	// ghooghe - prepare items for carousel
    prepareItems: function() {
    	var item = null;
    	var info = null;
		this.element.getChildren().each(function(el) {
			if (el.get('tag') == 'h3') {
				item = new Element('a', {
		    		'class': 'carousel-item',
		    		 events: {
			    		mouseover: function() {
							this.pause();
						}.bind(this),
			    		mouseout: function() {
							this.play();
						}.bind(this)
					}
		    	});
				info = new Element('div', {
		    		'class': 'carousel-item-info'
		    	});
				item.adopt(info);
				this.element.adopt(item);
				info.adopt(el);
			} else if (el.get('tag') == 'p') {
				var link = el.getChildren('a')[0];
				item.set('href', link.get('href'));
				var strong = new Element('strong', {
					'html': link.get('html')
				});
				info.adopt(strong);
				el.destroy();
			} else {
				el.inject(item, 'top');
			}
		}.bind(this));
		
		this.element.setStyle('height', '290px');
	},
	
	// ghooghe - add 2 elements for rounded corner display
	addDoubleMask: function() {
		var maskLeft = new Element('div', {
			'class': 'carouselmask-left'
		});
		var maskRight = new Element('div', {
			'class': 'carouselmask-right'
		});
		maskLeft.inject(this.element, 'after');
		maskRight.inject(this.element, 'after');
		
	},
	
	// ghooghe - add a pager for quick navigation
	addPager: function() {
		this.pager = new Element('ul', {
			'class': 'carousel-nav'
		});
		this.slides.each(function(el, idx) {
			var li = new Element('li');
			var title = el.getChildren('h3')[0];
			var link = new Element('a', {
				'href': el.get('href'),
				'title': title,
				'html': title, 
				events: {
					mouseover: function() {
						this.pause();
						this.show(idx);
					}.bind(this),
					mouseout: function() {
						this.play();
					}.bind(this)
				}
			});
			if (idx == 0) {
				link.addClass('selected');
			}
			li.adopt(link);
			this.pager.adopt(li);
		}.bind(this));
		this.pager.inject(this.element, 'bottom');
		
	},
	
	setup: function(){
	  this.setupElement().setupSlides(true);
		return this;
	},
	
	setupElement: function(){
		var el = this.element;
		if (el.getStyle('position') != 'absolute' && el != document.body) el.setStyle('position','relative');
		return this;
	},
	
	setupSlides: function(hideFirst){
		this.slides.each(function(slide, index){
			this.storeTransition(slide).reset(slide);
			if (hideFirst && index != 0) slide.setStyle('display','none');
		}, this);
		return this;
	},
	
	storeTransition: function(slide){
		var classes = slide.get('class');
		var transitionRegex = /transition:[a-zA-Z]+/;
		var durationRegex = /duration:[0-9]+/;
		var transition = (classes.match(transitionRegex)) ? classes.match(transitionRegex)[0].split(':')[1] : this.options.transition;
		var duration = (classes.match(durationRegex)) ? classes.match(durationRegex)[0].split(':')[1] : this.options.duration;
		slide.store('ssTransition', transition).store('ssDuration', duration);
		return this;
	},
	
	resetOptions: function(options){
		this.options = $merge(this.options, options);
		this.setupSlides(false);
		return this;
	},
	
	getTransition: function(slide){
		return slide.retrieve('ssTransition');
	},
	
	getDuration: function(slide){
		return slide.retrieve('ssDuration');
	},
	
	show: function(slide, options){
		slide = (typeof slide == 'number') ? this.slides[slide] : slide;
		if (slide != this.current && !this.transitioning){
			this.transitioning = true;
			var transition = (options && options.transition) ? options.transition: this.getTransition(slide),
				duration = (options && options.duration) ? options.duration: this.getDuration(slide),
				previous = this.current.setStyle('z-index', 1),
				next = this.reset(slide);
			var slideData = {
				previous: {
					element: previous,
					index: this.slides.indexOf(previous)
				}, 
				next: {
					element: next,
					index: this.slides.indexOf(next)
				}
			};
			this.fireEvent('show', slideData);

			// ghooghe - pager update selected class
			var pagerLinks = this.pager.getElements('a');
			pagerLinks.removeClass('selected');
			var nextSlideIndex = this.slides.indexOf(slide);
			pagerLinks[nextSlideIndex].addClass('selected');

			this.transitions[transition](previous, next, duration, this);
			(function() { 
				previous.setStyle('display','none');
				this.fireEvent('showComplete', slideData);
				this.transitioning = false;
			}).bind(this).delay(duration);
			this.current = next;
		}
		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.getNext();
		// ghooghe - poor hack to avoid moving to page as next
		if (next.get('tag') == 'ul') {
			next = null;
		}
		return (next) ? next : this.slides[0];
	},

	previousSlide: function(){
		var previous = this.current.getPrevious();
		return (previous) ? previous : this.slides.getLast();
	},
	
	showNext: function(options){
		this.show(this.nextSlide(), options);
		return this;
	},
	
	showPrevious: function(options){
		this.show(this.previousSlide(), options);
		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;
	},
	
	toElement: function(){
		return this.element;
	}
	
});

Element.Properties.slideshow = {

	set: function(options){
		var slideshow = this.retrieve('slideshow');
		if (slideshow) slideshow.pause();
		return this.eliminate('slideshow').store('slideshow:options', options);
	},

	get: function(options){
		if (options || !this.retrieve('slideshow')){
			if (options || !this.retrieve('slideshow:options')) this.set('slideshow', options);
			this.store('slideshow', new SlideShow(this, this.retrieve('slideshow:options')));
		}
		return this.retrieve('slideshow');
	}

};


Element.implement({
	
	playSlideShow: function(options){
		this.get('slideshow', options).play();
		return this;
	},
	
	pauseSlideShow: function(options){
		this.get('slideshow', options).pause();
		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.getSize().x;
		next.setStyle('left', distance);
		new Fx.Elements([previous,next],{duration: duration}).start({
			0: { left: [-distance] },
			1: { left: [0] }
		});
		return this;
	}],

	['pushRight', function(p,n,d,i){
		var distance = i.element.getSize().x;
		n.setStyle('left', -distance);
		new Fx.Elements([p,n],{duration: d}).start({
			0: { left: [distance] },
			1: { left: [0] }
		});
		return this;
	}],

	['pushUp', function(p,n,d,i){
		var distance = i.element.getSize().y;
		n.setStyle('top', distance);
		new Fx.Elements([p,n],{duration: d}).start({
			0: { top: [-distance] },
			1: { top: [0] }
		});
		return this;
	}],

	['pushDown', function(p,n,d,i){
		var distance = i.element.getSize().y;
		n.setStyle('top', -distance);
		new Fx.Elements([p,n],{duration: d}).start({
			0: { top: [distance] },
			1: { top: [0] }
		});
		return this;
	}],

	['blindRight', function(p,n,d,i){
		var distance = i.element.getSize().x;
		n.setStyles({
			left: -distance,
			'z-index': 2
		}).set('tween',{duration: d}).tween('left',0);
		return this;
	}],

	['blindLeft', function(p,n,d,i){
		var distance = i.element.getSize().x;
		n.setStyles({
			left: distance,
			'z-index': 2
		}).set('tween',{duration: d}).tween('left',0);
		return this;
	}],

	['blindUp', function(p,n,d,i){
		var distance = i.element.getSize().y;
		n.setStyles({
			top: distance,
			'z-index': 2
		}).set('tween',{duration: d}).tween('top',0);
		return this;
	}],

	['blindDown', function(p,n,d,i){
		var distance = i.element.getSize().y;
		n.setStyles({
			top: -distance,
			'z-index': 2
		}).set('tween',{duration: d}).tween('top',0);
		return this;
	}],

	['blindDownFade', function(p,n,d,i){
		this.blindDown(p,n,d,i).fade(p,n,d,i);
	}],

	['blindUpFade', function(p,n,d,i){
		this.blindUp(p,n,d,i).fade(p,n,d,i);
	}],

	['blindLeftFade', function(p,n,d,i){
		this.blindLeft(p,n,d,i).fade(p,n,d,i);
	}],

	['blindRightFade', function(p,n,d,i){
		this.blindRight(p,n,d,i).fade(p,n,d,i);
	}]

]);

