/* -- Picture OBJECT ----------------------------*/

function Picture(url, caption, linkhref, linktarget, width, height)
{
  this.url = url;
  this.caption = caption;
  this.linkhref = linkhref;
  this.linktarget = linktarget;
  this.image = undefined;
  this.width = width;
  this.height = height;
}

Picture.prototype.isLoaded = function()
{
  if(this.image != undefined && this.image.src!='')
    return this.image.complete || this.image.completed;
  else
    return false;
}

Picture.prototype.preload = function()
{
  if(this.image == undefined || this.image.src=='')
  {
    this.image = new Image();
    this.image.completed = false;
    this.image.onload = new Function("this.completed = true;");
    this.image.src = this.url;
  }
  return this.image.complete || this.image.completed;
}

/* -- Slideshow OBJECT ----------------------------*/


function Slideshow(varname)
{
  this.varname = varname;
  this.pictures = Array();
  this.currentSlide = 0;
  this.timer = undefined;
  
  //objects
  this.imageObjectBack = undefined;
  this.imageObjectFront = undefined;
  this.containerObject = undefined;
  this.loadingindicatorObject = undefined;
  this.captionbox = undefined;
  this.centerX = false;
  this.centerY = false;
   
  //speeds
  this.pause = 3000; // ms
  this.fadespeed = 2000; // ms
  this.preloadpollspeed = 500; // ms  : how fast do we recheck the image to see if it was preloaded?
  
  // status variables
  this.crossFadeInProgress = false;
  this.crossFadingTimeouts = Array();
}

Slideshow.prototype.addPicture = function(picture)
{
  this.pictures.push(picture);
}

Slideshow.prototype.setPause = function(pause)
{
  this.pause = pause;
}

Slideshow.prototype.setFadeSpeed = function(fadespeed)
{
  this.fadespeed = fadespeed;
}

Slideshow.prototype.setPause = function(pause)
{
  this.pause = pause;
}

Slideshow.prototype.setPreloadPollSpeed = function(preloadpollspeed)
{
  this.preloadpollspeed = preloadpollspeed;
}

Slideshow.prototype.setBackgroundImage = function(object)
{
  this.imageObjectBack = object;
}

Slideshow.prototype.setImage = function(object)
{
  this.imageObjectFront = object;
}

Slideshow.prototype.setContainer = function(object)
{
  this.containerObject = object;
}

Slideshow.prototype.setLoadingIndicator = function(object)
{
  this.loadingindicatorObject = object;
}

Slideshow.prototype.setCaptionBox = function(object)
{
  this.captionbox = object;
}

Slideshow.prototype.setCenterX = function(value)
{
  if(value == undefined || value)
    this.centerX = true;
}

Slideshow.prototype.setCenterY = function(value)
{
  if(value == undefined || value)
    this.centerY = true;
}

Slideshow.prototype.isRunning = function()
{
  return (this.timer != undefined);
}

Slideshow.prototype.startAutoSlide = function()
{
  if(this.timer == undefined)
    this.nextAutoSlide();
}

Slideshow.prototype.nextAutoSlide = function()
{
  if(this.imageObjectBack != undefined && this.imageObjectFront != undefined && this.containerObject != undefined)
  {
    this.nextSlide(true, false);
  }
}

Slideshow.prototype.stopAutoSlide = function()
{
  this.clearTimer();
}

Slideshow.prototype.clearTimer = function()
{
  if(this.timer != undefined)
  {
    clearTimeout(this.timer);
    this.timer = undefined;
  }
}

Slideshow.prototype.nextSlide = function(fade, stop)
{
  this.gotoSlide(this.currentSlide +1, fade, stop, 'next');
}

Slideshow.prototype.previousSlide = function(fade, stop)
{
  this.gotoSlide(this.currentSlide -1, fade, stop, 'previous');
}



