document.observe('dom:loaded', function() {
  new slideshow($('hero'));
});

/**
 * Slideshow.
 * Creates a slideshow object.
 */

var slideshow = Class.create({
  /**
   * Initialize all values for the slideshow object.
   * @param element A single Prototype-extended DOM element, e.g., $('slideshow').
   */
  initialize: function(element) {
    if (element === null) {
      return;
    }
    var i = 0;
    this.element = element;
    this.user_logged_in = false;
    this.slides = element.select('.slide');
    this.total = element.select('.slide').length;
    i = this.total - 1;
    this.defaults = [];
    if (i > 0) { do {
      this.defaults[i] = this.slides[i].innerHTML;
    } while (i--);}
    this.previous_slide = 1;
    if (this.total > 1) {
      this.next_slide = 2;
    } else {
      this.next_slide = 1;
    }
    this.nav_container = new Element('ul');
    this.processing = false;
    this.looping = true;
    this.fade = setInterval(this.switch_to.bind(this), 4000);
    this._create();
  },
  /**
   * Create the slideshow object. Called once internally during initialization.
   */
  _create: function() {
    var i = 1,
        navlinks = '<li class="selected">1</li>';
    for (i; i < this.total; i++) {
      $('s' + i).hide();
      navlinks += '<li>' + parseInt(i + 1, 10) + '</li>';
    }
    this.nav_container.writeAttribute({
      'class': 'slide_nav'
    }).update(navlinks);
    this.element.appendChild(this.nav_container);
    this.nav = this.nav_container.select('li');
    this.nav.invoke('observe', 'mouseover', function() {
      $(this).addClassName('hover');
    }).invoke('observe', 'mouseout', function() {
      $(this).removeClassName('hover');
    }).invoke('observe', 'click', function(e) {
      Event.stop(e);
      if (e.target.hasClassName('selected')) {
        this._timer();
      } else {
        this.switch_to(e.target.innerHTML);
        this.looping = false;
        clearTimeout(this.fade);
      }
    }.bind(this));
    document.observe('auth:start', function(event) {
      this.user_logged_in = event.memo.logged_in;
      this._update();
    }.bind(this));
  },
  /**
   * Update the slideshow object. Called internally each time the user's authorization status changes.
   */
  _update: function() {
    if (this.user_logged_in == true) {
      var randomnumber = Math.floor(Math.random() * 10000000001); /** To prevent caching. */
      new Ajax.Request('/home/slides?' + randomnumber, {
        method:'get',
        onSuccess: function(transport) {
          this.slides[0].update(transport.responseText);
        }.bind(this)
      });
    } else {
      this.slides[0].update(this.defaults[0]);
    }
  },
  /**
   * Start or stop the object's timer. Called interally.
   */
  _timer: function() {
    if (this.looping) {
      this.looping = false;
      clearTimeout(this.fade);
    } else {
      this.looping = true;
      this.fade = setInterval(this.switch_to.bind(this), 4000);
    }
  },
  /**
   * Switch to a specific slide, or the next slide in the loop (if no next slide is defined). May be called externally.
   * @param next_slide Integer.
   */
  switch_to: function(next_slide) {
    next_slide = (typeof next_slide == 'string') ? next_slide : this.next_slide;
    next_slide = parseInt(next_slide, 10);
    if (next_slide < 1 || next_slide > this.total) {
      var slide_id = 0;
    } else {
      var slide_id = next_slide - 1;
    }
    if (!this.processing) {
      var length = this.total,
          i = 0,
          j = 3;
      if (next_slide < this.total) {
        this.next_slide = next_slide + 1;
      } else {
        this.next_slide = 1;
      }
      for (i; i < length; i++) {
        if (this.slides[i].hasClassName('current')) {
          this.previous_slide = i + 1;
        }
      }
      this.processing = true;
      new Effect.Appear(this.slides[slide_id], {
        duration: 1.0,
        beforeStart: function() {
          this.slides[this.previous_slide - 1].removeClassName('current').fade({duration:1.0});
          this.slides[slide_id].addClassName('current');
          this.nav.invoke('removeClassName', 'selected');
          this.nav[slide_id].addClassName('selected');
        }.bind(this),
        afterFinish: function() {
          this.processing = false;
        }.bind(this)
      });
    }
  }
});

