/*
 Except for the function <getElementsByClassName>,
 this work is licensed under the Creative Commons Attribution 3.0 License.
 To view a copy of this license, visit 
 http://creativecommons.org/licenses/by/3.0/
 
 Copyright Riccardo Attilio Galli http://www.sideralis.org
*/

/**
 * Return all the elements whose class is className
 * @className css class name
 * @tag search only in elements whose tag is tag (or all if not present)
 * @elm search only in descendants of elm (or in all document elements if not present)
 */
function getElementsByClassName(className, tag, elm){
    /*
        Written by Jonathan Snook, http://www.snook.ca/jonathan
        Add-ons by Robert Nyman, http://www.robertnyman.com
    */
	var testClass = new RegExp("(^|\\\\s)" + className + "(\\\\s|$)");
	var tag = tag || "*";
	var elm = elm || document;
	var elements = (tag == "*" && elm.all)? elm.all : elm.getElementsByTagName(tag);
	var returnElements = [];
	var current;
	var length = elements.length;
	for(var i=0; i<length; i++){
		current = elements[i];
		if(testClass.test(current.className)){
			returnElements.push(current);
		}
	}
	return returnElements;
}


/**
 * Crossbrowser method to change opacity of an element
 * @domElem element who's going to have opacity changed
 * @alphaValue value beetween [0,1] (1 means fully opaque, 0 fully transparent)
 */
function setOpacity(domElem,alphaValue){
    var style=domElem.style;
    style.MozOpacity = alphaValue;  /* Mozilla extension */
    style.KhtmlOpacity = alphaValue; /* Konqueror extension (Safari 1.1)*/
    style.filter = "alpha(opacity=" + alphaValue*100 + ")"; /* IE filter extension */
    style.opacity = alphaValue; /* the correct CSS3 syntax */
}

/**
 * Change the opacity of an object during a given time.
 *
 * @id_or_elem element id or element object
 * @opacStart initial alpha value (0.0 fully transparent, 1.0 fully opaque)
 * @opacEnd final alpha value (0.0 fully transparent, 1.0 fully opaque)
 * @millisec duration of the fade effect, in milliseconds
 */
function fade(id_or_elem, opacStart, opacEnd, millisec) {
    
    //avoid re-creating each time the functions
    if (!fade._changeOpacity) {
        //closure to suit setTimeout
        fade._doIt=function(obj,alphaStart,alphaEnd,step,interval){return function(){
            alphaStart+=step;
            
            setOpacity(obj,alphaStart);
            
            if (Math.abs(alphaStart-alphaEnd)-Math.abs(step)>0)
                setTimeout(fade._doIt(obj,alphaStart,alphaEnd,step,interval),interval);
            
            //else if (1)
            //    alert("elapsed: "+(((new Date()).getTime()-fade._start)/1000));
            
        }}; 
    }
    
    var obj=id_or_elem;
    if (!id_or_elem.appendChild) {
        obj=document.getElementById(id_or_elem);
    }
    
    //fade._start=new Date().getTime();
    
    var interval=Math.abs(0.01*millisec/(opacStart-opacEnd));
    var step= opacStart>opacEnd ? -0.01 : 0.01;
    setTimeout(fade._doIt(obj,opacStart,opacEnd,step,interval),interval);
}



/**
 * Creates a Slideshow object
 * @container object which is going to hold the slideshow, or his id
 * @numSlides number of slides composing the slideshow
 * @imgUrlPattern string containing the image path using a pattern where
 *   where %d will be replaced by a number beetween 1 and @numSlides
 *
 * example:
 *  Supposing you have a directory "images" with files as slide_1.png
 *   slide_2.png ... to slide_10.png , you can use Slideshow like this
 *   
 *   var showMe=new Slideshow('containerId',10,'images/slide_%d.png');
 *   showMe.start();
 */
function Slideshow(container,numSlides,imgUrlPattern){
    this._container=container;
    if (!container.appendChild)
        this._container=document.getElementById(container);
    
    this._numSlides=numSlides;
    this._imgUrlPattern=imgUrlPattern;
    
    this._fadeIn_time=this._fadeOut_time=1000;
    this._visible_time=this._hidden_time=2000;
    
    this._currentSlide=0;
    
    this._availableSlides={
        'current':null,
        'next':null
    };
    
    /**
     * Sets the time needed to "fade in" and "fade out"
     * @fadeIn duration of fading in, in milliseconds 
     * @fadeOut duration of fading out, in milliseconds 
     */
    this.setFadingTime=function(fadeIn,fadeOut) {
        this._fadeIn_time=fadeIn;
        this._fadeOut_time=fadeOut;
    }
    
    /**
     * Sets the aumount of time during which the slide is visible
     * @msec milliseconds during which the slide is visible
     */
    this.setVisibleTime=function(msec){
        this._visible_time=msec;
    }
    
    /**
     * Sets the aumount of time passing beetween two slides
     * @msec milliseconds to wait before showing the next slide
     */
    this.setTransitionTime=function(msec){
        this._hidden=msec;
    }
    
    /**
     * Cache the next image to show
     */
    this._preloadImages=function() {
        this._availableSlides['next']=new Image();
        this._availableSlides['next'].src=this._imgUrlPattern.replace('%d',
            ''+(this._currentSlide+1));
    }
    
    /**
     * Return the next slide (image) to show
     */
    this._getNextSlide=function() {
        var nextSlide=this._availableSlides['next'];
        
        this._currentSlide+=1;
        if (this._currentSlide==this._numSlides-1)
            this._currentSlide=0;
        
        this._availableSlides['current']=nextSlide;
        
        setTimeout((function(obj) {return function(){
            obj._preloadImages();
            };})(this),this._visible_time/2);
        
        return nextSlide;
    }
    
    /**
     * Starts the slideshow
     */
    this.start=function(){
        this._preloadImages();
        /*
        var iniziale=100;
        var cappa=1;
        */
        
        var showNext=function(obj) {return function(){
            /*   
            var lol=document.getElementById('slideContainer'); 
            lol.style.top=iniziale*cappa*2+"px";
            cappa+=1;
            if (cappa==4) cappa=1;
            */
            
            var slide=obj._getNextSlide();
            setOpacity(slide,0);
            
            while (obj._container.firstChild) {
                obj._container.removeChild(obj._container.firstChild);
            }
            obj._container.appendChild(slide);
            
            fade(slide,0,1,obj._fadeIn_time);
            var fade_closure=function(a,b,c,d){return function(){
                fade(a,b,c,d);
            }};
            setTimeout(fade_closure(slide,1,0,obj._fadeOut_time),
                        obj._fadeIn_time+obj._visible_time);
            
        }}
        
        showNext(this)();
        setInterval(showNext(this),this._fadeIn_time+this._fadeOut_time+
                    this._visible_time+this._hidden_time);
    }
}


