var Protocycle = Class.create({
	initialize: function(container, options) {
		
		if(container instanceof Array)
		{
			container.each(function(el){
				new Protocycle(el, options);					  
			});
			return true;
		}
		else if(typeof(container) == 'string')
		{
			new Protocycle($$(container), options);
			return true;
		}
		
		this.options = {
			fx: 'fade', // 'fade' or 'none'
			timeout: 4000, // time between slide changes (in milliseconds)
			speed: 500, // time taken to do the transition (in milliseconds)
			sync: true, // true if in/out transitions should occur simultaneously 
			containerResize: true // automatically resize container to fit largest slide 
		}
		Object.extend(this.options, options || {});  
		
		
		// automatically set timeout option if the container element has a classname of 
		// timeout[n] where n is the desired value in milliseconds
		$w(container.className).each(function(classname){
			var result = classname.match(/timeout\[([0-9]+)\]/);
			
			if(result != null)
			{
				this.options.timeout = result[1];
			}
		}.bind(this));
	  
		var slideHeight = 0; // default
		var slideWidth = 0; // default
		this.currentSlide = 0;
		
		// If the holder isnt valid then stop here
		if(!container) return false;
		
		container.setStyle({position: 'relative'});
		this.slides = container.childElements();
		this.totalSlides = this.slides.size();
			
		// Work out the dimensions of the biggest slide, also hides all but the first slide
		var first = true;
		this.slides.each(function(el){
		
			if(Prototype.Browser.IE && parseInt(navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE")+5)) == 6)
			{
				var dimensions = el.getDimensions();
				el.setStyle({width: (dimensions.width-10)+'px'});
			}
				
			var dimensions = el.getDimensions();

			if(dimensions.height > slideHeight) slideHeight = dimensions.height;
			if(dimensions.width > slideWidth) slideWidth = dimensions.width;
			
			
			
			if(!first)
			{
				el.setStyle({display: 'none'});
			}
			first = false;
			el.setStyle({position: 'absolute'});
		
		});
		
		
		
		slideHeight += 10;
		
		// Automatically resize container?
		if(this.options.containerResize)
		{
			container.setStyle({height: slideHeight+'px', width: slideWidth+'px'});
			container.setStyle({overflow: 'visible'});
		}
		
		if(this.totalSlides > 1 && this.options.timeout > 0)
		{
			new PeriodicalExecuter(function() { this.nextSlide() }.bind(this), (this.options.timeout/1000));
		}
	},
	
	nextSlide: function()
	{
		var nextSlide = this.currentSlide + 1;
		if(nextSlide >= (this.totalSlides)) { nextSlide = 0; }
		
		if(this.options.fx == 'fade')
		{
	 
			var currentOpts = {from: 1.0, to: 0.0, duration: (this.options.speed/1000), afterFinish: function(effect) { effect.element.setStyle({display: 'none'}); }};
			var nextOpts = {from: 0.0, to: 1.0, duration: (this.options.speed/1000), afterSetup: function(effect) { effect.element.setStyle({display: 'block'});   }};
		
			if(this.options.sync)
			{
				// Run both animations in parallel.
				Object.extend(currentOpts, {sync: true});  
				Object.extend(nextOpts, {sync: true}); 
				
				new Effect.Parallel([
					new Effect.Opacity(this.slides[this.currentSlide], currentOpts),
					new Effect.Opacity(this.slides[nextSlide], nextOpts)
				]);
			}
			else
			{
				// Run in and out animation after one another.
				Object.extend(currentOpts, {queue: 'end'});  
				Object.extend(nextOpts, {queue: 'end'}); 
				
				new Effect.Opacity(this.slides[this.currentSlide], currentOpts);
				new Effect.Opacity(this.slides[nextSlide], nextOpts);
			}
		}
		else
		{
			// If no fx has been set then just do a simple swap
			this.slides[this.currentSlide].setStyle({display: 'none'});
			this.slides[nextSlide].setStyle({display: 'block'});
		}
		
		this.currentSlide++;
		
		if(this.currentSlide >= this.totalSlides)
		{
			this.currentSlide = 0;
		}
		
	}
});
