/*
 * @name Simple Prototype Slideshow Class
 * @version 0.9
 * @author Andrew Peel <http://dotandpixel.com/> Adapted for Prototype
 * @author Jon Raasch <http://jonraasch.com/> Originally released model
 * @copyright 2011 Apparent Communications Pty Ltd <http://apparent.com.au/>
 * @license FreeBSD
 * @url http://dotandpixel.com/dev/slideshow
 * @require prototype.js, effects.js
 */


if(typeof(Prototype) == "undefined") {
    throw "Slideshow requires Prototype to be loaded."; }
if(typeof(Effect) == "undefined") {
	throw "Slideshow requires Effects to be loaded."; }
	
var Slideshow = Class.create(Prototype, {
    initialize:function(_slideshow_container,_options){
		this.instID = 'Slideshow.' + this.timestamp();
		this.options = {
            /*beforeChange: Prototype.emptyFunction,
            afterChange: Prototype.emptyFunction,
            hover: false,
            linkSelector: 'li a',
            setClassOnContainer: false,
            activeClassName: 'active',
            defaultTab: 'first',
            autoLinkExternal: true,
            targetRegExp: /#(.+)$/,
            showFunction: Element.show,
            hideFunction: Element.hide,*/
			loop: 0,
			startDelay: 0,
			fadeInDuration: 0.5,
			fadeInDelay: 0.5,
			fadeOutDuration: 0.5,
			fadeOutDelay: 1.5,
			onComplete: Prototype.emptyFunction.bind(this),
			completeVisible: true,
			continuous: true /* different to infinite looping */
        };
		
		Object.extend(this.options, _options || {});
		this.lynchpin = true;
		this.wrapper = $(_slideshow_container);
		this.a = this.wrapper.descendants();
		this.wrapper.setStyle({"display":"block"});
		this.totalLoopNum = (this.options.loop*this.a.length)-1;
		
	},
	
	timestamp: function(){
		return new Date().getTime();
	},
	
	id: function(){
		return this.instID;
	},

	index:function(elm){
		var nodes = elm.parentNode.childNodes, node;
	    var i = count = 0;
	    while( (node=nodes.item(i++)) && node!=elm )
	        if( node.nodeType==1 ) count++;
	   	 	return count;
	},
	
	startDelay: function(){
		return this.options.startDelay;
	},
	
	start: function(){
		this.reset();
		this.lynchpin = true;
		return this.loopSlideshow();
	},
	
	stop: function(){
		this.lynchpin = false;
		//console.log("stop() -> lynchpin: "+this.lynchpin);
		this.reset();
		return this.lynchpin;
	},
	
	reset: function(){
		// remove active previous
		(this.wrapper.down('.previous')) ? this.wrapper.down('.previous').removeClassName('active previous') : null;
		// remove active
		(this.wrapper.down('.active')) ? this.wrapper.down('.active').removeClassName('active') : null;
		// set active to last
		(!this.a[this.a.length-1].hasClassName('active')) ? this.a[this.a.length-1].addClassName('active') : null;
		// reset count
		this.c = 0;
		//set all to opacity 0
		this.wrapper.select('img').each(function(e){ e.setStyle({"opacity":"0"}); });
		
		return true;
	},
	
	isPlaying: function(){
		return this.lynchpin;
	},
	
	completeCallback: function(){
		//console.log("slideshow -> completeCallback");
		this.options.onComplete();
	},

	loopSlideshow:function(){
		//console.log("loopSlideshow() -> lynchpin: "+this.lynchpin);
		if(this.isPlaying()){
				this.active = this.wrapper.down('.active');
				this.next = (this.index(this.active) < this.a.length-1) ? this.active.next() : this.a[0];
				//this.active.addClassName('previous');
				( this.active.hasClassName('previous') ) ? null : this.active.addClassName('previous');		
				$(this.next).appear({ duration: this.options.fadeInDuration, delay: this.options.fadeInDelay, from: 0.0, to: 1, afterFinish: function(){  
					//this.next.addClassName('active');
					( this.next.hasClassName('active') ) ? null : this.next.addClassName('active');
					if(this.options.loop > 0){
						// loop totalLoopNum of times, then stop
						if(this.c < this.totalLoopNum && this.isPlaying()){ 
							this.c++;
							$(this.next).fade({ duration: this.options.fadeOutDuration, delay: this.options.fadeOutDelay, from: 1.0, to: 0.0, afterFinish: function(){
								if(this.isPlaying()){
									(this.active.hasClassName('active previous')) ? this.active.removeClassName('active previous') : null;
									// continue looping 
									//console.log("continue");
									this.loopSlideshow();
								}
							}.bind(this)});
						} else {
							if(this.options.completeVisible){
								// visibie finish
								//console.log("visibie finish");
								this.stop();
								this.completeCallback();
							} else {
								// hidden finish
								//console.log("hidden finish");
								$(this.next).fade({ duration: this.options.fadeOutDuration, delay: this.options.fadeOutDelay, from: 1.0, to: 0.0, afterFinish: function(){
									(this.active.hasClassName('active previous')) ? this.active.removeClassName('active previous') : null;
										this.stop();
										this.completeCallback();	
								}.bind(this)});
							}
						}
					} else {
						// infinite looping
						$(this.next).fade({ duration: this.options.fadeOutDuration, delay: this.options.fadeOutDelay, from: 1.0, to: 0.0, afterFinish: function(){
							if(this.isPlaying()){
								//this.active.removeClassName('active previous') 
								(this.active.hasClassName('active previous')) ? this.active.removeClassName('active previous') : null;
								this.loopSlideshow();
							} else {
								this.stop();	
							}
						}.bind(this)});
					}
				}.bind(this)});
		} else {
			this.stop();
		}
	}
	
})

// base-class, extended
var anExtendedClass = Class.create(Slideshow, {
	initialize:function(){
	},

	somefunction : function(){
		//console.log("Executing somefunction in an instance of anExtendedClass");
	},

	anotherfunction : function($super){
		$super();
		//console.log("Executing anotherfunction in an instance of anExtendedClass");
	}
})

/* Now, create an instance of Slideshow, and call the function somefunction */

//var oSlideshow = new Slideshow();
//oSlideshow.somefunction();
