if (typeof jQuery == 'undefined') throw new Error('jQuery must be in scope to use Friday menus');
if (typeof Friday == 'undefined') Friday = {};

(function($){
  Friday.Menu = function(trigger,descriptors,options) {
      Friday.Menu.menus.push(this);
      this.trigger = trigger;
      this.descriptors = descriptors;
      this.state = Friday.Menu.STATE_HIDDEN;
      //
      // Merge the options into the settings for the menu
      //
      this.settings = $.extend({
        onselect: function(key) { alert(key); },
        containerClass: 'fridayMenuContainer',
        entryClass: 'fridayMenuEntry',
        offsetHorizontal: 0,
        offsetVertical: 0,
        duration: 750,
        delay: 1500
      },options);
      //
      // Get the dimensions of the trigger
      //
      this.dims = this._getDimensions();
      this.container = $('<div></div>')
        .css({
          position:'absolute',
          top: this.dims.top + this.settings.offsetVertical,
          left: this.dims.left + this.settings.offsetHorizontal,
          display: 'none'
        })
        .addClass(this.settings.containerClass)
        .appendTo('body')[0];
      var menu = this;
      $.each(descriptors,function(){
        $('<div></div>')
          .addClass(menu.settings.entryClass)
          .html(this.caption)
          .attr('fridayMenuEntryKey',this.key)
          .mouseover(function(){$(this).addClass('hover')})
          .mouseout(function(){$(this).removeClass('hover')})
          .click(function(){
            menu.inMenu = false;
            menu._hideMenu();
            menu.settings.onselect($(this).attr('fridayMenuEntryKey'));
           })
          .appendTo(menu.container);
      });
      $(this.trigger)
        .hoverIntent({
          sensitivity: 1,
          interval: 0,
          timeout: menu.settings.delay,
          over: function(){}, //function(){menu._showMenu()},
          out: function(){menu._hideMenu()}
        })
        .mouseover(function(){menu._showMenu()});
      $(this.container)
        .mouseover(function(){menu.inMenu = true})
        .mouseout(function(){menu.inMenu = false})
        .hoverIntent({
          sensitivity: 1,
          interval: 0,
          timeout: menu.settings.delay,
          over: function(){},
          out: function(){menu._hideMenu()}
      });
  }

  Friday.Menu.STATE_HIDDEN = 'hidden';
  Friday.Menu.STATE_HIDING = 'hiding';
  Friday.Menu.STATE_SHOWN = 'shown';
  Friday.Menu.STATE_SHOWING = 'showing';
  Friday.Menu.STATE_PENDING = 'pending'

  Friday.Menu.menus = [];

  Friday.Menu.prototype._getDimensions = function() {
    //alert($(this.trigger).offset().top+','+$(this.trigger).offset().left+','+$(this.trigger).width()+','+$(this.trigger).height());
    return {
      top: $(this.trigger).offset().top,
      left: $(this.trigger).offset().left,
      width: $(this.trigger).width(),
      height: $(this.trigger).height()
    };
  }

  Friday.Menu.prototype._showMenu = function() {
    var menu = this;
    if (menu.state == Friday.Menu.STATE_HIDDEN) {
        menu.dims = this._getDimensions();
        $(menu.container)
          .css({
            top: this.dims.top + this.settings.offsetVertical,
            left: this.dims.left + this.settings.offsetHorizontal
          });
      menu._closeOthers(this);
      menu.state = Friday.Menu.STATE_SHOWING;
      $(menu.container).slideDown(menu.settings.duration,function(){menu.state = Friday.Menu.STATE_SHOWN;});
    }
  }

  Friday.Menu.prototype._hideMenu = function() {
      var menu = this;
      if (!menu.inMenu && (menu.state == Friday.Menu.STATE_SHOWN)) {
        menu.state = Friday.Menu.STATE_HIDING;
        $(menu.container).slideUp(menu.settings.duration,function(){menu.state = Friday.Menu.STATE_HIDDEN;});
      }
  }

  Friday.Menu.prototype._closeOthers = function(except) {
    $.each(Friday.Menu.menus,function(){
        if (this != except) this._hideMenu();
    });
  }

})(jQuery);