Slideshow.prototype.gotoSlide = function(slide, fade, stop, previousnext)
{
  // prevent the currentcounter to become < 0
  slide += this.pictures.length;
  
  // always stop and resume afterwards if needed.
  this.stopAutoSlide();
    
  // cancel all crossfading
  var busyCrossFading = this.cancelCrossFading();
  
  // if we were crossfading, and we are asked the next slide while fading, stay with the current one.
  if(busyCrossFading && previousnext=='next' && !fade)
  {
    this.currentSlide %= this.pictures.length;
  }
  else
  {
    this.currentSlide = (slide + this.pictures.length) % this.pictures.length;
  }
    
    
  // if the image is not ready, retry until it is...
  if(!this.pictures[this.currentSlide].preload())
  {
    var preloadtimer = setTimeout(this.varname + ".gotoSlide(" + this.currentSlide + ", " + fade + ", " + stop + ", '" +previousnext + "')",this.preloadpollspeed);
    if(!stop)
      this.timer = preloadtimer;
    this.showLoading();
  }
  else
  {
    this.clearTimer();
    this.hideLoading();
    
    this.setCaption(this.pictures[this.currentSlide].caption);
    this.setLink(this.pictures[this.currentSlide].linkhref, this.pictures[this.currentSlide].linktarget);
    
    if(fade)
    {
      this.crossFadeTo(this.pictures[this.currentSlide]);
      // if we need to continue, start again
      if(!stop)
        this.timer = setTimeout(this.varname + '.nextAutoSlide()', this.pause + this.fadespeed);
    }
    else
    {
        //hide the background
        this.imageObjectBack.style.visibility = 'hidden';
        //changeOpacity(this.imageObjectBack, 0);
        
        // set background image properties
        this.imageObjectBack.width = this.imageObjectFront.width;
        this.imageObjectBack.height = this.imageObjectFront.height;
        this.imageObjectBack.style.left = this.imageObjectFront.style.left;
        this.imageObjectBack.style.top = this.imageObjectFront.style.top;
    
        // set current image as background
        this.imageObjectBack.src = this.imageObjectFront.src;
      
        // make back visible and front invisible
        this.imageObjectBack.style.visibility = 'visible';
        this.imageObjectFront.style.visibility = 'hidden';
        //changeOpacity(this.imageObjectBack, 100);
        //changeOpacity(this.imageObjectFront, 0);
        
        
        // set img size for the new source
        this.imageObjectFront.width = this.pictures[this.currentSlide].width;
        this.imageObjectFront.height = this.pictures[this.currentSlide].height;
        if(this.centerX)
        {
          this.imageObjectFront.style.left = Math.round((this.containerObject.offsetWidth - this.pictures[this.currentSlide].width)/2)+"px";
        }
        if(this.centerY)
        {
          this.imageObjectFront.style.top = Math.round((this.containerObject.offsetHeight - this.pictures[this.currentSlide].height)/2)+"px";
        }
        // set new src
        this.imageObjectFront.src = this.pictures[this.currentSlide].url;

        // make front visible and back invisible
        this.imageObjectFront.style.visibility = 'visible';
        this.imageObjectBack.style.visibility = 'hidden';
        //changeOpacity(this.imageObjectFront, 100);
        //changeOpacity(this.imageObjectBack, 0);
 
      // if we need to continue, start again
      if(!stop)
        this.timer = setTimeout(this.varname + '.nextAutoSlide()', this.pause);
    }
    this.preloadNextImage();
    this.preloadPreviousImage();
  }
  return true;
}

Slideshow.prototype.showLoading = function()
{
  if(this.loadingindicatorObject != undefined)
  {
    if(this.loadingindicatorObject.style.visibility == 'hidden')
    {
      this.loadingindicatorObject.src = ''+this.loadingindicatorObject.src;
      this.loadingindicatorObject.style.visibility = 'visible';
    }
  }
}

Slideshow.prototype.setCaption = function(caption)
{
  if(this.captionbox != undefined)
  {
    if(caption.substring(0,1) == '@')
    {
      //dynamic page, requires seperate server call
      loadCaption(caption.substring(1), this.captionbox);
    }
    else
    {
      this.captionbox.innerHTML = caption;
    }
  }
}

Slideshow.prototype.setLink = function(linkhref, linktarget)
{
  if(linkhref != '' && linkhref != 'default')
  {
    if(linktarget == "_top")
      this.imageObjectFront.onclick = new Function("top.location.href = '" + linkhref + "'");
    else if(linktarget == "_blank" || linktarget == "")
      this.imageObjectFront.onclick = new Function("window.open('" + linkhref + "', '_blank');");
    else
      this.imageObjectFront.onclick = new Function("document.getElementsByName('" + linktarget + "')[0].contentWindow.location.href = '" + linkhref + "';");
    this.imageObjectFront.style.cursor = 'pointer';
  }
  else
  {
    this.imageObjectFront.onclick = '';
    this.imageObjectFront.style.cursor = 'auto';
  }
}

Slideshow.prototype.hideLoading = function()
{
  if(this.loadingindicatorObject != undefined)
  {
    this.loadingindicatorObject.style.visibility = 'hidden';
  }
}

Slideshow.prototype.preloadNextImage = function()
{
  this.pictures[(this.currentSlide + 1)% this.pictures.length].preload();
}

Slideshow.prototype.preloadPreviousImage = function()
{
  this.pictures[(this.currentSlide + this.pictures.length - 1) % this.pictures.length].preload();
}

Slideshow.prototype.initstart = function()
{
  if(this.objectCheck())
    this.gotoSlide(0, false, false);
}

Slideshow.prototype.init = function()
{
  if(this.objectCheck())
    this.gotoSlide(0, false, true);
}

Slideshow.prototype.objectCheck = function()
{
  if(this.containerObject == undefined || this.imageObjectBack == undefined || this.imageObjectFront == undefined)
  {
    alert('Necessary objects are not initialized');
    return false;
  }
  else
    return true;
}


