/**
* shSmoothSlideshow Joomla module : javascript class
* Copyright (C) 2006 Yannick Gaultier (shumisha). All rights reserved.
* Released under the http://www.gnu.org/copyleft/gpl.html GNU/GPL, doc/license and credits.txt
* This is free software. This version may have been modified pursuant
* to the GNU General Public License, and as distributed it includes or
* is derivative of works licensed under the GNU General Public License or
* other free or open source software licenses.
* version: 0.9.2
* released: september 4, 2006
*/

function shSmoothSlideShow( pdivIDName, prandomDisplay, pslideShowDelay, plinkDestination, ptransitionTime, ptransitionType, pslideInfoDelay, pisCentered, pstretchingMode, pslideHeight, pslideWidth, pmySlideData, pOnCompleteSlideFunc) {
    // internal properties init
    this.currentIter = 0;
    this.lastIter = 0;
    this.maxIter = 0;
    this.slideShowElement = "";
    this.slideShowData = pmySlideData;
    this.slideShowInit = 1;
    this.slideShowDelay = pslideShowDelay;
    this.articleLink = "";
    
    // store slideshow parameters into properties
    this.divIDName = pdivIDName; // name for slideshow div container
    this.randomDisplay = prandomDisplay;
    this.linkDestination = plinkDestination; // links open in same page or new page
    this.transitionTime = ptransitionTime;  // duration of transition in ms, default to 2 s  
    this.transitionType = ptransitionType; // 'automatic' or 'controls'
    this.slideInfoDelay = pslideInfoDelay; // delay before Slideinfo panel appears. Count is started when image is displayed
    this.isCentered = pisCentered; // set to true if divIDName must be centered about container div. Used only when stretchingMode = stretchBest, as divSize in this case is fixed
    this.stretchingMode = pstretchingMode; // stretch mode, default = no stretch or stretchX, stretchY, stretchBest
    // slideshow size : used to reisze image
    this.slideHeight = pslideHeight;  // height in px of the displayed slideshow
    this.slideWidth = pslideWidth; // widht in px of the displayed slideshow
    this.onCompleteSlideFunc = pOnCompleteSlideFunc; // any javascript code. Will be executed when image is displayed. The same code will be displayed for all images. Can be used to resize an element, display or hide another one ...

    // div for slideinfozone and slidelement is object-specific
    this.slideInfoZoneName = 'slideInfoZone'+this.divIDName;
    this.slideElementName = 'slideElement'+this.divIDName;
    // randomize data array if requested
    if (this.randomDisplay == 'yes') 
      this.slideShowData.sort(randOrd);
    // initialize slideshow based on running mode selected by user : automatic or user-controlled
    if (this.transitionType == 'automatic')
      {this.initSlideShowAutomatic($(this.divIDName));} 
    else 
      {this.initSlideShowControls($(this.divIDName));}
}

function addLoadEvent(func) {  // add event to onLoad events chain
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
oldonload();
func();
}; } }

function randOrd(){
return (Math.round(Math.random())-0.5); }

shSmoothSlideShow.prototype.onCompleteSlide = function() {
  this.onCompleteSlideFunc();
};

shSmoothSlideShow.prototype.runSlide = function() { 
// slideshow is started when this method is called 
  if (this.transitionType == 'automatic')
      {this.doSlideShowAutomatic();} 
    else 
      {this.doSlideShowControls(1);}
};   
 
