var Slideshow = new Class({
	Implements: [Options, Events, Log],
	
	options: {
		allowSlidesMenu: false,
		slideAxis: 'x',
		loop: 'reset', // 'continue', 'reset' or false
		autoPlay: true,
		slideOptions: {
			duration: 5000,
			delay: 500
		},
		animation: {
			duration: 500,
			transition: Fx.Transitions.linear.easeOut
		},
		updateCallback: null
	},
	
	// Variables
	element: null,
	slidesElement: null,
	slides: [],
	size: null,
	activeSlideIndex: 0,
	autoPlayTimer: null,
	fx: null,
	isPaused: false,
	hideSlideTimer: null,
	
	// Class variables
	menu: null,
	
	/*
	 * Initialize
	 */
	initialize: function(element, options)
	{
		//this.enableLog();
		this.log("Slideshow::initialize(" + element + ", " + options + ")");
		
		// Set options
		this.setOptions(options);

		// Set variables
		this.element = element;
		this.slidesElement = this.element.getElement('.slides');

		var size = this.element.measure( function() { return this.getSize(); } );
		this.size = { width: size.x, height: size.y };
		
		// Build slideshow
		this.build();

		// Load
		this.load();
		
		// Enable slideshow
		//this.enable();

		// Start slideshow
		this.start();
	},
	
	/*
	 * Reset
	*/
	reset: function()
	{
		this.log("Slideshow::reset()");
		
		// Set active slide index
		this.activeSlideIndex = 0;

		if(this.options.allowSlidesMenu)
		{
			this.menu.reset();
		}


		// Set begin postion
		this.setPosition(this.activeSlideIndex);
		
		// Enable slideshow
		this.enable();
	},
	
	/*
	 * Build
	 */
	build: function()
	{
		this.log("Slideshow::build()");

		// Create slide instances
		this.slidesElement.getElements('.slide').each(function(element, index) {

			this.log("element: " + element);

			var slide = new SlideshowSlide(element, this.options.slideOptions);

			this.slides.include(slide);

		}.bind(this));

		// Create instances
		if(this.options.allowSlidesMenu)
		{
			var menuOptions = {};
			this.menu = new SlideshowMenu(this, $('home'), this.slides, menuOptions);
		}


		// Create slide fx
		this.slidesElement.fx = new Fx.Tween(this.slidesElement, {
			duration: this.options.animation.duration,
			transition: this.options.animation.transition,
			link: 'cancel'
		});

		this.slidesElement.fx.addEvent('start', function() {
			
			this.log("start slidesElement.fx");
			
		}.bind(this));

		this.slidesElement.fx.addEvent('complete', function() {

			this.log("complete slidesElement.fx");

		}.bind(this));

		// Clone first and last slides for continue loop effect
		if(this.options.loop == 'continue')
		{
			var firstSlide = this.slides[0];
			this.slidesElement.adopt(firstSlide.element.clone());

			var lastSlide = this.slides[this.slides.length - 1];
			lastSlide.element.clone().inject(this.slidesElement, 'top');
		}

		// Set new container size
		this.setSlideContainerSize();
	},

	/*
	 * Load
	 */
	load: function()
	{
		this.log("Slideshow::load()");

		// Set begin postion
		this.setPosition(this.activeSlideIndex);
	},

	/*
	 * Show
	 */
	show: function()
	{
		this.log("Slideshow::show()");
		
		this.slidesElement.show();
	},
	
	/*
	 * Hide
	 */
	hide: function()
	{
		this.log("Slideshow::hide()");
		
		this.slidesElement.hide();
	},
	
	/*
	 * Enable
	 */
	enable: function()
	{
		this.log("Slideshow::enable()");
		
		this.addEvents();
	},
	
	/*
	 * Disable
	 */
	disable: function()
	{
		this.log("Slideshow::disable()");

		this.removeEvents();
	},
	
	/*
	 * Start
	 */
	start: function()
	{
		this.log("Slideshow::start()");
		
		// Auto play
		if(this.options.autoPlay)
		{
			this.play();
		}
	},
	
	/*
	 * Stop
	 */
	stop: function()
	{
		this.log("Slideshow::stop()");
		
		this.pause();
	},
	
	/*
	 * Play
	 */
	play: function()
	{
		this.log("Slideshow::play()");
		
		if(!this.autoPlayTimer && this.slides.length > 1)
		{
			this.isPaused = false;
			//this.autoPlayTimer = this.slide.periodical(this.options.duration, this, 'next');
			this.slideTo(this.activeSlideIndex, null, null);
		}
	},
	
	/*
	 * Pause
	 */
	pause: function()
	{
		this.log("Slideshow::pause()");
		
		this.isPaused = true;
		//this.autoPlayTimer = this.clearInterval(this.autoPlayTimer);
	},
	
	/*
	 * Add events
	 */
	addEvents: function()
	{
		this.log("Slideshow::addEvents()");
		
		// First remove events to prevent duplicate event calls
		this.removeEvents();
		
	},
	
	/*
	 * Remove events
	 */
	removeEvents: function()
	{
		this.log("Slideshow::removeEvents()");
		
	},


	/*
	 * Set position
	 */
	setPosition: function(index)
	{
		this.log("SlideShow::setPosition(" + index + ")");

		// Recalculate index for continuous loop effect
		if(this.options.loop == 'continue')
		{
			index += 1;
		}

		if(this.options.slideAxis == 'y')
		{
			var position = index * -this.size.height;
			this.slidesElement.setStyle('top', position);
		}
		else
		{
			var position = index * -this.size.width;
			this.slidesElement.setStyle('left', position);
		}
	},

	/*
	 * Slide
	 */
	slide: function(command)
	{
		this.log("Slideshow::slide(" + command + ")");

		var pauseSlideShow = false;
		var scrollToIndex;
		var resetIndex;
		var loop = false;

		if(command == "previous")
		{
			scrollToIndex = this.activeSlideIndex - 1;

			// Check if slideshow should be paused
			if(scrollToIndex <= 0)
			{
				if(!this.options.loop)
				{
					// Stop slideshow
					pauseSlideShow = true;
				}
				else if(scrollToIndex < 0)
				{
					// Slideshow looped
					loop = true;

					// Reset index for reset loop effect
					if(this.options.loop == 'reset')
					{
						scrollToIndex = this.slides.length - 1;
					}
					else
					{
						resetIndex = this.slides.length - 1;
					}
				}
			}
		}
		else
		{
			scrollToIndex = this.activeSlideIndex + 1;

			this.log("1. scrollToIndex: " + scrollToIndex);
			this.log("this.slides.length: " + this.slides.length);

			// Check if slideshow should be paused
			if(scrollToIndex >= this.slides.length - 1)
			{
				this.log("in if");
				if(!this.options.loop)
				{
					// Stop slideshow
					pauseSlideShow = true;
				}
				else if(scrollToIndex > this.slides.length - 1)
				{
					// Slideshow looped
					loop = true;

					// Reset index for reset loop effect
					if(this.options.loop == 'reset')
					{
						scrollToIndex = 0;
					}
					else
					{
						resetIndex = 0;
					}
				}
			}

			this.log("2. scrollToIndex: " + scrollToIndex);
			this.log("1. resetIndex: " + resetIndex);
		}

		if(
			((scrollToIndex >= 0 && this.options.loop != 'continue') || (scrollToIndex >= -1 && this.options.loop == 'continue')) &&
			((scrollToIndex <= this.slides.length - 1 && this.options.loop != 'continue') || (scrollToIndex <= this.slides.length && this.options.loop == 'continue'))
		)
		{
			// Show next slide
			this.slideTo(scrollToIndex, resetIndex, loop);
		}

		// Check if slideshow must pause
		if(pauseSlideShow)
		{
			this.pause();
		}

	},

	/*
	 * Slide to
	 */
	slideTo: function(index, resetIndex, loop)
	{
		this.log("SlideShow::slideTo(" + index + ", " + resetIndex + ", " + loop + ")");

//		if(index != this.activeSlideIndex)
//		{
			// Disable slideshow
			this.disable();

			// Set complete handler
			this.slidesElement.fx.removeEvents('complete');
			this.slidesElement.fx.addEvent('complete', function() {
				this.log("fire update(" + index + ", " + resetIndex + ")");

				var slide = this.slides[ index ];
				slide.show.delay(this.options.slideOptions.delay, slide);
				slide.removeEvents('hide');
				slide.addEvent('hide', function() {

					this.log("slideshowSlide hide event");

					this.update( index, resetIndex );
					this.slide('next');

				}.bind(this));

				//this.update( index, resetIndex );
			}.bind(this));

			// Recalculate index for continuous loop effect
			if(this.options.loop == 'continue')
			{
				index += 1;
			}

			if(this.options.slideAxis == 'y')
			{
				var position = index * -this.size.height;
				this.slidesElement.fx.start('top', position);
			}
			else
			{
				var position = index * -this.size.width;

				this.log("position: " + position);
				this.slidesElement.fx.start('left', position);
			}
//		}

	},

	/*
	 * Update
	 */
	update: function( index, resetIndex )
	{
		this.log("SlideShow::update(" + index + ", " + resetIndex + ")");

		this.activeSlideIndex = [resetIndex, index].pick();

		this.log("this.activeSlideIndex: " + this.activeSlideIndex);

		if( resetIndex )
		{
			this.setPosition( this.activeSlideIndex );
		}

		// Enable slideshow
		this.enable();

//		if( this.options.autoPlay && !this.isPaused )
//		{
//			this.play();
//		}
	},

	/*
	 * Slide
	 *
	slide: function()
	{
		this.log("Slideshow::slide()");

		var activeSlide = this.slides[this.activeSlideIndex];

		activeSlide.show();
		activeSlide.removeEvents('show');
		activeSlide.removeEvents('hide');
		activeSlide.addEvent('show', function(event) {

			activeSlide.hideSlideTimer = activeSlide.hide.delay(this.options.duration, activeSlide);

		}.bind(this));
		activeSlide.addEvent('hide', function(event) {

			this.update();
			this.slide();

		}.bind(this));

		// Select menu item
		this.menu.selectMenuItem(this.activeSlideIndex);
	},

	/*
	 * Show slide
	 *
	showSlide: function(index)
	{
		this.log("Slideshow::showSlide(" + index + ")");

		// Hide old slide and remove all events
		this.slides.each(function(slide, index) {
			$clear(slide.hideSlideTimer);
			slide.removeEvents('show');
			slide.removeEvents('hide');
		}.bind(this));

		var activeSlide = this.slides[this.activeSlideIndex];

		activeSlide.addEvent('hide', function(event) {

			this.update(index);
			this.slide();

		}.bind(this));

		activeSlide.hide();
	},

	/*
	 * Update
	 *
	update: function(index)
	{
		this.log("Slideshow::update(" + index + ")");

		var newActiveSlideIndex = this.activeSlideIndex + 1;

		if(index != null)
		{
			newActiveSlideIndex = index;
		}

		this.activeSlideIndex = newActiveSlideIndex % this.slides.length;

//		this.log("newActiveSlideIndex: " + newActiveSlideIndex);
//		this.log("this.activeSlideIndex: " + this.activeSlideIndex);
//		this.log("this.slides.length: " + this.slides.length);
	},


	/*
	 * Set slide container size
	 */
	setSlideContainerSize: function()
	{
		this.log("SlideShow::setSlideContainerSize()");

		var slidesWidth;
		var slidesHeight;
		var slidesAmount;

		// Recalculate index for continuous loop effect
		if(this.options.loop == 'continue')
		{

			slidesAmount = this.slides.length + 2;
		}
		else
		{
			slidesAmount = this.slides.length;
		}

		if(this.options.slideAxis == 'y')
		{
			slidesWidth = this.size.width;
			slidesHeight = this.size.height * slidesAmount;
		}
		else
		{
			slidesWidth = this.size.width * slidesAmount;
			slidesHeight = this.size.height;
		}

		this.slidesElement.setStyle('width', slidesWidth);
		this.slidesElement.setStyle('height', slidesHeight);

		this.log("slidesWidth: " + slidesWidth);
		this.log("slidesHeight: " + slidesHeight);
	}
	
});