Slideshow.prototype.togglePause = function()
{
  if(this.timer != undefined)
  {
    this.stopAutoSlide();
    return true;
  }
  else
  {
    this.nextAutoSlide();
    return false;
  }
}

Slideshow.prototype.crossFadeTo = function(newImage)
{
    
    // set image background properties
    this.imageObjectBack.width = this.imageObjectFront.width;
    this.imageObjectBack.height = this.imageObjectFront.height;
    this.imageObjectBack.style.left = this.imageObjectFront.style.left;
    this.imageObjectBack.style.top = this.imageObjectFront.style.top;

    // set current image as background
    this.imageObjectBack.src = this.imageObjectFront.src;
  
    // make back visible
    changeOpacity(this.imageObjectBack, 100);
    this.imageObjectBack.style.visibility = 'visible';
    
    // make front invisible by opacity
    changeOpacity(this.imageObjectFront, 0);
    this.imageObjectBack.style.visibility = 'visible';

    // set img size for the new source
    this.imageObjectFront.width = newImage.width;
    this.imageObjectFront.height = newImage.height;
    if(this.centerX)
    {
      this.imageObjectFront.style.left = Math.round((this.containerObject.offsetWidth - newImage.width)/2)+"px";
    }
    if(this.centerY)
    {
      this.imageObjectFront.style.top = Math.round((this.containerObject.offsetHeight - newImage.height)/2)+"px";
    }

    // set new src
    this.imageObjectFront.src = newImage.url;

    // fade in new image to 100% and store the timeouts (for canceling)
    if(this.imageObjectBack.width != this.imageObjectFront.width || this.imageObjectBack.height != this.imageObjectFront.height)
    {
      // the size changes: fade out background
      this.crossFadingTimeouts = crossfade(this.imageObjectFront, this.imageObjectBack, 0, 100, this.fadespeed);
    }
    else
    {
      // the size stays the same: do not fade out background
      this.crossFadingTimeouts = crossfade(this.imageObjectFront, undefined, 0, 100, this.fadespeed);
    }      
    // cancel the crossfading-timeouts after the fade
    this.crossFadingTimeouts.push(setTimeout(this.varname + '.cancelCrossFading()', this.fadespeed));
    
}

Slideshow.prototype.cancelCrossFading = function()
{
  if(this.crossFadingTimeouts.length > 0)
  {
    while(this.crossFadingTimeouts.length > 0)
    {
      clearTimeout(this.crossFadingTimeouts.pop());
    }
    changeOpacity(this.imageObjectFront, 100);
    changeOpacity(this.imageObjectBack, 0);
    return true;
  }
  else
  {
    return false;
  }
}


/* -- Helper functions ----------------------------*/


function crossfade(objectFront, objectBack, opacStart, opacEnd, millisec) 
{ 
  // fade backimage out,
  // fade frontimage in

  var timeoutArray = Array();
  if(objectFront != undefined && opacStart != opacEnd)
  {
    // normalize the values => start is smaller than end, so we can build positive
    if(opacStart > opacEnd)
    {
      var temp = opacStart;
      opacStart = opacEnd;
      opacEnd = temp;
    }
  
    //speed for each frame 
    var timer = 0; 
    var timeout = Math.round(millisec / (opacEnd - opacStart));
    var opacityincrease = 1;
    
    // if number of changes exceeds 25 / sec (timeout < 40ms), keep it to 25, but change the opacity by a factor (instead of 1)
    if(timeout < 40)
    {
      timeout = 40;
      opacityincrease = ((opacEnd - opacStart) * timeout) / millisec;
    }
    
    tekst='';
    //determine the direction for the blending, if start and end are the same nothing happens 

    for(i = opacStart; i <= opacEnd; i += opacityincrease) 
    {
      tekst = tekst + "changeOpacity('" + objectFront.id + "', " + Math.round(i) + ")\n";
      timeoutArray.push(setTimeout("changeOpacity('" + objectFront.id + "', " + Math.round(i) + ")",timeout * timer));
      if(objectBack != undefined )
      {
        timeoutArray.push(setTimeout("changeOpacity('" + objectBack.id + "', " + Math.round(opacEnd-i) + ")",timeout * timer));
        tekst = tekst + "changeOpacity('" + objectBack.id + "', " + Math.round(opacEnd-i) +")\n";
      }
      timer++;
    }
    //alert(tekst);
  }
  return timeoutArray;
} 
 

function changeOpacity(object, opacity) 
{ 
  if(object != undefined)
  {
    if(typeof(object) != 'object')
      object = document.getElementById(object);
       
    if(object != undefined)
    {
      var objectstyle = object.style; 
      objectstyle.opacity = (opacity / 100); 
      objectstyle.MozOpacity = (opacity / 100); 
      objectstyle.KhtmlOpacity = (opacity / 100); 
      objectstyle.filter = "alpha(opacity=" + opacity + ")"; 
    }
  }
}