shSmoothSlideShow.prototype.initSlideShowAutomatic = function(element) {
// perform initialisation work, but does not start the slideshow
	this.slideShowElement = element;
	element.style.display="block";
	this.articleLink = document.createElement('a');
	this.articleLink.className = 'global';
	element.appendChild(this.articleLink);
	// shumisha 2006-08-19 set link target. If not link in parameters, then set #, so that image links to itself : clicking on it will have no effect
	if (this.slideShowData[0][1] == '') {
    this.articleLink.href = '#';
    this.articleLink.target='_self';
    this.articleLink.className='nolink';
  } else {
    this.articleLink.href = this.slideShowData[0][1];
	  this.articleLink.target=this.linkDestination;
	}
	// load all images in page. Would be great to use ajax to load them dynamically. Next time !
	this.maxIter = this.slideShowData.length;
	for(i=0;i<this.maxIter;i++)
	{
		var currentImg = document.createElement('img');
		currentImg.setAttribute('id',this.slideElementName+ parseInt(i));
		currentImg.style.position="absolute";
		currentImg.style.left="0px";
		currentImg.style.top="0px";
		currentImg.style.margin="0px";
		currentImg.style.border="0px";
		currentImg.src=this.slideShowData[i][0];
		
		this.articleLink.appendChild(currentImg);
		currentImg.currentOpacity = new fx.Opacity(currentImg, {duration: parseInt(this.transitionTime)});
		currentImg.currentOpacity.setOpacity(0); // all images are hidden at the beginning
	}
	
	// create slideInfoZone div
	var slideInfoZone = document.createElement('div');
	slideInfoZone.setAttribute('id',this.slideInfoZoneName);
	slideInfoZone.combo = new fx.Combo(slideInfoZone);
	slideInfoZone.combo.o.setOpacity(0);
	this.articleLink.appendChild(slideInfoZone);
		
};

// shumisha 2006-08-22 add stretching of image
function stretchImg( imgTag, mode, sWidth, sHeight) {
// input : a DOM reference to an image, stretching mode, required Height and Width in px
// output : the px height of the resulting image
// Based on the value of mode, this function will resize the image referenced by imgTag. Proportions are always kept, images are not distorted
// 'noStretch' : do nothing
// 'stretchX'  : image is stretched horizontally to sWidth px. Then height is adjusted to keep proportion. All images have sWidth width
// 'stretchY'  : image is stretched vertically to sHeight px. Then width is adjusted to keep proportions. All images have sHeight height
// 'stretchBest' : image is streched both horizontally and vertically, until it reaches sWidth or sHeight, whichever comes first. Proportions are kept. All images fit within a rectangle sWidth wide and sHeight tall 
  var xFactor, yFactor, imgWidth, imgHeight = 0;
  var imgRef = document.getElementById( imgTag);  
  if (imgRef) { // if image exists
    imgWidth = imgRef.offsetWidth;
    imgHeight = imgRef.offsetHeight;
    //alert(imgWidth+'//'+imgRef.offsetHeight);
    if (mode == 'noStretch') {return imgHeight;}
    if ((imgHeight * imgWidth) == 0) {return 0;}
    switch(mode) {
      case 'stretchX':
        xFactor = sWidth/imgWidth;
        imgWidth = sWidth;
        imgHeight = imgHeight * xFactor;
        break;
      case 'stretchY':
        yFactor = sHeight/imgHeight;
        imgHeight = sHeight;
        imgWidth = imgWidth * yFactor;
        break;
      case 'stretchBest':
        xFactor = sWidth/imgWidth;
        yFactor = sHeight/imgHeight;
        if (xFactor <= yFactor) {
          imgWidth = sWidth;
          imgHeight = imgHeight*xFactor;
        } else {
          imgHeight = sHeight;
          imgWidth = imgWidth * yFactor;
        }
        break;
      default:
    }
    imgRef.style.width =  Math.round(imgWidth)+'px';
    imgRef.style.height = Math.round(imgHeight)+'px';
    return Math.round(imgHeight);
  }    
  return 0;
}

function centerDiv( divIDName, elementName){
// center slide vertically within the div. Horizontal centering is done through CSS
    var noPx=document.childNodes ?'px':0; // in case of old browser (Opera5, netscape4)
    if ((elementName != '') && (document.getElementById(elementName).offsetHeight)) {
       var maincontentclientHeight=document.getElementById(divIDName).offsetHeight;
       if (document.getElementById(elementName)) {
           document.getElementById(elementName).style.top=(maincontentclientHeight-document.getElementById(elementName).offsetHeight)/2+noPx;
       }
   }
}

