//*********************************************************************
//  Slideshow
//  Author: Geoff Elliott
//  Updated: June, 2007
//*********************************************************************

//  Globals ***********************************************************

var usesDOM=(document.getElementById); // supports W3C DOM


//  Slideshow Object **************************************************

function Slideshow (slideshowId, delay, mouseoverPause) {
  this.slideshowId = slideshowId; // corresponds to ID of <div> containing all slides
  this.delay = delay; // how long to wait between fades
  this.mouseoverPause = mouseoverPause; // should the slideshow pause onmouseover, true/false
  this.paused = false;
  this.opacityPercent = 10; // initial opacity
  this.currImageIndex = 0;
  this.nextImageIndex = 1;
  this.rotateTimer = null;
  this.fadeInterval = null;
  this.imageSet = new Array();

  this.imageSet = $('#' + this.slideshowId + ' > .slide').get();
  //console.log("# of slides: " + this.imageSet.length);

  this.startUp();
}


//  startUp :: impacts DOM elements related to Slideshow, initiates timer

Slideshow.prototype.startUp = function() {
  this.imageSet[0].style.zIndex++; // So that the first slide will keep up with the other slides; otherwise it's hidden
  $("#" + this.slideshowId + " > .pause").css("z-index", 5).css("display", "block"); // Here because setting it in CSS doesn't populate the .style object
  $("#" + this.slideshowId + " > .controls").css("z-index", 5);

  this.updateCounter(this.currImageIndex);

  if(this.mouseoverPause) {
    $('#' + this.slideshowId).mouseover(function() {
      this.paused = true;
    }).mouseout(function() {
      this.paused = false;
    });
  }
  var thisShow = this; // Necessary to get the correct scope in setTimeout
  this.rotateTimer = setTimeout(function(){thisShow.rotate()}, thisShow.delay);
}


//  setupForFade :: prepare to transition slides by:
//                    resetting opacityPercent,
//                    positioning the nextSlide,
//                    and setting nextSlide's starting opacity

Slideshow.prototype.setupForFade = function() {
  this.opacityPercent = 10;
  var currSlide = $('#' + this.slideshowId + "_slide" + this.currImageIndex);
  var nextSlide = $('#' + this.slideshowId + "_slide" + this.nextImageIndex);
  // parseInt because we get back a string, and adding 1 or 2 just appends the character on the end
  // after a while the "numbers" get very large, suddenly go negative, and bad things happen
  $("#" + this.slideshowId + " > .pause").css("z-index", parseInt(currSlide.css("z-index"), 10)+2);
  $("#" + this.slideshowId + " > .controls").css("z-index", parseInt(currSlide.css("z-index"), 10)+2);
  this.setOpacity(nextSlide[0]);
  nextSlide.css("display", "block").css("z-index", parseInt(currSlide.css("z-index"), 10)+1);
  this.updateCounter(this.nextImageIndex);
}


//  rotate :: function called from the slideshow timer; if not paused sets up fade and then starts fadeInterval

Slideshow.prototype.rotate = function() {
  var thisShow = this; // Necessary to get the correct scope in setInterval
  if(this.paused) {
    return;
  }
  else if(usesDOM) {
    this.setupForFade();
    this.fadeInterval = setInterval(function(){thisShow.fadeSlide()}, 50);
  }
}


//  setOpacity :: sets the opacity of a given element, selecting the appropriate browser technology

Slideshow.prototype.setOpacity = function(element) {
  if(element.style.MozOpacity)
    element.style.MozOpacity = this.opacityPercent/100;
  else if(element.style.KhtmlOpacity)
    element.style.KhtmlOpacity = this.opacityPercent/100;
  else if(element.filters && element.filters[0]){
    if(typeof element.filters[0].opacity == "number") { //if IE6+
      element.filters[0].opacity = this.opacityPercent;
    }
    else //else if IE5.5-
      element.style.filter = "alpha(opacity=" + this.opacityPercent + ")";
  }
  else if(element.style.opacity)
    element.style.opacity = this.opacityPercent/100;
}


