/**
 * @class RecentlyTicker
 * Auto-update the recently used timeline.
 */
var RecentlyTicker = Class.create({
  lineHeight: 27,
  recentlyURL: '/home/recently_used',
  updateTime: 5000,
  requestNumber: 0,
  maxRequestNumber: 128,
  html: null,

  /**
   * @construct initalize
   * Appends some elements, sets interval
   * @param elm {string} ID value of the element to auto-update
   */
  initialize: function(node) {
    if(!$(node)) return;
    this.node = $(node);

    wrap = Builder.node('div', {id: 'recently-wrap'}, [Builder.node('div')]);

    this.node.parentNode.insertBefore(wrap, this.node);
    wrap.appendChild(this.node);
    wrap.onmouseover = (function() {this.hovered = true;}).bindAsEventListener(this);
    wrap.onmouseout = (function() {this.hovered = false;}).bindAsEventListener(this);

    liElms = this.node.getElementsByTagName('li');

    this.activeItems = '|';
    this.size = liElms.length;

    for (var l = 0; l < this.size; l++)
      this.activeItems += liElms[l].id + "|";

    this.size = liElms.length;
    this.busy = this.hovered = false;
    this.odd = 1;

    this.updateTicker();
  },

  /**
   * Called every once in a while to update the stuff.
   * Does the Ajax call and checks whick items need to be inserted.
   * Then calls this.insertLines to insert all lines.
   */
  updateTicker: function() {
    if (this.busy || this.hovered) {
      window.setTimeout(this.updateTicker.bindAsEventListener(this), Math.round(this.updateTime * Math.random()));
      return;
    }

    this.requestNumber++;
    if (this.requestNumber > this.maxRequestNumber) {
      this.requestNumber = 1;
    }

    new Ajax.Request(this.recentlyURL, {
      method: 'get',
      parameters: {request_number: this.requestNumber},
      onSuccess: (function(transport) {
        var response = transport.responseText;

        var chunk = response.split(/<li id="|<\/li>/g);

        this.lines = [];
        count = -1;

        // A lot of unnecessary code, just because of one single IE bug.
        for (var k = 0; k < chunk.length; k++){
          if (typeof chunk[k] !== 'undefined') {
            var split = chunk[k].indexOf('">');
            var id = chunk[k].substring(0, split);
            var html = chunk[k].substring(split + 2, chunk[k].length);

            if (split !== -1 && this.activeItems.indexOf('|' + id + '|') == -1) {
              this.activeItems += id + "|";
              this.lines[count++] = html;
            }
          }
        }

        if (count > 0) {
          window.setTimeout(this.insertLines.bindAsEventListener(this), Math.round(this.updateTime * Math.random()));
        } else {
          window.setTimeout(this.updateTicker.bindAsEventListener(this), this.updateTime);
        }
      }).bindAsEventListener(this)
    });
  },

  /**
   * Preloads images in the lines.
   * After preloadin, it calles insertLines_animat() to insert the line with an animation
   */
  insertLines: function() {
    if (this.busy || this.hovered) {
      window.setTimeout(this.insertLines.bindAsEventListener(this), Math.round(this.updateTime * Math.random()));
      return;
    }

    this.busy = true;

    if (this.lines.length < 1) {
      window.setTimeout(this.updateTicker.bindAsEventListener(this), Math.round(this.updateTime * Math.random()));
      this.busy = false;
      return;
    }

    this.html = this.lines.shift(); // shift removes and returns the first element in the this.lines array

    this.preloadImages = this.html.match(/src="(.+?[\.jpg|\.png|\.gif])"/gi);
    this.preloadImages_loaded = 0;
    tempImg = [];

    if (this.preloadImages) {
      for (var m = 0; m < this.preloadImages.length; m++) {
        tempImg[m] = new Image();

        tempImg[m].onload = (function() {
          this.preloadImages_loaded++;
          if (this.preloadImages_loaded === this.preloadImages.length) {
            this.insertLines_animate.bindAsEventListener(this)();
          }
        }).bindAsEventListener(this);

        tempImg[m].src = this.preloadImages[m].replace(/(src="|")/g, '');
      }
    } else {
      this.insertLines_animate.bindAsEventListener(this)();
    }
  },

  /*
   * Inserts the lines with an animation.
   * After finsih, it calles insertLines() for the next line.
   */
  insertLines_animate: function() {
    var fromPos = this.lineHeight * ((this.odd === 1) ? 1 : 2);
    this.odd *= -1;

    var newElm = document.createElement('li');
    newElm.innerHTML = this.html;
    this.node.insert({top: newElm});

    this.node.style.backgroundPosition = '0px -' + fromPos + 'px';
    this.node.style.marginTop = '-' + this.lineHeight + 'px';

    this.node.morph({
      marginTop: '0px'
    },{
      duration: 0.75,
      transition: Effect.Transitions.sinoidal,
      afterFinish: (function(){
        var liElms = this.node.getElementsByTagName('li');
        for (var j = this.size; j < liElms.length; j++)
          this.node.removeChild(liElms[j]);

        this.busy = false;

        if (this.lines.length !== 0) {
          window.setTimeout(this.insertLines.bindAsEventListener(this), Math.round(this.updateTime * Math.random()));
        } else {
          this.updateTicker();
        }
      }).bindAsEventListener(this)
    });
  }
});