Slideshow = Class.create();
Object.extend(Object.extend(Slideshow.prototype, Abstract.prototype), {
	initialize: function(wrapper, options) {
		this.crossfading  = false;
		this.current    = -1;
		this.wrapper    = $(wrapper);
		this.wrapper.insert('<ol class="slide-controls"></ol>');

		this.scroller     = this.wrapper.down();
		this.slides       = this.scroller.childElements();
		this.options      = Object.extend({duration: 0.5, frequency: 3}, options || {});
		this.controlBar   = this.wrapper.down('.slide-controls');
		var slideControls = this.controlBar;

		this.slides.each( function(slide, index) {
			slideControls.insert('<li><a href="#slide' + (index+1) + '">Go to slide ' + (index+1) + '</a></li>');
			var slideControl = slideControls.childElements()[index];
			slideControl._index = index;
			slide.hide();
		});

		this.controls = slideControls.childElements();
		
		this.events = {
			click: this.click.bind(this)
		};

		this.addObservers();
		this.moveTo(0, this.scroller, 0);
		this.start();
	},
	
	addObservers: function() {
		var controls = this.controlBar.select('a');
		controls.invoke('observe', 'click', this.events.click);
	},

	click: function(event) {
		this.stop();
		Event.stop(event);
		var element = Event.findElement(event, 'a');
		if (element.up()._index == this.current) return false;
		
		if (this.crossfading) this.crossfading.cancel();
		this.moveTo(element.up()._index, this.scroller, this.options.duration);
	},

	moveTo: function(index, container, duration) {
		var oldSlide = null;
		var newSlide = null;
		
		if (this.current > -1) {
			this.slides[this.current].removeClassName('active');
			this.controls[this.current].removeClassName('active');
			oldSlide = this.slides[this.current];
		}

		this.current = index;
		this.slides[this.current].addClassName('active');
		this.controls[this.current].addClassName('active');
		newSlide = this.slides[this.current];


		this.crossfading 	= new Effect.CrossFade(newSlide, oldSlide, {duration:duration});
		return false;
	},

	next: function() {
		var nextIndex = (this.slides.length - 1 == this.current) ? 0 : this.current + 1;
		this.moveTo(nextIndex, this.scroller, this.options.duration);
	},

	previous: function() {
		var prevIndex = (this.current == 0) ? this.slides.length - 1 : this.current - 1;
		this.moveTo(prevIndex, this.scroller, this.options.duration);
	},

	stop: function() {
		clearTimeout(this.timer);
	},

	start: function() {
		this.periodicallyUpdate();
	},

	periodicallyUpdate: function() {
		if (this.timer != null) {
			clearTimeout(this.timer);
			this.next();
		}
		this.timer = setTimeout(this.periodicallyUpdate.bind(this), this.options.frequency*1000);
	}

});

Effect.CrossFade = Class.create();
Object.extend(Effect.CrossFade.prototype, {
	initialize: function(newElement, oldElement, options) {
		this.newElement = newElement;
		this.oldElement = oldElement;
		this.appearing = new Effect.Appear(this.newElement, options);
		if (this.oldElement) {
			this.fading = new Effect.Fade(this.oldElement, options);
		}
	},
	cancel: function() {
		if (this.appearing) {
			this.appearing.cancel();
			this.newElement.show();
		}
		if (this.fading) {
			this.fading.cancel();
			this.oldElement.hide();
		}
	}
});