//  fadeSlide :: fades in the next picture; when fade is finished, sets up the ImageIndexes, starts new timer

Slideshow.prototype.fadeSlide = function() {
  var thisShow = this; // Necessary to get the correct scope in setTimeout
  if(this.opacityPercent < 100) {
    this.opacityPercent += 10;
    var nextSlide = $('#' + this.slideshowId + "_slide" + this.nextImageIndex);
    this.setOpacity(nextSlide[0]);
  }
  else {
    clearInterval(this.fadeInterval);
    this.fadeInterval = null;
    this.currImageIndex = this.nextImageIndex;
    this.nextImageIndex = (this.nextImageIndex < this.imageSet.length-1) ? this.nextImageIndex+1 : 0;
    if(!this.paused) // If we're paused because of a prev/next click, don't start another timer
      this.rotateTimer = setTimeout(function(){thisShow.rotate()}, thisShow.delay);
  }
}


//  updateCounter :: sets the slideshow counter to the slide index passed in
//                    At the beginning we pass in the currImageIndex, during fades the nextImageIndex.  It works.

Slideshow.prototype.updateCounter = function(slideNumber) {
  var counter = $('#' + this.slideshowId + "Counter")[0];
  counter.removeChild(counter.firstChild);
  slideNumber+=1; // Adjust because we're passed an index
  counter.appendChild(document.createTextNode("Slide " + slideNumber + " of " + this.imageSet.length));
}


//  nextSlide :: triggered by user, pauses show, forces fade to next slide

Slideshow.prototype.nextSlide = function() {
  if(this.fadeInterval != null) return; // avoid errors when clicking too fast and interrupting a fade
  var thisShow = this; // Necessary to get the correct scope in setInterval
  this.pauseShow();
  this.setupForFade();
  this.fadeInterval = setInterval(function(){thisShow.fadeSlide()}, 50);
}


// prevSlide :: triggered by user, pauses show, forces fade to previous slide

Slideshow.prototype.prevSlide = function() {
  if(this.fadeInterval != null) return; // avoid errors when clicking too fast and interrupting a fade
  var thisShow = this; // Necessary to get the correct scope in setInterval
  this.pauseShow();
  this.nextImageIndex = (this.currImageIndex > 0) ? this.currImageIndex-1 : this.imageSet.length-1;
  this.setupForFade();
  this.fadeInterval = setInterval(function(){thisShow.fadeSlide()}, 50);
}


//  togglePause :: fired when user clicks on the play/pause icon; pauses or restarts the slideshow

Slideshow.prototype.togglePause = function() {
  var thisShow = this; // Necessary to get the correct scope
  // avoid errors when clicking too fast and interrupting a fade
  if(this.fadeInterval != null) {
    setTimeout(function(){thisShow.togglePause()}, 50);
    return;
  }
  if(this.paused) {
    //alert('off pause')
    this.paused = false;
    $("#" + this.slideshowId + " .pauseImg").attr("src", '/images/pause.png').attr("alt", "Pause Slideshow");
    $("#" + this.slideshowId + " .pauseBtnLink").attr("title", 'Pause Slideshow');
    // Fade to the next slide immediately when un-pausing
    this.setupForFade();
    this.fadeInterval = setInterval(function(){thisShow.fadeSlide()}, 50);
  }
  else {
    this.pauseShow();
  }
}


//  pauseShow :: handles pause "on", called from togglePause, nextSlide, prevSlide methods

Slideshow.prototype.pauseShow = function() {
  //alert('on pause')
  this.paused = true;
  $("#" + this.slideshowId + " .pauseImg").attr('src', '/images/play.png').attr("alt", "Resume Slideshow");
  $("#" + this.slideshowId + " .pauseBtnLink").attr('title', 'Resume Slideshow');
  clearTimeout(this.rotateTimer);
}