var gActivePopup = null;
var globalId = 1;


/**
 * Create a MenuBar within the supplied DIV.
 * 
 * A JSON object defines the menu structure structure
 * Each element in the structure can have the following:
 *     "label"  - Text name of the menu-item
 *     "action" - The string to pass to the _action() method when the
 *                menu-item is clicked.
 *     "popup"  - Substructure defining a popup menu.
 *     "style"  - An alternative style class name for the item.
 *
 *
 *    var jsonMenuBar = [
 *        {
 *            label: 'Menu 1',
 *            popup: [
 *                {
 *                    label: 'popup 1',
 *                    action: 'alert(1)'
 *                },
 *                {
 *                    label: 'popup 2',
 *                    action: 'alert(2)'
 *                },
 *                {
 *                    label: 'popup 3 is very long...',
 *                    action: 'alert(3)'
 *                },
 *                {
 *                    label: 'popup 4',
 *                    action: 'alert(4)'
 *                }
 *            ]
 *        },
 *        {
 *            label: 'Menu 2',
 *            action: 'Menu 2',
 *        },
 *        {
 *            label: 'Menu 3',
 *            action: 'Menu 3'
 *        },
 *        {
 *            label: 'Menu 4',
 *            action: 'Menu 4'
 *        }
 *    ];
 
 * 
 **/
function MenuBar(menuDivId, aMenuConfig)
{
    this.MENU_ITEM_STYLE       = "menuitem";
    this.POPUP_MENU_STYLE      = "popup_menu";
    this.POPUP_MENU_ITEM_STYLE = "popupitem";
    
    this.$menubar = jQuery(menuDivId);
    this.config   = aMenuConfig;
}


/**
 * Create the MenuBar.
 *
 * This method is called once the DIV which contains the menu is created.
 * Generally, the onload() event of the BODY is a good place...
 **/
MenuBar.prototype.create = function()
{
    this._createMenuItems(this.$menubar, this.config, this.MENU_ITEM_STYLE);
}


/**
 * Create the child DIVs representing the menu items of either a top-level
 * menu-bar or a popup-menu.
 **/
MenuBar.prototype._createMenuItems = function($parent, menuConfig, defaultClass)
{
    for (var i=0; i<menuConfig.length; i++)
    {
        var itemConfig = menuConfig[i];

        // Create the new menu item as a DIV...
        var menuId = "menu_item_" + globalId++;
        $parent.append("<div id=" + menuId + "></div>");

        // Initialize the new menu item...
        var $item = jQuery("#" + menuId, $parent);
        $item.addClass( itemConfig["style"] || defaultClass );
        $item.html    ( itemConfig["label"] );

        var me = this;
        if (itemConfig["popup"] != null)
        {
            $item.data("popup", this._createPopup(itemConfig["popup"]));
        }
        else
        {
            $item.data("action", itemConfig["action"]);
            $item.click( function(ev)
            {
                me._action( jQuery(this).data("action") );
            });
        }
        //
        // Only top-level menu items have mouseover event handers.
        // This means that only one level of menu nesting is supported!
        //
        if ($parent != this.$menubar) continue;

        $item.mouseover( function(ev)
        {
            me._showPopup(jQuery(this).data("popup"), jQuery(this));
        });
    }
}


/**
 * Create a popup menu...
 *
 * The id of the popup menu DIV is returned...
 **/
MenuBar.prototype._createPopup = function(popupConfig)
{
    // Create the new popup menu as a DIV...
    var popupId = "popup_menu_" + globalId++;
    jQuery("body").append("<div id=" + popupId + "></div>");

    // Initialize the new popup menu...
    var $popup = jQuery("#" + popupId);
    $popup.addClass(this.POPUP_MENU_STYLE);

    // Position it to prevent the document layout later...
    $popup.offset({top: 0, left: 0});
    
    this._createMenuItems($popup, popupConfig, this.POPUP_MENU_ITEM_STYLE);
    return $popup;
}


/**
 * Perform the requested action.
 *
 * This method is called when ever a menu item is clicked and an "action" was
 * defined in its JSON configuration.
 *
 **/
MenuBar.prototype._action = function(aAction)
{
    window.location.href = aAction;
//    alert(aAction);
}

/**
 * Show a popup menu.
 *
 * The ID of the DIV containing the popup and the ID of the parent
 * menu item are supplied.
 **/
MenuBar.prototype._showPopup = function($popup, $parent)
{
    //
    // Hide any currently visible popup menu...  And make the new popup active
    //
    if (gActivePopup)
    {
        gActivePopup.css("visibility", "hidden");
        jQuery(document).unbind("mousemove");
    } 
    gActivePopup = $popup;

    if (!$popup) return;

    // Install a mouse handler to hide the popup when the mouse leaves it...
    var $thisMenu = this.$menubar;
    jQuery(document).mousemove(function(ev)
    {
        if (gActivePopup)
        {
            if (gActivePopup.has(ev.target).size() || $thisMenu.has(ev.target).size())
            {
                return;
            }
 
            gActivePopup.css("visibility", "hidden");
            gActivePopup = null;
            jQuery(document).unbind("mousemove");
        }
    });

    // Position the popup menu...
    var off = $parent.offset();
    off.top += $parent.height();
    $popup.offset( off );

    // Show the new popup...
    $popup.css("visibility", "visible");
}

