/***********************************************************
 *
 * This object represents a slide show.
 *
 * Create an object with "new JsdSlideShow( parameters )"
 * and use functions startSlideShow(), stopSlideShow(), and
 * toggleSlideShow() on created object to control the slide show.
 *
 * Additional functionality:
 *
 *   setSlideDisplayTime(number) - sets the time to display each slide (in seconds) -
 *        default is 5 seconds;
 *
 *   setSlideTransitionTime(number) - sets the duration of a transition between slides
 *        (in seconds) - default si 3 seconds;
 *
 *   setRandom(boolean) - true will switch to random mode (from sequential);
 *
 *   setLastSlidePause(number) - adds additional time (in seconds) to the last slide
 *        when in sequesntial mode (not random);
 *
 ***********************************************************/

/**
 * Prototype for a JsdSlideShow object.
 * 
 * Note, that a valid image resource must exist at each of the
 * following locations: "slidesPath + slidesPrefix + NUMBER + slidesExt",
 * where NUMBER is an interger such as: slidesMin <= NUMBER <= slidesMax.
 *
 * @param varName javascript name of this created JsdSlideShow object.
 * @param slidesDivBackId HTML id of the back div.
 * @param slidesDivFrontId HTML id of the front div.
 * @param slidesPath path to the slide image files.
 * @param slidesPrefix prefix for the image file name.
 * @param slidesExt extention name for the image files (including the dot).
 * @param slidesMin low bound file name index of the slides set.
 * @param slidesMax high bound file name index of the slides set.
 * @param slideStart file name index to start slide show with
 *        (slidesMin <= slideStart <= slidesMax).
 */
function JsdSlideShow(varName,
                      slidesDivBackId,
                      slidesDivFrontId,
                      slidesPath,
                      slidesPrefix,
                      slidesExt,
                      slidesMin,
                      slidesMax,
                      slideStart) {

  // CONFIGURABLE SETTINGS ////////////////////////////////////////////

  this.varName = varName;
  this.slidesDivBackId = slidesDivBackId;
  this.slidesDivFrontId = slidesDivFrontId;
  this.slidesPath = slidesPath;
  this.slidesPrefix = slidesPrefix;
  this.slidesExt = slidesExt;
  this.slidesMin = slidesMin;
  this.slidesMax = slidesMax;

  // functions to call /////////////////////////////////////////////////

  // starts the slide show if it's off
  this.startSlideShow = function(startDelay) {
    if (startDelay != null && startDelay > 0) {
      setTimeout(varName + ".__startSlideShow()", 1000 * startDelay);
    } else {
      this.__startSlideShow();
    }
  }

  // stops the slide show if it's playing
  this.stopSlideShow = function() {
    if (this.__timerId) {
      clearTimeout(this.__timerId);
      this.__timerId = null;
    }
  }

  // toggles (starts/stops) the slide show
  this.toggleSlideShow = function() {
    if (this.__timerId) {
      this.stopSlideShow();
    } else {
      this.startSlideShow();
    }
  }

  // Sets the time to display each slide (in seconds);
  this.setSlideDisplayTime = function(slideDisplayTime) {
    this.__slideDisplayTime = slideDisplayTime; 
  }
  
  // time for duration of a transition between slides;
  this.setSlideTransitionTime = function(slideTransTime) {
    this.__slideTransTime = slideTransTime;
  }

  // sets the random flag - when set to true,
  // makes the images displayed in a random order
  this.setRandom = function(isRandom) {
    this.__isRandom = isRandom;
  }

  // sets the lastSlidePause additional time - number of seconds,
  // to add to the last slide show time (last slide is the one with max index)
  this.setLastSlidePause = function(lastSlidePause) {
    this.__lastSlidePause = lastSlidePause;
  }

  // XXX Do not change anything below XXX /////////////////////////////////

  // starts the slide show if it's off
  this.__startSlideShow = function() {
    if (!this.__timerId) {
      var frontDiv = document.getElementById(this.slidesDivFrontId);
      if (frontDiv.style.display == 'none') {
        this.__frontDivVisible = false;
      }
      this.showNextSlide();
    }
  }

  this.showNextSlide = function() {

    // changing the images and applying effects in in the appropriate div
    var backDiv = document.getElementById(this.slidesDivBackId);
    var frontDiv = document.getElementById(this.slidesDivFrontId);
    var lastLonger = 0;

    var currSlideNumber;
    if (this.__isRandom) {
      currSlideNumber = this.__slides[this.__slidesCurrInd - this.slidesMin][0];
    } else {
      currSlideNumber = this.__slidesCurrInd;
    }

    if (this.__frontDivVisible) {
      backDiv.style.backgroundImage = 'url(' + this.__getFileName(currSlideNumber) + ')';
      this.__frontDivVisible = false;
      new Effect.Fade(this.slidesDivFrontId, {duration: this.__slideTransTime});

    } else {
      frontDiv.style.backgroundImage = 'url(' + this.__getFileName(currSlideNumber) + ')';
      this.__frontDivVisible = true;
      new Effect.Appear(this.slidesDivFrontId, {duration: this.__slideTransTime});
    }

    // determining the next slide
    this.__slidesCurrInd += 1;
    if ((this.__slidesCurrInd - this.slidesMin) == this.__slides.length) {
      this.__slidesCurrInd = this.slidesMin;
      // making the last slide to stay a bit longer when in sequential mode
      if (this.__isRandom == false && this.__lastSlidePause > 0) {
        lastLonger = 1000 * this.__lastSlidePause;
      }
    }

    // scheduling the next slide preload if it's not loaded already
    if (this.__isRandom) {
      currSlideNumber = this.__slides[this.__slidesCurrInd - this.slidesMin][0];
    } else {
      currSlideNumber = this.__slidesCurrInd;
    }
    if (this.__slides[currSlideNumber - this.slidesMin][1] == false) {
      setTimeout(varName + ".__preload('" + this.__slides[currSlideNumber - this.slidesMin][0] + "')", this.__slideDisplayTime * 200);
      this.__slides[currSlideNumber - this.slidesMin][1] = true;
    }

    // scheduling the next slide
    this.__timerId = setTimeout(varName + ".showNextSlide()", this.__slideDisplayTime * 1000 + lastLonger);
  }

  // "private" variable and funtions
  this.__slideDisplayTime = 5;
  this.__slideTransTime = 3;
  this.__isRandom = false;
  this.__lastSlidePause = 0;
  this.__slides = new Array();
  this.__slidesCurrInd = slideStart;
  this.__frontDivVisible = false;
  this.__timerId = null;
  this.__getFileName = function(num) {
    return this.slidesPath + this.slidesPrefix + num + this.slidesExt;
  }
  this.__preload = function(num) {
    var i = new Image();
    i.src = this.__getFileName(num);
  }

  this.__init = function() {
    // initializing the slides array with random numbers in a proper range
    // and setting each slides flag (second item on the included array) to false (not-preloaded)
    var tempArray = new Array();
    for (var i = this.slidesMin; i <= this.slidesMax; ++i) {
      tempArray[i - this.slidesMin] = i;
    }
    while (tempArray.length > 0) {
      var num = Math.floor(Math.random() * tempArray.length);
      this.__slides.push(new Array(tempArray[num], false));
      if (num == tempArray.length - 1) {
        tempArray.pop();
      } else {
        tempArray[num] = tempArray.pop();
      }
    }
    this.__preload(this.__slides[this.__slidesCurrInd - this.slidesMin][0]); // preloading the first image
    this.__slides[this.__slidesCurrInd - this.slidesMin][1] = true;
  }

  this.__init();

}
