/*
Simple slideshow. Copyright 2006 Dag Sverre Seljebotn,
dagss@student.matnat.uio.no.

Ask for permission before using and I'll wrap it up nicely with a GPL
license or something.

Notes:
- Fetching ticks to do properly was too slow, so we need to rely on
  "incrementally adding ticks". A crude benchmark is done to set the
  fade speed...
- A quadratic fade function (on [0,1]) subjectively looked much better
  than a linear one. I didn't experiment too much - cubic looked worse
  on Firefox and I expect non-integer powers to be a waste of computing
  resources.
*/

if (typeof(Fredtun) == 'undefined') {
  var Fredtun = {};
}

Fredtun.Slideshow = function(interval) {
  this.images = [];
  this.imageElements = [];
  this.interval = interval;
  this.fade = false; // not fully implemented
  this.fadeDuration = 800; // in millisecs
  this.transitionSteps = 8;
  var self = this;
  this.bound_onSwitchImage = function () { self.onSwitchImage(); }
  this.numberOfTickEvents = 0;
  this.numberOfTransitions = 0;

  this.tickstep = 300; // in case benchmark isn't done...
  var BENCHDUR = 1000;
  var self = this;
}

Fredtun.Slideshow.slideshowIdx = 0;

Fredtun.Slideshow.setOpacity = function(elem, opacity) {
  if (opacity == 1) {
    elem.style.opacity = 0.99; // bug in old versions of Firefox...
    elem.style.filter = null;
  } else {
    elem.style.opacity = opacity;
    elem.style.filter = "alpha(opacity=" + Math.floor(opacity * 100) + ")";
  }
}

Fredtun.Slideshow.prototype = {
  addImage : function(url, width, height) {
    this.images[this.images.length] = [url, width, height];
  },

  writeSlideshow: function() {
    var idx = Fredtun.Slideshow.slideshowIdx++;
    var id = "fredtun-slideshow-id-" + idx;
//    document.write('<div style="position: relative">');
    document.write('<div id="' + id + '"></div>'); 
//    document.write('</div>');
    var div = document.getElementById(id);
    this.setContainer(div);
    this.initialize();
  },

  setContainer: function(container) {
    this.container = container;
  },

  initialize: function() {
    for (var i = 0; i != this.images.length; ++i) {
      var img = document.createElement("img");
      img.src = this.images[i][0];

      img.style.width = "100%";
      img.style.height = "100%";
      img.style.position = "absolute";
      img.style.top = img.style.left = "0px";

      //img.style.filter = "alpha(opacity=50)";
      if (i > 0) img.style.display = "none";
      this.imageElements[i] = img;
      this.container.appendChild(img);
    }
    this.container.style.width = "100%";
    this.container.style.height = "100%";
    this.currentIdx = 0;

    // I suspect browsers might have memory leaks, so create closures only once...
    var self = this;

    function getStepClosure(deg) {
      function closure() {
        Fredtun.Slideshow.setOpacity(self.fadeFrom, 1 - deg);
        Fredtun.Slideshow.setOpacity(self.fadeTo, deg);
      }
      return closure;
    }
    
    this.fadeClosures = [];

    this.timePerStep = this.fadeDuration / this.transitionSteps;
    var opacityPerStep = 1 / this.transitionSteps;

    for (var i = 0; i != this.transitionSteps - 1; ++i) {
      var deg = opacityPerStep * i;
      deg = deg * deg; // quadratic fade function looks better
      this.fadeClosures[i] = getStepClosure(deg);
    }
    // set up last animation step to trigger new image switch
    var endclosure = getStepClosure(1);
    var endswitch = this.bound_onSwitchImage;
    var interval = this.interval;
    this.fadeClosures[this.transitionSteps - 1] = function() {
      endclosure();
      setTimeout(endswitch, interval);
    }

    // Start switching. We cannot use setInterval - on a slow computer, the switching
    // will inevitably catch up with the fading and things go crazy...
    var self = this;
    setTimeout(this.bound_onSwitchImage, this.interval);    
  },

  startFade: function(from, to) {
    this.fadeStartTick = new Date().getTime();
    this.fadeFrom = from;
    this.fadeTo = to;
    from.style.display = "block";
    to.style.display = "block";

    this.fadeClosures[0]();
    var n = this.transitionSteps;
    for (var i = 1; i != n; ++i) {
      setTimeout(this.fadeClosures[i], this.timePerStep * i);
    }
  },

  onSwitchImage: function () {
    var cur = this.currentIdx;
    var next = (cur + 1) % this.imageElements.length;
    this.startFade(this.imageElements[cur], this.imageElements[next]);
    this.currentIdx = next;     
  }

}
