var Fadr = new Class({
	Implements: [Options, Events],
	options: {
		delay: 7000,
		fadeDuration: 1000
	},
	
	initialize: function (el, options, autostart) {
		this.stop = false;
		this.el = $(el);
		this.autostart = autostart;
		this.setOptions(options);
		if (this.el.getFirst().getFirst() && this.el.getFirst().getFirst().getNext()) {
			this.overlay = this.el.getFirst().getFirst().getNext();
			this.overlay.setStyles({'display': 'block', 'opacity':1, 'bottom': 4, 'left': 4}).inject(this.el.getParent());
		} else {
			this.overlay = false;
		}
		if (this.autostart) {
			this.fade.delay(this.options.delay, this);
		}
	},
	
	next: function () {
		if (this.stop == 'prev') {
			this.el.getElements('div').reverse();
		}
		this.stop = 'next';
		this.fade();
	},
	
	prev: function () {
		if (this.stop != 'prev')
			this.el.getElements('div').reverse();
		this.stop = 'prev';
		this.fade();
	},
	
	start: function () {
		this.fade.delay(this.options.delay, this);
	},
	
	fade: function () {
		// Grab first banner
		this.current = this.el.getFirst();
		if (!this.current.getNext()) {
			return;
		}
		
		this.tween = new Fx.Tween(this.current, {
			duration: this.options.fadeDuration,
			transition: this.options.transition,
			link: 'chain',
			property: 'opacity'
		});
		
		// Copy next banner image to container background
		this.el.setStyle('background', 'url(' + this.current.getNext().getElement('img').get('src') + ')');
		
		if (!this.overlay) {
			this.tween.start(1, 0).addEvent(
				'onComplete', function () {
					if (!this.stop) {
						// move top of list to bottom.
						var lastElement = this.el.getFirst().dispose();
						lastElement.setStyle('opacity', 1).inject(this.el);
						this.fade.delay(this.options.delay, this);
					}
				}.bind(this));
		} else {
			this.morph = new Fx.Morph(this.overlay, {
				duration: this.options.fadeDuration,
				transition: this.options.transition,
				link: 'chain'
			});
			// Fade overlay up and out
			this.morph.start({
				opacity: [1, 0],
				bottom: [4, 4],
				left: [4, 4]
			})
			// Chain into Fade banner
			.chain(function(){
				// Fade banner
				this.tween.start(1, 0).addEvent(
					'onComplete', function () {
						// move overlay back to holding layer
						this.overlay.dispose().inject(this.el.getFirst()).setStyles({'display': 'none'});
						
						// move top of list to bottom.
						var lastElement = this.el.getFirst().dispose();
						lastElement.setStyle('opacity', 1).inject(this.el);
						
						this.overlay = this.el.getFirst().getFirst().getNext();
						if (this.overlay) {
							this.overlay.inject(this.el.getParent()).setStyles({'display': 'block', 'opacity': 0});
						}
						this.morph = new Fx.Morph(this.overlay, {
							duration: this.options.fadeDuration,
							transition: this.options.transition,
							link: 'chain'
						}).start({
							opacity: [0, 1],
							bottom: [4, 4],
							left: [4, 4]
						})
						// Chain loop on completion
						.addEvent('onComplete', function () {
							if (!this.stop) {
								this.fade.delay(this.options.delay, this);
							}
						}.bind(this)); // close event
					}.bind(this)); // close event
			}.bind(this));
		}
	}
});

var Slidr = new Class({

	Implements: [Options, Events],

	options: {
		slideDelay: 3000,
		slideDuration: 500,
		slideWidth: 100,
		transition: 'quad',
		canPause: false,
		fadeIn: true,
		direction: 'left'
	},

	initialize: function (el, options) {
		this.el = $(el);
		this.setOptions(options);
		this.setupComponent();
	},

	setupComponent: function() {
		this.slider = new Element('div').setStyles({
			'position': 'relative',
			'overflow': 'hidden',
			'width': this.el.getWidth(),
			'height': this.el.getHeight()
		}).wraps(this.el);
		
		if (this.options.canPause) {
			this.el.addEvents({
				'mouseenter': function(e) {
					this.store('mouseOver', true);
				},
				'mouseleave': function(e) {
					this.eliminate('mouseOver');
				}
			});
		}
	},

	getInternalWidth: function() {
		var width = 0;

		this.el.getChildren().each(function(el) {
			width += el.getWidth() + el.getStyle('margin-left').toInt() + el.getStyle('margin-right').toInt();
		});

		return width;
	},
	
	getInternalHeight: function() {
		var height = 0;
		this.el.getChildren().each(function(el) {
			height += el.getHeight () + el.getStyle('margin-top').toInt() + el.getStyle('margin-bottom').toInt();
		});
		return height;
	},

	start: function() {
		var internalWidth  = this.getInternalWidth();
		var internalHeight = this.getInternalHeight();
		
		var width  = internalWidth  > this.el.getSize().x ? internalWidth  : this.el.getSize().x;
		var height = internalHeight > this.el.getSize().y ? internalHeight : this.el.getSize().y;
		
		this.el.setStyles({
			'width': width,
			'height': height,
			'position': 'relative'
		});
		
		this.el.set('tween', {
			duration: this.options.slideDuration,
			transition: this.options.transition,
			link: 'cancel',
			onComplete: function() {
				this.el.setStyle(this.options.direction, 0).getFirst().dispose().removeClass('firstItem').inject(this.el);
				
				if (this.options.fadeIn) {
					this.el.getFirst().addClass('firstItem').tween('opacity', 0, 1);
				}
				else {
					this.el.getFirst().addClass('firstItem');
				}

				this.slideComponent.delay(this.options.slideDelay, this);
			}.bindWithEvent(this)
		});
		this.slideComponent.delay(this.options.slideDelay, this);
	},

	slideComponent: function() {
		if (this.stop) { return; }
		if (this.slider) {
			if (this.el.retrieve('mouseOver')) {
				this.slideComponent.delay(1000, this);
			} else {
				var lrMargin = this.el.getFirst().getStyle('margin-left').toInt() + this.el.getFirst().getStyle('margin-right').toInt();
				var tbMargin = this.el.getFirst().getStyle('margin-top').toInt() + this.el.getFirst().getStyle('margin-bottom').toInt();
				
				switch (this.options.direction) {
				case 'left':
					this.el.tween('left', this.el.getWidth() - this.el.getFirst().getWidth() - lrMargin);
					break;
				case 'right':
					this.el.tween('right', this.el.getFirst().getWidth() + lrMargin);
					break;
				case 'top':
					this.el.tween('top', this.el.getHeight() - this.el.getFirst().getHeight() - tbMargin);
					break;
				case 'bottom':
					this.el.tween('bottom', this.el.getFirst().getHeight() + tbMargin);
					break;
				}
			}
		}
	},
	
	play: function () {
		this.stop = false;
		this.start();
	},
	
	pause: function () {
		this.stop = true;
	},

	toElement: function() {
		return ($defined(this.slider) ? this.slider : this.el);
	}
});

