if(Object.isUndefined(Controls))
	var Controls = {};

Controls.Slideshow = Class.create({
	
	currentFrame: null,
	
	paused: false,
	
	container: null,
	
	options: null,
	
	timer: null,
	
	initialize: function(container, options)
	{
		this.container = $(container);
		
		// default options
		this.options = {
			storageKey: 'slideshow',
			delay: 2,
			startSlide: 0,
			slideSelector: '.slide',
			reverse: false,
			autostart: true,
			pauseOnMouseover: true
		};
		Object.extend(this.options, options);
		var o = this.options;
		
		this.container.store(o.storageKey, this);
		if(o.pauseOnMouseover)
		{
			this.container.observe('mouseover', this.container_Mouseover.bind(this));
			this.container.observe('mouseout', this.container_Mouseout.bind(this));
		}

		if(o.autostart)
		{
			this.restart();
		}
	},
	
	container_Mouseover: function(event)
	{
		this.pause();
	},

	container_Mouseout: function(event)
	{
		this.resume();
	},
	
	restart: function()
	{
		var o = this.options;
		var slides = this.getSlides();
		
		slides.each(function(slide, index) {
			if(o.startSlide == index)
			{
				this.currentSlide = slide;
				slide.show();
			}
			else
			{
				slide.hide();
			}
		}.bind(this));
		
		this.resume();
	},
	
	getSlides: function()
	{
		var o = this.options;
		var s = o.slideSelector;
		return this.container.select(s);
	},
	
	slide: function(slide)
	{
		var o = this.options;
		if(!Object.isElement(slide))
		{
			slide = this.container.down(o.slideSelector, slide);
		}
		return slide;
	},
	
	change: function(slide, effectOptions)
	{
		var o = this.options;
		slide = this.slide(slide);
		if(!slide)
		{
			throw new Error("Missing 'slide'");
		}
		if(slide == this.currentSlide)
		{
			return; // because there's nothing to do
		}
		
		var prevSlide = this.currentSlide;
		this.currentSlide = slide;
		
		var _effectOptions = {
			afterFinish: Prototype.emptyFunction,
			moreEffects: []
		};
		Object.extend(_effectOptions, effectOptions || {});
		
		var effectAfterFinish = _effectOptions.afterFinish;
		_effectOptions.afterFinish = function ()
		{
			if(!this.paused)
			{
				this.resume();					
			}
			effectAfterFinish();
		}.bind(this);
		
		var effects = [
	    	new Effect.Appear(this.currentSlide, {sync : true}),
			new Effect.Fade(prevSlide, {sync : true})
		].concat(_effectOptions.moreEffects);
		new Effect.Parallel(effects, _effectOptions);
	},
	
	next: function(reverse)
	{
		var o = this.options;
		var s = o.slideSelector;
		var nextSlide = this.currentSlide[reverse ? 'previous' : 'next'](s);
		if(!nextSlide)
		{
			var slides = this.container.select(s);
			nextSlide = slides[reverse ? 'last' : 'first']();
		}
		this.change(nextSlide);
	},
	
	prev: function()
	{
		this.next(true);
	},
	
	pause: function()
	{
		this.paused = true;
		window.clearTimeout(this.timer);
		this.timer = null;
	},
	
	resume: function()
	{
		this.paused = false;
		var o = this.options;
		if(null !== this.timer)
		{
			// we don't want anymore events in the queue
			// this keeps stuff from overlapping in stressfull conditions
			window.clearTimeout(this.timer);
		}
		this.timer = this.next.bind(this).delay(o.delay, o.reverse);
	}
});

// usage
//slideshow = new Controls.Slideshow('slide-images');