function setDivSize( stretchMode, maxHeight, maxWidth, isCentered, imgName, divName) {
// shumisha 2006-08-23 function to adjust container div height and width, so that it is will display properly
  var noPx=document.childNodes ?'px':0; // in case of old browser (Opera5, netscape4)
  if (stretchMode != 'stretchBest') {
    // if anything else than stretchBest, div size is adjusted to image size, meaning slideshow size will vary according to actual image size.
    document.getElementById( divName).style.width = document.getElementById( imgName).offsetWidth+noPx;
	  document.getElementById( divName).style.height = document.getElementById( imgName).offsetHeight+noPx;
	} else {
	  // if stretchBest : div size is fixed and set to slideshow size as per the parameters
    document.getElementById( divName).style.width = document.getElementById( imgName).offsetWidth<maxWidth ? document.getElementById( imgName).offsetWidth+noPx:maxWidth+noPx;
    if (isCentered)
      document.getElementById( divName).style.height = maxHeight+noPx;
    else
      document.getElementById( divName).style.height = document.getElementById( imgName).offsetheight<maxHeight ? document.getElementById( imgName).offsetHeight+noPx:maxHeight+noPx;
	}  
  if (isCentered == 'yes') centerDiv(divName, imgName);
}

shSmoothSlideShow.prototype.setInitDivSize = function() {
// special case for first image of show
  var noPx=document.childNodes ?'px':0; // in case of old browser (Opera5, netscape4)
  // we go through all images to resize them all of needed
  var shCurHeight = 0;
  for(i=0;i<this.maxIter;i++) {
    shCurHeight = stretchImg( this.slideElementName+i, this.stretchingMode, 
                  this.slideWidth, this.slideHeight);
  }
  // adjust div size before displaying image
  setDivSize(this.stretchingMode, this.slideHeight, this.slideWidth,this.isCentered, this.slideElementName+'0', this.divIDName);
  // display first image immediately, no fading in effetc
	$(this.slideElementName+'0').currentOpacity.setOpacity(1);
	// call end of init function, after displaying first image. Due to some bugs in FF and IE, we need to wait a little bit before doing this, so we set a timer for 50 ms
	if (this.onCompleteSlideFunc) {
	  shcw[this.divIDName][6] = new CCallWrapper(this, 50, 'onCompleteSlide');
    CCallWrapper.asyncExecute(shcw[this.divIDName][6]);
  }
};
 
shSmoothSlideShow.prototype.nextSlideShowAutomatic = function() {
// move to next image
	this.lastIter = this.currentIter;
	this.currentIter++;
	if (this.currentIter >= this.maxIter)
	{
		this.currentIter = 0;
		this.lastIter = this.maxIter - 1;
	}
	
  //shumisha 2006-08-19 change : moved setting of href link here, as we do not get to previous location of this code if there are no title or description set. Added provisions for empty links
  if (this.slideShowData[this.currentIter][1] == '') {
    this.articleLink.href = '#';
    this.articleLink.target='_self';
    this.articleLink.className='nolink';
  } else {
	  this.articleLink.href = this.slideShowData[this.currentIter][1];
	}
	// shumisha end of change
	this.doSlideShowAutomatic();
	this.slideShowInit = 0;
};

shSmoothSlideShow.prototype.shOnComplete = function( cIter, lIter, divName, stretchingMode, slideHeight, slideWidth, isCentered, elementName) {
// needed to perform onComplete operations, as we cannot set object methods to do so (context will be lost, similar to setTimeout)
  setDivSize(stretchingMode, slideHeight, slideWidth, isCentered, elementName + parseInt(cIter), divName);
};

