/**
 * @class Ext.menu.MenuMgr
 * Provides a common registry of all menu items on a page so that they can be easily accessed by id.
 * @singleton
 */

Ext.menu.MenuMgr = function(){
   
var menus, active, groups = {}, attached = false, lastShow = new Date();

   
// private - called when first menu is created
   
function init(){
       menus
= {};
       active
= new Ext.util.MixedCollection();
       
Ext.getDoc().addKeyListener(27, function(){
           
if(active.length > 0){
               hideAll
();
           
}
       
});
   
}

   
// private
   
function hideAll(){
       
if(active && active.length > 0){
           
var c = active.clone();
           c
.each(function(m){
               m
.hide();
           
});
       
}
   
}

   
// private
   
function onHide(m){
       active
.remove(m);
       
if(active.length < 1){
           
Ext.getDoc().un("mousedown", onMouseDown);
           attached
= false;
       
}
   
}

   
// private
   
function onShow(m){
       
var last = active.last();
       lastShow
= new Date();
       active
.add(m);
       
if(!attached){
           
Ext.getDoc().on("mousedown", onMouseDown);
           attached
= true;
       
}
       
if(m.parentMenu){
          m
.getEl().setZIndex(parseInt(m.parentMenu.getEl().getStyle("z-index"), 10) + 3);
          m
.parentMenu.activeChild = m;
       
}else if(last && last.isVisible()){
          m
.getEl().setZIndex(parseInt(last.getEl().getStyle("z-index"), 10) + 3);
       
}
   
}

   
// private
   
function onBeforeHide(m){
       
if(m.activeChild){
           m
.activeChild.hide();
       
}
       
if(m.autoHideTimer){
           clearTimeout
(m.autoHideTimer);
           
delete m.autoHideTimer;
       
}
   
}

   
// private
   
function onBeforeShow(m){
       
var pm = m.parentMenu;
       
if(!pm && !m.allowOtherMenus){
           hideAll
();
       
}else if(pm && pm.activeChild){
           pm
.activeChild.hide();
       
}
   
}

   
// private
   
function onMouseDown(e){
       
if(lastShow.getElapsed() > 50 && active.length > 0 && !e.getTarget(".x-menu")){
           hideAll
();
       
}
   
}

   
// private
   
function onBeforeCheck(mi, state){
       
if(state){
           
var g = groups[mi.group];
           
for(var i = 0, l = g.length; i < l; i++){
               
if(g[i] != mi){
                   g
[i].setChecked(false);
               
}
           
}
       
}
   
}

   
return {

       
/**
        * Hides all menus that are currently visible
        */

       hideAll
: function(){
            hideAll
();  
       
},

       
// private
       
register : function(menu){
           
if(!menus){
               init
();
           
}
           menus
[menu.id] = menu;
           menu
.on("beforehide", onBeforeHide);
           menu
.on("hide", onHide);
           menu
.on("beforeshow", onBeforeShow);
           menu
.on("show", onShow);
           
var g = menu.group;
           
if(g && menu.events["checkchange"]){
               
if(!groups[g]){
                   groups
[g] = [];
               
}
               groups
[g].push(menu);
               menu
.on("checkchange", onCheck);
           
}
       
},

       
/**
         * Returns a {@link Ext.menu.Menu} object
         * @param {String/Object} menu The string menu id, an existing menu object reference, or a Menu config that will
         * be used to generate and return a new Menu instance.
         * @return {Ext.menu.Menu} The specified menu, or null if none are found
         */

       
get : function(menu){
           
if(typeof menu == "string"){ // menu id
               
if(!menus){  // not initialized, no menus to return
                   
return null;
               
}
               
return menus[menu];
           
}else if(menu.events){  // menu instance
               
return menu;
           
}else if(typeof menu.length == 'number'){ // array of menu items?
               
return new Ext.menu.Menu({items:menu});
           
}else{ // otherwise, must be a config
               
return Ext.create(menu, 'menu');
           
}
       
},

       
// private
       unregister
: function(menu){
           
delete menus[menu.id];
           menu
.un("beforehide", onBeforeHide);
           menu
.un("hide", onHide);
           menu
.un("beforeshow", onBeforeShow);
           menu
.un("show", onShow);
           
var g = menu.group;
           
if(g && menu.events["checkchange"]){
               groups
[g].remove(menu);
               menu
.un("checkchange", onCheck);
           
}
       
},

       
// private
       registerCheckable
: function(menuItem){
           
var g = menuItem.group;
           
if(g){
               
if(!groups[g]){
                   groups
[g] = [];
               
}
               groups
[g].push(menuItem);
               menuItem
.on("beforecheckchange", onBeforeCheck);
           
}
       
},

       
// private
       unregisterCheckable
: function(menuItem){
           
var g = menuItem.group;
           
if(g){
               groups
[g].remove(menuItem);
               menuItem
.un("beforecheckchange", onBeforeCheck);
           
}
       
},

       getCheckedItem
: function(groupId){
           
var g = groups[groupId];
           
if(g){
               
for(var i = 0, l = g.length; i < l; i++){
                   
if(g[i].checked){
                       
return g[i];
                   
}
               
}
           
}
           
return null;
       
},

       setCheckedItem
: function(groupId, itemId){
           
var g = groups[groupId];
           
if(g){
               
for(var i = 0, l = g.length; i < l; i++){
                   
if(g[i].id == itemId){
                       g
[i].setChecked(true);
                   
}
               
}
           
}
           
return null;
       
}
   
};
}();