var Slideshow = Class.create();

/** Default options for slideshow. */
var SlideshowOptions = {
	duration: 3,
	playing: true,
	showLargerLink: true
};

Slideshow.prototype = {
	/** @lends Slideshow# */
	
	Version: 0.1,
	
	/**
	 * Creates a new Slideshow instance.
	 * @constructs
	 * @requires Lightbox 2.0+
	 * @version 0.1 alpha
	 * @author <a href="mailto:ttarplee@qualcomm.com">Todd Tarplee</a>
	 *
	 * @param {String|Element} element The DIV with class "slideshow".
	 * @param {Object} lightbox A reference to the lightbox for the page.
	 * @param {Object} [options] Any options needed to overload the defaults.
	 * @param {Number} [options.duration=3] Set the duration of each slide when playing.
	 * @param {Boolean} [options.playing=true] Determines if the slideshow will play on load.
	 * @param {Boolean} [options.showLargerLink=true] Whether or not to show the "View larger" text below the slideshow.
	 *
	 * @property {Boolean} playing. Whether or not the slideshow is playing.
	 * @property {Boolean} hovered. Whether or not the slideshow is moused over.
	 * @property {Boolean} element The DIV with class "slideshow".
	 * @property {Boolean} element.slideshow. Makes the slideshow instance accessible directly from the the element (e.g., $('my-slideshow').slideshow).
	 * @property {Number} currentIndex The index of the current slide.
	 */
	initialize: function(element, lightbox, options) {
		this.element = $(element);
		this.element.slideshow = this;
		this.lightbox = lightbox;
		this.options = Object.extend(SlideshowOptions, options || {});
		this.playing = this.options.playing;
		this._items = this.element.select('li');
		this.currentIndex = 0;
		this._currentItem = this._items.first();
		this._firstPlay = true;
		this._initItems();
		this._initViewLargerLink();
		this._initOverlay();
		if(this.playing)
			this.play();
	},
	
	/** Play the slideshow. */
	play: function() {
		this.playing = true;
		this.toggle.addClassName('playing');
		if(this._firstPlay)
			this._firstPlay = false;
		if(!this.hovered)
			this._start();
	},
	
	/** Pause the slideshow. */
	pause: function() {
		this.playing = false;
		this.toggle.removeClassName('playing');
		this._stop();
	},
	
	/**
	 * Change to a different slide.
	 * @param {Number} [index] Will change to selected index. If no index passed, it will go to the next slide.
	 */
	changeSlide: function(index) {
		var nextIndex;
		if(index && $R(0,this._items.length).include(index))
			nextIndex = index;
		else {
			nextIndex = this._items.indexOf(this._currentItem) + 1;
			if(nextIndex + 1 > this._items.length) 
				nextIndex = 0;	
		}
		this._currentItem.fade();
		this.currentIndex = nextIndex;
		this._currentItem = this._items[nextIndex];
		this._currentItem.appear();
	},
	
	/*----- Private -----*/
	
	_overlayMouseover: function(event) {
		this.hovered = true;
		//console.log("over: "+event.element().inspect());
		var target = event.findElement('div.overlay');
		clearTimeout(this.overlay.timeoutId);
		/** @ignore */
		this.overlay.timeoutId = function() {
			this._stop();
			if(!target.shown)
				new Effect.Opacity(target, {
					from: 0, 
					to: 1, 
					duration: 0.15, 
					afterFinish: function(obj) {
						obj.element.shown = true;
					}
				});
		}.bind(this).delay(0.15);
	},
	
	_overlayMouseout: function(event) {
		this.hovered = false;
		//console.log("out: "+event.element().inspect());
		var target = event.findElement('div.overlay');
		clearTimeout(this.overlay.timeoutId);
		/** @ignore */
		this.overlay.timeoutId = function() {
			if(this.playing && !this.lightbox.lightbox.visible())
				this._start();
			new Effect.Opacity(target, {
				from: 1, 
				to: 0, 
				duration: 0.15,
				afterFinish: function(obj) {
					obj.element.shown = false;
				}
			});
		}.bind(this).delay(0.15);
	},
	
	_openClick: function() {
		this._openLightbox();
	},
	
	_toggleClick: function() {
		this.playing ? this.pause() : this.play();
	},
	
	_start: function() {
		if(this.playLoop)
			this.playLoop.stop();
		this.playLoop = new PeriodicalExecuter(function(pe) {
			if(this.restartLoop) {
				this.restartLoop.stop();
				this.restartLoop = undefined;
			}
			this.changeSlide();
		}.bind(this), this.options.duration);
	},
	
	_stop: function(listenForLightboxClose) {
		if(this.playLoop) {
			this.playLoop.stop();
			this.playLoop = undefined;
		}
		if(listenForLightboxClose) {
			this.restartLoop = new PeriodicalExecuter(function(pe) {
				if(!this.lightbox.lightbox.visible()) {
					if(this.playing)
						this._start();
					pe.stop();
				} else if(this.lightbox.activeImage != this._items.indexOf(this._currentItem)) {
					this.changeSlide(this.lightbox.activeImage);
				}
			}.bind(this), 0.5);
		}
	},
	
	_initItems: function() {
		this._items.each(function(el, index) {
			if(index > 0) 
				el.hide();
		});
	},
	
	_initViewLargerLink: function() {
		if(this.options.showLargerLink) {
			this.largerLink = new Element('a', {'class':'larger', href:'#'});
			this.element.insert({bottom:this.largerLink.update('View larger')});
			this.largerLink.observe('click', this._openLightbox.bind(this));
		}
	},
	
	_initOverlay: function() {
		this.open = new Element('a', {'class':'open', href:'#', title:'View larger'});
		this.toggle = new Element('a', {'class':'toggle', href:'#', title:'Play or pause the slideshow'});
		var inner = new Element('div', {'class':'overlay-inner'});
		this.overlay = new Element('div', {'class':'overlay'}).update(inner);
		this.overlay.insert({bottom: this.toggle});
		this.overlay.insert({bottom: this.open});
		this.overlay.setStyle({
			opacity: 0
		});
		this.overlay.down('.overlay-inner').setStyle({
			width: this.element.select('ol').first().getWidth() + 'px',
			height: this.element.select('ol').first().getHeight() + 'px'
		});
		this.element.insert({top: this.overlay});
		this.toggle.observe('click', this._toggleClick.bindAsEventListener(this));
		this.open.observe('click', this._openClick.bindAsEventListener(this));
		this.overlay.observe('mouseover', this._overlayMouseover.bindAsEventListener(this));
		this.overlay.observe('mouseout', this._overlayMouseout.bindAsEventListener(this));
		(function() {
			var ovd = this.overlay.getDimensions();
			var tgd = this.toggle.getDimensions();
			var opd = this.open.getDimensions();
			this.toggle.setStyle({
				top: (ovd.height/2-tgd.height/2) + 'px',
				left: (ovd.width/2-tgd.width-5) + 'px' 
			});
			this.open.setStyle({
				top: (ovd.height/2-opd.height/2) + 'px',
				left: (ovd.width/2+5) + 'px'
			});
		}.bind(this)).defer();
	},
	
	_openLightbox: function() {
		this.lightbox.start(this._currentItem.down('a'));
		this._stop(true);
	}
	
}