shSmoothSlideShow.prototype.doSlideShowAutomatic = function() {
// main  slideshow function
	if (this.slideShowInit == 1)
	{ // if first display of first image, a few special operations
		this.currentIter = 0;
		this.slideShowInit = 0;
		// call setInitDivSize with a little delay, to allow browser to do its work
    shcw[this.divIDName][1] = new CCallWrapper(this, 500, 'setInitDivSize');
    CCallWrapper.asyncExecute(shcw[this.divIDName][1]);  
    // set timer for displaying slideinfo pannel
    shcw[this.divIDName][2] = new CCallWrapper( this, parseInt(this.slideInfoDelay),'showInfoSlideShowAutomatic');
    CCallWrapper.asyncExecute(shcw[this.divIDName][2]);
    // set timer for hiding slideinfo panel     
    shcw[this.divIDName][3] = new CCallWrapper( this, parseInt(this.slideShowDelay)-400,'hideInfoSlideShowAutomatic');
    CCallWrapper.asyncExecute(shcw[this.divIDName][3]);
    // set timer for switching to next image                 
		shcw[this.divIDName][4] = new CCallWrapper( this, parseInt(this.slideShowDelay), 'nextSlideShowAutomatic');
    CCallWrapper.asyncExecute(shcw[this.divIDName][4]);
	} 
  else { // if this is not the first display of first image
    // fade out last image and fade in current image
	  $(this.slideElementName + parseInt(this.lastIter)).currentOpacity.custom(1,0);
		$(this.slideElementName + parseInt(this.currentIter)).currentOpacity.custom(0, 1);
		// set div size around the newly displayed image
	  setDivSize(this.stretchingMode, this.slideHeight, this.slideWidth, this.isCentered, this.slideElementName + parseInt(this.currentIter), this.divIDName, this.mainDivName);
	  // set timer for displaying slideinfopanel
		shcw[this.divIDName][2] = new CCallWrapper( this, parseInt(this.slideInfoDelay), 'showInfoSlideShowAutomatic');
    CCallWrapper.asyncExecute(shcw[this.divIDName][2]);
    // set timer for hiding slideinfo panel
		shcw[this.divIDName][3] = new CCallWrapper( this, parseInt(this.slideShowDelay)-400, 'hideInfoSlideShowAutomatic');
    CCallWrapper.asyncExecute(shcw[this.divIDName][3]);
    // set timer for switching to next image
		shcw[this.divIDName][4] = new CCallWrapper( this, parseInt(this.slideShowDelay), 'nextSlideShowAutomatic');
    CCallWrapper.asyncExecute(shcw[this.divIDName][4]);
  } 
};	

shSmoothSlideShow.prototype.showInfoSlideShowAutomatic = function() {
	//shumisha 2006-08-19 change : if not title or description, do not create slideinfo zone
	with (this) {
  if ((slideShowData[currentIter][2] =='') &&
      (slideShowData[currentIter][3] =='')) return;
  // shumisha 2006-08-19 end of change    
	articleLink.removeChild($(slideInfoZoneName));
	var slideInfoZone = document.createElement('div');
	slideInfoZone.setAttribute('id',slideInfoZoneName);
	slideInfoZone.combo = new fx.Combo(slideInfoZone);
	slideInfoZone.combo.o.setOpacity(0);
	var slideInfoZoneTitle = document.createElement('h2');
	slideInfoZoneTitle.innerHTML = slideShowData[currentIter][2];
	slideInfoZone.appendChild(slideInfoZoneTitle);
	var slideInfoZoneDescription = document.createElement('p');
	slideInfoZoneDescription.innerHTML = slideShowData[currentIter][3];
	slideInfoZone.appendChild(slideInfoZoneDescription);
	articleLink.appendChild(slideInfoZone);
	
	//shumisha 2006-08-19 change : moved setting of href link from here, as we do not get here if there are no title or description set
	//articleLink.href = slideShowData[currentIter][1];
	// shumisha end of change
	slideInfoZone.combo.o.custom(0, 0.7);
	slideInfoZone.combo.h.custom(0, slideInfoZone.combo.h.el.offsetHeight);
	}
};

shSmoothSlideShow.prototype.hideInfoSlideShowAutomatic = function() {
  //shumisha 2006-08-19 change : if not title or description, do not create slideinfo zone, hence no need to hide it
  with (this) {
  if ((slideShowData[currentIter][2] =='') &&
      (slideShowData[currentIter][3] =='')) return;
  // shumisha 2006-08-19 end of change    
	$(slideInfoZoneName).combo.o.custom(0.7, 0);
	//$(slideInfoZoneName).combo.h.custom(slideInfoZone.combo.h.el.offsetHeight, 0);
	}
};


// ---------------  controls version ------------------------------------------

