var imageslide = (function() {
  return function(id, data, interval) {  
    var ret = {
      'idx':-1, //current point in slideshow
      'interval' : interval, //interval between slides
      'prevImg' : null, //previous image object (for fades)
      'img' : null, //image object
      'data' : null, //array of slideshow data
      'loadingDiv' : null,
      'loadedCBs' : [],
      'progressBar' : null,
      'progressTimer' : null,
      'replayDiv' : null,
      'replayFadeTimer' : null,
      'replayMaxOp' : 100,

      'init':function() {
        this.next();
      },
      'next':function() { //for next image in slideshow
        this.idx++;
        if (this.idx >= this.data.length) this.idx = 0;
        
        var func = (function(that, idx) { return function() {
          that.showImage(idx);
        };})(this, this.idx);

        if (this.data[this.idx].loaded == 1) { //loaded
          this.showImage(this.idx);
        } else if (this.data[this.idx].loaded == 0) { //being loaded
          this.loadedCBs[this.idx] = func;
        } else { //not loaded
          this.loadImage(this.idx, func);
        }
        
        if (this.idx+1 < this.data.length && this.data[this.idx+1].loaded == -1) { //load next image in slideshow
          this.loadImage(this.idx+1);
        }
      },
      'loadImage':function(idx, cb) {
        var img = document.createElement("img");
        this.data[idx].loaded = 0;
        if (cb) this.loadedCBs[idx] = cb;

        var func = (function(that, idx, img) { return function() {
          that.loadedImage(idx, img) };
        })(this, idx, img);
        if (img.addEventListener) {
          img.addEventListener('load',func,false);
        } else {
          img.attachEvent('onload',func);
        }
        setTimeout(
          (function (that, img, idx) { return function() {
            img.src = that.data[idx].image;
          };})(this, img, idx),
          1
        );
      },
      'loadedImage':function(idx, img) {
        this.data[idx].loaded = 1;
        this.data[idx].src = img.src;
        if (this.loadedCBs[idx]) this.loadedCBs[idx]();
      },
      'showImage':function(idx) {
        this.loadingDiv.style.display = "none";

        if (this.img.src) {
          this.prevImg.src = this.img.src;
          this.opacity(this.prevImg, 100);
          this.prevImg.style.display="block";
          this.fadeImages();
        }
        this.img.src = this.data[idx].src;
        this.img.style.display = "block";
        
        setTimeout(
          (function(that) { return function() {
            that.next();
          };})(this),
          this.interval
        );
      },
      'fadeImages':function() {
        var step=2;
        var op = this.opacity(this.prevImg);
        op-=step;
        this.opacity(this.prevImg, op);

        if (op > 0) {
          setTimeout(
            function(that) {
              return function() {
                that.fadeImages();
              }
            }(this),
            5
          );
        }
      },
      'opacity':function(obj, set) {
        if (typeof set == "undefined") {
          var ret;
          if (typeof obj.style.filter != "undefined") ret = obj.style.filter.replace(/\D+/g, "");
          if (typeof obj.style.MozOpacity != "undefined") ret = obj.style.MozOpacity*100;
          if (typeof obj.style.opacity != "undefined") ret = obj.style.opacity*100;
          return parseInt(ret);
        } else {
          if (typeof obj.style.filter != "undefined") obj.style.filter="alpha(opacity="+(set)+")";
          if (typeof obj.style.MozOpacity != "undefined") obj.style.MozOpacity = set/100;
          if (typeof obj.style.opacity != "undefined") obj.style.opacity = set/100;
        }
      }
    };
    
    var container = document.getElementById(id);

    var imageDiv = document.createElement("div");
    imageDiv.className = 'imageSlideImageDiv';
    
    var loadingDiv = document.createElement("div");
    loadingDiv.className = 'imageSlideLoadingDiv';
    loadingDiv.style.zIndex=999;
    loadingDiv.style.position="absolute";
    loadingDiv.style.display="none";
    imageDiv.appendChild(loadingDiv);
    ret.loadingDiv = loadingDiv;
    
    var prevImg = document.createElement("img");
    prevImg.className = 'imageSlideImage';
    prevImg.style.display="none";
    prevImg.style.position="absolute";
    prevImg.style.zIndex=998;
    imageDiv.appendChild(prevImg);
    ret.prevImg = prevImg;

    var img = document.createElement("img");
    img.className = 'imageSlideImage';
    img.style.display="none";
    img.style.zIndex=997;
    imageDiv.appendChild(img);
    ret.img = img;

    while(container.hasChildNodes()) {
      container.removeChild(container.lastChild);
    }
    container.appendChild(imageDiv);


    for(var i in data) {
      data[i].loaded = -1;
    }

    ret.data = data;
    setTimeout(
      (function (ret) { return function() {
        ret.init();
      };})(ret),
      1
    );
    return ret;
  }
})();
