/**
 * DoSlideshow
 *
 * @requires prototype
 * @requires scriptaculous
 * @author Jost Neumann <neumann@die-ordnung.de>
 */
DoSlideshow = Class.create();
Object.extend(DoSlideshow.prototype, {
	/**
	 * Object of states
	 */
	state : { 'pause' : false },
	
	/**
	 * frame identifiers (start, end, current)
	 */
	frame : {},

	/**
	 * Initializes this class
	 *
	 * @param array options options
	 */
	initialize: function(options){
		// target container
		this.target = $(options.target);
		this.id = this.target.getAttribute('id');
		
		// delay btw slide
		this.delay = options.delay || 8;
		this.duration = options.duration || .25;
		this.mode = options.mode || 0;
		
		
		// all images
		this.frames = this.target.getElementsBySelector('.do_slideshow-image');
		
		// hide all images except the last one and get the max height and width
		var h = 0, w = 0;
		this.frames.each(function(frame, i){
			if( i>0 ){
				frame.hide();
				frame.style.visibility = 'visible';
			}
			h = frame.getHeight() > h ? frame.getHeight() : h;
			w = frame.getWidth() > w ? frame.getWidth() : w;
		});
		// set height and width of target container
		var imagesObj = this.target.down('.do_slideshow-images'); 
		imagesObj.style.height = h + 'px';
		imagesObj.style.width = w + 'px';
		// give all frames the full height
		this.frames.each(function(frame, i){
		    frame.style.height = h + 'px';
		    frame.style.width = w + 'px';
		});		

		// add click observer to controls
		var _this = this;
		this.target.getElementsBySelector('.do_slideshow-controls ul li a').each(function(aObj, i){
			Event.observe(aObj, 'click', _this.onShowFrame.bindAsEventListener(_this, i));
		});
		
		// add over and out event to set/unset pause state
		Event.observe(this.target, 'mouseover', function(evt){
			_this.state.pause = true;
		});
		Event.observe(this.target, 'mouseout', function(evt){
			_this.state.pause = false;
		});
		
		// initialize frame counters
		this.frame.current = 0;
		this.frame.start = 0;
		this.frame.end = this.frames.length-1;
		this.nextZIndex = 1;
		
		// start the show
		this.showFrame(0);
		if( this.mode == '1'){ // automatic mode
			new PeriodicalExecuter(this.onPeriodicalShowFrame.bind(this), this.delay);
		}
	},

	/**
	 * Callback to click event on controls. Calls a desired frame manually.
	 */
	onShowFrame: function(evt, frame){
		Event.stop(evt);
		this.showFrame(frame);
	},
	
	/**
	 * 
	 * 
	 */
	onPeriodicalShowFrame: function(){
		if( !this.state.pause ){
			this.showFrame();
		}
	},
	
	/**
	 * Gets the next frame
	 */
	nextFrame: function(){
		frame = this.frame.current;
		if( frame == this.frame.end ){ 
			frame = this.frame.start; 
		} else { 
			frame++; 
		}
		return frame;
	},
    
    /**
     * Shows the next frame and hides the current one
     */
    showFrame: function(frame){
    	// get the current/next frame
		if( typeof(frame) != 'number' ){
			frame = this.nextFrame();
		}
		
		// get the desried frame object
		frameObj = this.frames[frame];
		
		// set the legend
		var title = frameObj.down('img').getAttribute('title');
		this.target.down('.do_slideshow-legend').innerHTML = title;
		
		// highlight controls
		this.target.getElementsBySelector('.do_slideshow-control').each(function(liObj, i){
			i == frame ? liObj.addClassName('do_slideshow-control-on') : liObj.removeClassName('do_slideshow-control-on');
		});
		
		// return if not a new frame
		if( frame == this.frame.current ){
			return false;
		}

		// set desired frame on top of the others and hide it
		frameObj.hide();
		frameObj.style.zIndex = ++this.nextZIndex	;
		
		// clear effect queue
		var queue = Effect.Queues.get(this.id);
		queue.each(function(effect) { effect.cancel(); });

		// fade in
		var options = {
			'duration' : this.duration,
			'queue' : { position:'end', scope:this.id, limit:1 }
		};
		Effect.Appear(frameObj, options);
		
		this.frame.current = frame;
    }
});