shSmoothSlideShow.prototype.initSlideShowControls = function(element) {
  with (this) {
	slideShowElement = element;
	element.style.display="block";
	maxIter = slideShowData.length;
	
	this.articleLink = document.createElement('a');
	this.articleLink.className = 'global';
	element.appendChild(this.articleLink);
	// shumisha 2006-08-19 set link target. If not link in parameters, then set #, so that image links to itself : clicking on it will have no effect
	if (this.slideShowData[0][1] == '') {
    this.articleLink.href = '#';
    this.articleLink.target='_self';
    this.articleLink.className='nolink';
  } else {
    this.articleLink.href = this.slideShowData[0][1];
	  this.articleLink.target=this.linkDestination;
	}
//	alert (this.slideShowData[0][1]);
	
	for(i=0;i<maxIter;i++)
	{
		var currentImg = document.createElement('img');
		currentImg.setAttribute('id', slideElementName + parseInt(i));
		currentImg.style.position="absolute";
		currentImg.style.left="0px";
		currentImg.style.bottom="0px";
		currentImg.style.margin="0px";
		currentImg.src=slideShowData[i][0];
		this.articleLink.appendChild(currentImg);
//		element.appendChild(currentImg);
		currentImg.currentOpacity = new fx.Opacity(currentImg, {duration: parseInt(transitionTime)});
		currentImg.currentOpacity.setOpacity(0);
	}

	// must stretch images)
  var shCurHeight = 0;
  for(i=0;i<this.maxIter;i++) {
    shCurHeight = stretchImg( this.slideElementName+i, this.stretchingMode, 
                  this.slideWidth, this.slideHeight);
  }
	if ( maxIter > 1)
	{
		var leftArrow = document.createElement('a');
		leftArrow.className = 'left';
		leftArrow.onclick = function () { pushPrevSlideShowControls(); };
		element.appendChild(leftArrow);
		
		var rightArrow = document.createElement('a');
		rightArrow.className = 'right';
		rightArrow.onclick = function () { pushNextSlideShowControls(); };
		element.appendChild(rightArrow);
	}
  element.appendChild(this.articleLink);
	
	var slideInfoZone = document.createElement('div');
	slideInfoZone.setAttribute('id',slideInfoZoneName);
	slideInfoZone.combo = new fx.Combo(slideInfoZone);
	slideInfoZone.combo.o.setOpacity(0);
	element.appendChild(slideInfoZone);
//	this.articleLink.appendChild(slideInfoZone);
	slideShowInit = 1;
	}
};

shSmoothSlideShow.prototype.destroySlideShowControls = function(element) {
	var myClassName = element.className;
	var newElement = document.createElement('div');
	newElement.className = myClassName;
	element.parentNode.replaceChild(newElement, element);
};

shSmoothSlideShow.prototype.pushNextSlideShowControls = function () {
	shcw[this.divIDName][3] = new CCallWrapper( this, 10, 'hideInfoSlideShowControls');
  CCallWrapper.asyncExecute(shcw[this.divIDName][3]);
	shcw[this.divIDName][4] = new CCallWrapper( this, 500,'nextSlideShowControls');
  CCallWrapper.asyncExecute(shcw[this.divIDName][4]);
};

shSmoothSlideShow.prototype.pushPrevSlideShowControls = function () {
  shcw[this.divIDName][3] = new CCallWrapper( this, 10, 'hideInfoSlideShowControls');
  CCallWrapper.asyncExecute(shcw[this.divIDName][3]);	
	shcw[this.divIDName][5] = new CCallWrapper( this, 500, 'prevSlideShowControls');
  CCallWrapper.asyncExecute(shcw[this.divIDName][5]);
};

shSmoothSlideShow.prototype.nextSlideShowControls = function() {
  with (this) {
	lastIter = currentIter;
	currentIter++;
	if (currentIter >= maxIter)
	{
		currentIter = 0;
		lastIter = maxIter - 1;
	}
	slideShowInit = 0;
	doSlideShowControls(1);
	}
};

shSmoothSlideShow.prototype.prevSlideShowControls = function() {
  with (this) {
	lastIter = currentIter;
	currentIter--;
	if (currentIter <= -1)
	{
		currentIter = maxIter - 1;
		lastIter = 0;
	}
	slideShowInit = 0;	
	doSlideShowControls(2);
  }
};

