/**
 * Tomo.SlideShow.js
 * Singleton object to be added to any page that needs a slideshow.
 *
 * Copyright (c) 2009 Stuart Jones
 *
 * Requires:
 * - Prototype
 * - Scriptaculous
 * - A global "imgs" array of images
 * - A trigger element (i.e. button) called "btnStart"
 *
 */

try {
  console.assert(1);
} catch(e) {
  console = {
    log: function() {},
    assert: function() {}
  }
}


var Tomo = window.Tomo || {};
Tomo.SlideShow = {

  /**
   * The number of images to load before allowing the slide show to be started.
   */
  INITIAL_PRELOAD_COUNT: 10,

  preloads: [],
  loadedcount: 0,

  /**
   *
   */
  initialise: function () {

    if (!Tomo.SlideShow.imgs || Tomo.SlideShow.imgs.length === 0) {
      // Eh?
      return;
    }

    Tomo.SlideShow.preload_first_m();

    new PeriodicalExecuter(
      function(pe) {
        if (Tomo.SlideShow.loadedcount == Tomo.SlideShow.INITIAL_PRELOAD_COUNT) {
          $('sandtimer').hide();
          $('btnStart').show();
          Tomo.SlideShow.preload_remaining_n();
        } else if (Tomo.SlideShow.loadedcount == Tomo.SlideShow.imgs.length) {
          pe.stop();
        } else {
          console.log('loadedcount = ' + Tomo.SlideShow.loadedcount);
        }
      },
      1 // seconds. need to decide how long to wait before giving up.
    );

    Event.observe('btnStart', 'click', Tomo.SlideShow.startShow);

  },

  /**
   *
   */
  startShow: function () {

    Event.stopObserving('btnStart', 'click', Tomo.SlideShow.startShow);

    var ss = new Tomo.SS(
      'photo_over',
      'photo_under',
      Tomo.SlideShow.preloads,
      Tomo.SlideShow.options);
    ss.start();

  },

  /**
   *
   */
  preload_first_m: function () {
    console.log('first m');
    Tomo.SlideShow.preload(0, Tomo.SlideShow.INITIAL_PRELOAD_COUNT);
  },

  /**
   *
   */
  preload_remaining_n: function() {
    console.log('remaining m');
    Tomo.SlideShow.preload(Tomo.SlideShow.INITIAL_PRELOAD_COUNT, Tomo.SlideShow.imgs.length);
  },

  /**
   *
   */
  preload: function (start, end) {
    for (var i = start; i < end; i++) {
      var image = new Image();
      image.src = Tomo.SlideShow.imgs[i];
      image.onload = function () {
        Tomo.SlideShow.loadedcount++;
      };
      Tomo.SlideShow.preloads.push(image);
      console.log('loaded image ' + i);
    }
  }
};


// thanks to http://www.ruby-forum.com/topic/113456#new
Tomo.SS = Class.create();
Tomo.SS.prototype = {
  /**
   *
   */
  // using css, set imgNodeTop and imgNodeBottom to the same position using top and left
  // then set imgNodeTop's z-index to be higher
  // also pass in an array of the sources
  initialize: function(imgNodeTop, imgNodeBottom, imageSources, options) {
    console.log(imageSources);
    // internally store the given values
    this.imgTop = $(imgNodeTop);
    this.imgBottom = $(imgNodeBottom);
    this.sources = imageSources;
    this.options = Object.extend(
      {
        fadeDuration: 0.3, //0.4
        showDuration: 0.1, //0.1
      },
      options
    );

    // set the top image source to the first source
    this.imgTop.src = this.sources[0].src;
    this.position = 0;
    this.onTop = 1;
    this.started = false;
  },

  /**
   *
   */
  start: function() {
    window.setTimeout(
      this.next.bind(this),
      this.options.showDuration * 1000
    );
    this.started = true;
  },

  /**
   *
   */
  stop: function() {
    this.started = false;
  },
 
  /**
   *
   */
  next: function() {

    // set the bottom image to the next source
    var pos = (this.position == this.sources.length - 1) ? 0 : (this.position + 1);
    console.log ('pos is ' + pos);

    // saj
    if (pos == 0) {
      // we're done... but this is naughty...
      Event.observe('btnStart', 'click', Tomo.SlideShow.startShow);
      return;
    }

    this.imgBottom.src = this.sources[pos].src;

    //console.log('setting imgBottom to pos '+pos+' and fading imgTop');
    // fade away the top image to slowly reveal the bottom image
    console.log('fading with imgTop = '+this.imgTop.src+', imgBottom ='+this.imgBottom.src);

    new Effect.Fade(
      this.imgTop,
      {
        duration: this.options.fadeDuration,
        afterFinish: function() {
          // when finished, set the top image to the last image (hopefully it won't flicker)
          this.imgTop.src = this.sources[this.position].src;
          //console.log('setting imgTop to pos '+this.position);
          this.imgTop.show();
          // start over
          if (this.started) this.start(); //////////
        }.bind(this)
      }
    );

    // increment the position, wrapping if needed
    this.position++;
    if (this.position==this.sources.length) {
      this.position = 0; // saj says this won't be reached
    }
  }
};