SlidingCarousel = new Class({
	Implements: [Options, Events, Chain],

	options: {
		slideDuration: 500,
		transition: 'quad',
		fadeIn: true,
		direction: 'left',
		closeWidth: 50,
		link: 'chain'
	},
	position: 0,
	
	initialize: function (element, options) {
		this.element = element;
		this.setOptions(options);
		if ($(this.element)) {
			this.setupCarousel();
		}
	},
	
	setupCarousel: function () {
		this.element.getElements('.panel').each (function (el){
			el.set('open', true);
			if (el.getElement('.button')) {
				el.getElement('.button').addEvent(
					'click', function (e){
						e.stop();
						var target = $(e.target.getParent());
						if (target.get('tag') == 'a') {
							this.trigger($(e.target).getParent().getParent());
						}
						else {
							this.trigger($(e.target).getParent());
						}
					}.bindWithEvent(this));
			}
		}.bind(this));
		this.openPanel(this.element.getElements('.panel')[0], 0);
	},
	
	trigger: function (element) {
		this.position = 0;
		
		if (element.get('open') == 'true') {
			this.closePanel(element, 0);
		}
		else {
			this.openPanel(element, 0);
		}
	},
	
	closePanel: function (element, i) {
		if (!element) {
			return;
		}
		// close all panels above this one
		else if (element.getPrevious()) {
			this.closePanel(element.getPrevious(), i+1);
		}
		
		// grab the width of the current panel
		var width = element.getStyle('width').toInt();
		
		if (width != this.options.closeWidth + this.position) {
			// store the width inside the element
			element.set('w', width);
			
			this.chain (
				function () {
					element.getChildren().each(function(el) {
						if (!el.hasClass('button')) {
							if (i != 0) {
								el.set('tween', {duration: 'short'});
								el.fade('out');
							}
						}
						else {
							el.getElement('span.title').set('tween', {duration: 'long'});
							if (i == 0) {
								this.clearChain();
								this.chain (
									function () {
										el.getElement('span.arrow').set('tween', {duration: 'long'}).fade('out');
										this.callChain();
									},
									function () {
										el.getElement('span.title').fade('out');
										this.callChain();
									},
									function () {
										el.getElement('span.arrow').addClass('rotate180').fade('in');
										this.callChain();
									}
								);
								this.callChain();
							}
							else {
								el.getElement('span.title').fade('in');
								el.getElement('span.arrow').removeClass('rotate180');
							}
						}
					}.bind(this));
					this.callChain();
				},
				function () {
					if (i != 0) {
						new Fx.Morph (element, {
							options: this.options,
							
							onStart: function (el) {
								
							},
							onComplete: function (el) {
								el.set('open', false);
							}.bind(this)
						}).start ({
							width: [element.getStyle('width'), this.options.closeWidth + this.position]
						});
						this.callChain();
					}
				}
			);
			this.callChain();
		}
		this.position += 10;
	},
	
	openPanel: function(element, i) {
		if (!element) {
			return;
		}
		else if (element.getNext()) {
			this.openPanel(element.getNext(), i+1);
		}
		
		new Fx.Morph (element, {
			options: this.options,
			onComplete: function (element) {
				element.set('open', true);
			}.bind(this)
		}).chain(function () {
			element.getChildren().each(function(el) {
				if (!el.hasClass('button')) {
					el.set('tween', {duration: 'long'});
					el.fade('in');
				}
				else {
					el.getElement('span.title').set('tween', {duration: 'long'});
					if (i == 0) {
						this.chain (
								function () {
									el.getElement('span.arrow').set('tween', {duration: 'long'}).fade('out');
									this.callChain();
								},
								function () {
									el.getElement('span.title').fade('out');
									this.callChain();
								},
								function () {
									el.getElement('span.arrow').addClass('rotate180').fade('in');
									this.callChain();
								}
							);
							this.callChain();
					}
					else {
						el.getElement('span.title').fade('in');
						el.getElement('span.arrow').removeClass('rotate180');
					}
				}
			}.bind(this));
		}).start ({
			width: [element.getStyle('width').toInt(), element.get('w')]
		});
	}
});