shSmoothSlideShow.prototype.doSlideShowControls = function(position) {
  with (this) {	
	if (slideShowInit == 1)
	{
		currentIter = 0;
		slideShowInit = 0;
		shcw[this.divIDName][1] = new CCallWrapper(this, 500, 'setInitDivSize');
    CCallWrapper.asyncExecute(shcw[this.divIDName][1]);
    shcw[this.divIDName][2] = new CCallWrapper( this, parseInt(this.slideInfoDelay),'showInfoSlideShowControls');
    CCallWrapper.asyncExecute(shcw[this.divIDName][2]);
	} else {
		if (position == 1)
		{
			if (currentIter != 0) {
				$(slideElementName + parseInt(currentIter)).currentOpacity.options.onComplete = function() {
					$(slideElementName + parseInt(lastIter)).currentOpacity.setOpacity(0);
	        setDivSize(stretchingMode, slideHeight, slideWidth,isCentered, slideElementName + parseInt(currentIter), divIDName);
				};
				$(slideElementName + parseInt(currentIter)).currentOpacity.custom(0, 1);
			} else {
				$(slideElementName + parseInt(currentIter)).currentOpacity.setOpacity(1);
				$(slideElementName + parseInt(lastIter)).currentOpacity.custom(1, 0);
	      setDivSize(stretchingMode, slideHeight, slideWidth,isCentered,slideElementName + parseInt(currentIter), divIDName);
			}
		} else {
			if (currentIter != maxIter - 1) {
				$(slideElementName + parseInt(currentIter)).currentOpacity.setOpacity(1);
				$(slideElementName + parseInt(lastIter)).currentOpacity.custom(1, 0);
	      setDivSize(stretchingMode, slideHeight, slideWidth,isCentered,slideElementName + parseInt(currentIter), divIDName);
			} else {
				$(slideElementName + parseInt(currentIter)).currentOpacity.options.onComplete = function() {
					$(slideElementName + parseInt(lastIter)).currentOpacity.setOpacity(0);
	        setDivSize(stretchingMode, slideHeight, slideWidth,isCentered, slideElementName + parseInt(currentIter), divIDName);
				};
				$(slideElementName + parseInt(currentIter)).currentOpacity.custom(0, 1);	
			}
		}
		shcw[this.divIDName][2] = new CCallWrapper( this, parseInt(this.slideInfoDelay), 'showInfoSlideShowControls');
    CCallWrapper.asyncExecute(shcw[this.divIDName][2]);
	}
  }	
};

shSmoothSlideShow.prototype.showInfoSlideShowControls = function() {
  with (this) {
  //shumisha 2006-08-19 change : if not title or description, do not create slideinfo zone
  if ((slideShowData[currentIter][2] =='') &&
      (slideShowData[currentIter][3] =='')) return;
  // shumisha 2006-08-19 end of change    
	slideShowElement.removeChild($(slideInfoZoneName));
	var slideInfoZone = document.createElement('div');
	slideInfoZone.setAttribute('id',slideInfoZoneName);
	slideInfoZone.combo = new fx.Combo(slideInfoZone);
	slideInfoZone.combo.o.setOpacity(0);
	var slideInfoZoneTitle = document.createElement('h2');
	slideInfoZoneTitle.innerHTML = slideShowData[currentIter][2];
	slideInfoZone.appendChild(slideInfoZoneTitle);
	var slideInfoZoneDescription = document.createElement('p');
	slideInfoZoneDescription.innerHTML = slideShowData[currentIter][3];
	slideInfoZone.appendChild(slideInfoZoneDescription);
	slideShowElement.appendChild(slideInfoZone);
	slideInfoZone.combo.o.custom(0, 0.7);
	slideInfoZone.combo.h.custom(0, slideInfoZone.combo.h.el.offsetHeight);
	}
};

shSmoothSlideShow.prototype.hideInfoSlideShowControls = function() {
  with (this) {
  //shumisha 2006-08-19 change : if not title or description, do not hide slideinfo zone
  if ((slideShowData[currentIter][2] =='') &&
      (slideShowData[currentIter][3] =='')) return;
  // shumisha 2006-08-19 end of change    
	$(slideInfoZoneName).combo.o.custom(0.7, 0);
	//$(slideInfoZoneName).combo.h.custom(slideInfoZone.combo.h.el.offsetHeight, 0);
	}
};

// JavaScript Document
/*
 * CCallWrapper.js
 * $Revision: 1.3 $ $Date: 2003/07/07 18:32:43 $
 */

/* ***** 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.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 = {};
