/*
	Author: Leon Radley (digiPlant)
	Status: Beta, not complete
	Creation Date: 2010-10-26
*/

var Slideshow = new Class({

	Implements: [Events, Options, Class.Binds],

	options: {
		fx: {
			inFx: {
				transition: 'fade',
				duration: 1000
			},
			outFx: {
				transition: 'fade',
				duration: 500
			}
		},
		visibleAtStart: true,
		autoplay: true,
		interval: 4000,
		loop: true,
		pauseOnHover: true,
		attachSlide: function(data){
			this.container.adopt(new Element('li', {
				'data-load': data.image
			}));
		}
	},

	initialize: function(container, options){
		this.container = document.id(container);
		this.setOptions(options);
		
		if(this.container == null)
			return;
		
		if(this.options.url){
			this.attach(this.options.url);
		} else {
			this.attach();
		}
	},
	
	toElement: function(){
		return this.container;
	},
	
	attach: function(url){
		if(url){
			this.request = new Request.JSON({
				url: url,
				onSuccess: this.bound('requestSuccess')
			}).get();
		} else {
			this.start();
		}
		if(this.options.pauseOnHover){
			this.container.addEvents({
				mouseenter: this.bound('pause'),
				mouseleave: this.bound('play')
			});
		}
	},
	
	detach: function(){
		this.container.removeEvents({
			mouseenter: this.bound('pause'),
			mouseleave: this.bound('play')
		});
		this.pause();
	},
	
	play: function(){
		clearInterval(this.timer);
		this.timer = this.next.periodical(this.options.interval, this);
	},
	
	pause: function(){
		clearInterval(this.timer);
	},
	
	next: function(){
		if(this.slides.length == 0) return;
		this.transition(this.current.getNext() || this.current.getParent().getFirst());
	},
	
	previous: function(){
		if(this.slides.length == 0) return;
		this.transition(this.current.getPrevious() || this.current.getParent().getLast());
	},
	
	gotoSlide: function(i){
		var slide = this.slides[i];
		this.transition(slide);
	},
	
	/*
	Private Methods
	*/
	requestSuccess: function(data){
		this.container.empty();
		Array.each(data, this.options.attachSlide.bind(this));
		this.start();
	},
	
	start: function(){
		this.slides = this.container.getChildren();
		this.fireEvent('pages', this.slides.length);
		this.slides.setStyles({
			'visibility': 'hidden',
			'z-index': 0
		});
		this.current = this.slides[0];
		this.current.setStyles({
			'visibility': 'visible',
			'z-index': 1
		});
		if(this.shouldPreload(this.current))
			this.preload(this.current);
		else if(this.options.autoplay && this.slides.length > 1)
			this.play();
	},
	
	shouldPreload: function(slide){
		return slide.getProperty('data-load');
	},
	
	preload: function(slide){
		this.fireEvent('preload', slide);
		var img = Asset.image(this.shouldPreload(slide), {
			onload: function(){
				this.fireEvent('preloadComplete', slide);
				slide.removeProperty('data-load');
				slide.adopt(img);
				this.transition(slide);
			}
		});
	},
	
	transition: function(slide){
		clearInterval(this.timer);
		slide = (typeof slide == 'number') ? this.slides[slide] : slide;
		if(slide == null)
			return this;
			
		if(this.shouldPreload(slide)){
			this.preload(slide);
			return this;
		}
		var previous = this.current.setStyle('z-index', 0),
		next = slide.setStyles({
			'visibility': 'hidden',
			'z-index': 1
		}),
		transitionData = {
			previous: {
				element: previous,
				index: this.slides.indexOf(previous)
			}, 
			next: {
				element: next,
				index: this.slides.indexOf(next)
			}
		};
		this.fireEvent('transition', transitionData);
		
		var previousOptions = Object.merge(this.options.fx, previous.retrieve('slideshow:fx'))
		var nextOptions = Object.merge(this.options.fx, next.retrieve('slideshow:fx'))
		
		var previousTransition = Slideshow.Transition[previousOptions.outFx.transition];
		if(previousTransition){
			previousTransition.transitionOut(this.container, previous, next, previousOptions.outFx.duration, nextOptions.inFx.duration);
		} else {
			console.log('Error: Slideshow.Transition.' + previousFx.outFx.transition + ' not found.');
		}
		
		var nextTransition = Slideshow.Transition[nextOptions.inFx.transition];
		if(nextTransition){
			nextTransition.transitionIn(this.container, previous, next, previousOptions.outFx.duration, nextOptions.inFx.duration);
		} else {
			console.log('Error: Slideshow.Transition.' + nextOptions.inFx.transition + ' not found.');
		}
		
		this.transitionComplete.delay(Math.max(previousOptions.outFx.duration, nextOptions.inFx.duration), this, transitionData);
		this.current = next;
		this.fireEvent('change', this.slides.indexOf(this.current));
		return this;
	},
	
	transitionComplete: function(transitionData){
		this.fireEvent('transitionComplete', transitionData);
		if(this.options.autoplay)
			this.play();
	}
});
Slideshow.Transition = {
	fade: {
		transitionIn: function(container, previous, next, previousDuration, nextDuration){
			next.fade('hide').set('tween', {duration: nextDuration}).fade('in');
		},
		transitionOut: function(container, previous, next, previousDuration, nextDuration){
			previous.set('tween', {duration: previousDuration}).fade('out');
		}
	}
};

var Navigation = new Class({

	Implements: [Options, Events, Class.Binds],

	options: {
		symbol: '●'
		//onChange
	},

	pages: null,

	initialize: function(element, options){
		this.element = document.id(element);
		this.setOptions(options);
		this.element.addEvent('click:relay(a)', this.bound('click'));
	},

	setElements: function(){
		this.elements = this.element.getElements('li');
		this.elements[0].addClass('active');
	},

	createElements: function(num){
		var self = this;
		if(num < 2) return;
		this.element.empty();
		num.each(function(i){
			self.element.adopt(
				new Element('li').adopt(
					new Element('a', {href: '#', text: self.options.symbol})
				)
			);
		});
		this.setElements();
	},

	setActive: function(active){
		if(!this.elements)
			return;
		this.elements.removeClass('active');
		this.elements[active].addClass('active');
	},

	click: function(event, a){
		event.preventDefault();
		if(!this.elements)
			return;
		this.fireEvent('change', this.elements.indexOf(a.getParent()));
	}
});
