// Constructor function
function Slideshow()
{
  this.imageList = new Array();
  this.imageCache = new Array();
  this.container = null;
  this.crossFadeTime = 1000;
  this.crossFadeSteps = 20;
  this.slideDisplayTime = 2000;
}
Slideshow.opacityNone    = 0;
Slideshow.opacityCSS3    = 1;
Slideshow.opacityIE      = 2;
Slideshow.opacityMozilla = 3;

// Set the container object that the images will be displayed in
Slideshow.prototype.setContainer = function(pContainer)
{
  pContainer.style.position = "relative";
  pContainer.style.top  = "0px";
  pContainer.style.left = "0px";
  this.container = pContainer;
}

// Add an image to the slideshow
Slideshow.prototype.addImage = function(pImage)
{
  // Set up the image so that it will behave properly in the slideshow
  this.setOpacity(pImage, 0);
  
  // Start the image loading, hopefully it will be here by the time we need it
  var cacheImage = new Image();
  cacheImage.src = pImage.src;
  this.imageCache[this.imageCache.length] = cacheImage;
  
  //pImage.style.position = "absolute";
  
  //var leftPosition = Math.round((this.container.offsetWidth - pImage.width) / 2);
  //pImage.style.left = leftPosition >= 0 ? (leftPosition + "px") : "0px";
  
  //var topPosition = Math.round((this.container.offsetHeight - pImage.height) / 2);
  //pImage.style.top = topPosition >= 0 ? (topPosition + "px") : "0px";
  
  this.imageList[this.imageList.length] = pImage;
}

// Add all the images in the container to the slideshow
Slideshow.prototype.addAllImages = function()
{
  if (this.container != null)
  {
    var images = this.container.getElementsByTagName("IMG");
    for (var i = 0; i != images.length; i++)
    {
      if (images[i].tagName == "IMG")
      {
        this.addImage(images[i]);
      }
    }
  }
}

// Start the slideshow
Slideshow.prototype.start = function()
{
  if (this.imageList.length > 1)
  {
    this.crossFadeTimerWrapper = new CCallWrapper(this, this.crossFadeTime / this.crossFadeSteps, "handleCrossFadeTimer");
    this.slideTimerWrapper = new CCallWrapper(this, this.slideDisplayTime, "handleSlideTimer");
    this.currentImageIndex = 0;
    this.nextImageIndex = 1;
    this.currentCrossFadeStep = 0;
    this.imageList[this.currentImageIndex].style.display = "";
    this.setOpacity(this.imageList[this.currentImageIndex], 1);
    CCallWrapper.asyncExecute(this.slideTimerWrapper);
  }
}

// Stop the slideshow
Slideshow.prototype.stop = function()
{
  if (this.crossFadeTimerWrapper != null) this.crossFadeTimerWrapper.cancel();
  if (this.slideTimerWrapper     != null) this.slideTimerWrapper.cancel();
}

// Set the opacity of an image object
Slideshow.prototype.setOpacity = function(pImage, pOpacity)
{
  if (this.opacityType == null)
  {
    this.determineOpacityType(pImage);
  }
  
  if (this.opacityType == Slideshow.opacityNone)
  {
    // No opacity, but we can still turn the image on and off
    if (pOpacity == 0)
    {
      pImage.style.display = "none";
    }
    else
    if (pOpacity == 1)
    {
      pImage.style.display = "";
    }
  }
  else
  if (this.opacityType == Slideshow.opacityCSS3)
  {
    // Set the style for CSS3 browsers
    pImage.style.opacity = pOpacity;
  }
  else
  if (this.opacityType == Slideshow.opacityIE)
  {
    // Set the style for IE based browsers
    pImage.style.filter = "progid:DXImageTransform.Microsoft.Alpha(opacity=" + (pOpacity * 100) + ")";
  }
  else
  if (this.opacityType == Slideshow.opacityMozilla)
  {
    // Set the style for browsers with the Mozilla opacity extension
    pImage.style["-moz-opacity"] = pOpacity;
  }
}

Slideshow.prototype.determineOpacityType = function(pImage)
{
  if (pImage.style.opacity != null)
  {
    this.opacityType = Slideshow.opacityCSS3;
  }
  else
  if (pImage.style.filter != null)
  {
    this.opacityType = Slideshow.opacityIE;
  }
  else
  if (pImage.style["-moz-opacity"] != null)
  {
    this.opacityType = Slideshow.opacityMozilla;
  }
  else
  {
    this.opacityType = Slideshow.opacityNone;
  }
}

