/**
 * Prototype base FancyMenu
 * @version 0.9b
 * @alias  FancyMenu
 *
 * @author Guillermo Rauch <devthought.com>
 * @author firejune <to [at] firejune [dot] com>
 * 
 * @usage = new FancyMenu('fancymenu', {
 *   transition: Effect.Transitions.backOut, duration: 0.7
 * });
 * 
 * @requires 
 *   - prototype <http://www.prototypejs.org>
 *   - scriptaculous <http://script.aculo.us>
 * 
 */

if (!Effect.Transitions.backOut) {
  Effect.Transitions.backOut = function(pos) {
    return ((pos-1)*(pos-1)*((2.7)*(pos-1) + 1.7) + 1);
  };
}

var FancyMenu = Class.create({
  initialize: function(menu, options) {
    this.options = Object.extend({
      transition: Effect.Transitions.sineInOut, duration: 0.5
    }, options || {});

    this.menu = $(menu);
    this.current = this.menu.down('li.current').down('a');
    
    var div = new Element('DIV', {className: 'left'});
    this.back = new Element('DIV', {className: 'background'});

    // BG Image Cache
    if (Prototype.Browser.IE6) {
      try {
       document.execCommand('BackgroundImageCache', false, true);
      } catch(e) {}
    }

    this.back.appendChild(div);
    this.menu.appendChild(this.back);

    this.observeClick = this.clickItem.bindAsEventListener(this);
    this.observeMouseMove = this.moveBg.bindAsEventListener(this);
    this.observeMouseOut = function() { this.moveBg(this.current); }.bind(this);

    this.menu.observe('click', this.observeClick);
    this.menu.observe('mousemove', this.observeMouseMove);
    this.menu.observe('mouseout', this.observeMouseOut);
    document.observe('unload', this.unregisterEvents.bindAsEventListener(this));

    if (this.current) this.setCurrent(this.current);
    else this.setCurrent(this.menu.down('a'));
  },

  unregisterEvents: function() {
    this.menu.stopObserving('click', this.observeClick);
    this.menu.stopObserving('mousemove', this.observeMouseMove);
    this.menu.stopObserving('mouseout', this.observeMouseOut);
  },

  clickItem: function(event) {
    var item = Event.element(event);
    if (!item || item.tagName != "A") return;
    if (!this.current) this.setCurrent(item);

    this.menu.down('li.current').className = '';
    this.current = item;

    $(this.current).up('li').className = 'current';
  },

  setCurrent: function(el) {
    this.back.setStyle({
      left: this.getOffsetX(el) + 'px',
      width: el.offsetWidth + 'px',
      visibility: 'visible'
    });

    this.current = el;
  },

  getOffsetX: function(el) {
    if (Prototype.Browser.IE) el = el.up();
    return Position.cumulativeOffset(el)[0] - Position.cumulativeOffset(this.menu)[0] ;
  },

  moveBg: function(object) {
    if (object.tagName == 'A') object = object;
    else object = Event.element(object);

    if (!this.current || this.object == object || !object || object.tagName != "A") return;

    this.moveTimeout();

    this.timeout = window.setTimeout(function() {
      var styles = "width:" + object.offsetWidth + "px; left:" + this.getOffsetX(object) + "px;";
      if (this.morph && this.morph.state == 'running') this.morph.cancel();

      this.morph = new Effect.Morph(this.back, {
        style: styles,
        duration: this.options.duration,
        transition: this.options.transition
      });
    }.bind(this), 90);

    this.object = object;
  },

  moveTimeout: function() {
    if (typeof this.timeout == "number") {
      window.clearTimeout(this.timeout);
      delete this.timeout;
    }
  }
});