Slideshow.prototype.bumpImageIndex = function(pIndex)
{
  pIndex++;
  return (pIndex == this.imageList.length ? 0 : pIndex);
}

// Handle the crossfade timer
Slideshow.prototype.handleCrossFadeTimer = function()
{
  this.currentCrossFadeStep++;
  var nextImageOpacity = this.currentCrossFadeStep / this.crossFadeSteps;
  
  this.setOpacity(this.imageList[this.currentImageIndex], 1 - nextImageOpacity);
  if (this.opacityType != Slideshow.opacityNone) this.imageList[this.nextImageIndex].style.display = "";
  this.setOpacity(this.imageList[this.nextImageIndex], nextImageOpacity);
  
  if (this.currentCrossFadeStep == this.crossFadeSteps)
  {
    this.currentImageIndex = this.bumpImageIndex(this.currentImageIndex);
    this.nextImageIndex = this.bumpImageIndex(this.nextImageIndex);
    this.currentCrossFadeStep = 0;
    CCallWrapper.asyncExecute(this.slideTimerWrapper);
  }
  else
  {
    CCallWrapper.asyncExecute(this.crossFadeTimerWrapper);
  }
}

// Handle the slide timer
Slideshow.prototype.handleSlideTimer = function()
{
  CCallWrapper.asyncExecute(this.crossFadeTimerWrapper);
}

/*
 * CCallWrapper.js
 * $Revision: 1.1 $ $Date: 2007/02/07 06:32:28 $
 */

/* ***** BEGIN LICENSE BLOCK *****
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Netscape code.
 *
 * The Initial Developer of the Original Code is
 * Netscape Corporation.
 * Portions created by the Initial Developer are Copyright (C) 2003
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s): Bob Clary <bclary@netscape.com>
 *
 * ***** END LICENSE BLOCK ***** */

function CCallWrapper(aObjectReference, 
                      aDelay,
                      aMethodName, 
                      aArgument0,
                      aArgument1,
                      aArgument2,
                      aArgument3,
                      aArgument4,
                      aArgument5,
                      aArgument6,
                      aArgument7,
                      aArgument8,
                      aArgument9
                      )
{
  this.mId = 'CCallWrapper_' + (CCallWrapper.mCounter++);
  this.mObjectReference = aObjectReference;
  this.mDelay     = aDelay;
  this.mTimerId = 0;
  this.mMethodName = aMethodName;
  this.mArgument0 = aArgument0;
  this.mArgument1 = aArgument1;
  this.mArgument2 = aArgument2;
  this.mArgument3 = aArgument3;
  this.mArgument4 = aArgument4;
  this.mArgument5 = aArgument5;
  this.mArgument6 = aArgument6;
  this.mArgument7 = aArgument7;
  this.mArgument8 = aArgument8;
  this.mArgument9 = aArgument9;
  CCallWrapper.mPendingCalls[this.mId] = this;
}

CCallWrapper.prototype.execute = function()
{
  this.mObjectReference[this.mMethodName](this.mArgument0,
                                          this.mArgument1,
                                          this.mArgument2,
                                          this.mArgument3,
                                          this.mArgument4,
                                          this.mArgument5,
                                          this.mArgument6,
                                          this.mArgument7,
                                          this.mArgument8,
                                          this.mArgument9
                                          );
  //delete CCallWrapper.mPendingCalls[this.mId];
};

CCallWrapper.prototype.reset = function()
{
  CCallWrapper.mPendingCalls[this.mId] = this;
}

CCallWrapper.prototype.cancel = function()
{
  clearTimeout(this.mTimerId);
  delete CCallWrapper.mPendingCalls[this.mId];
};

CCallWrapper.asyncExecute = function (/* CCallWrapper */ callwrapper)
{
  CCallWrapper.mPendingCalls[callwrapper.mId].mTimerId = setTimeout('CCallWrapper.mPendingCalls["' + callwrapper.mId + '"].execute()', callwrapper.mDelay);
};

CCallWrapper.mCounter = 0;
CCallWrapper.mPendingCalls = {};
