Ext.ns('Ext.ux');

Ext.ux.Menu = Ext.extend(Ext.util.Observable, {
    direction: 'horizontal',
    delay: 0.2,
    autoWidth: true,
    transitionType: 'fade',
    transitionDuration: 0.3,
    animate: true,
    currentClass: 'current',
    constructor: function(elId, config){
        config = config ||
        {};
        Ext.apply(this, config);
        
        Ext.ux.Menu.superclass.constructor.call(this, config);
        
        this.addEvents('show', 'hide', 'click');
        
        this.el = Ext.get(elId);
        
        this.initMarkup();
        this.initEvents();
        
        this.setCurrent();
    },
    
    initMarkup: function(){
        this.el.show();
        this.container = this.el.wrap({
            cls: 'ux-menu-container',
            style: 'z-index: ' + --Ext.ux.Menu.zSeed
        });
        this.items = this.el.select('li');
        
        this.el.addClass('ux-menu ux-menu-' + this.direction);
        this.el.select('>li').addClass('ux-menu-item-main');
        
        
        this.el.select('li').addClass('ux-menu-item-parent').each(function(item){
           
						if (item.down('a')) {
                item.down('a').addClass('ux-menu-link-parent').createChild({
                    tag: 'span',
                    cls: 'ux-menu-arrow'
                });
            }
        });
        
        this.el.select('li:first-child>a').addClass('ux-menu-link-first');
        this.el.select('li:last-child>a').addClass('ux-menu-link-last');
        
        // create clear fixes for the floating stuff
        this.container.addClass('ux-menu-clearfix');
        
        // if autoWidth make every submenu as wide as its biggest child;
        if (this.autoWidth) {
            this.doAutoWidth();
        }
        
        var subs = this.el.select('ul');
        subs.addClass('ux-menu-sub');
        
        subs.addClass('ux-menu-hidden');
        
        var subs = this.el.select('>li');
        subs.each(function(item){
            item.createChild({
                tag: 'div',
                "class": 'navi-top',
                style: "height:11px;width:" + (item.getWidth() - 4) + "px;position:relative;margin-right:4px;top:-45px;background:url(/img/css/navi_hover_links.gif) no-repeat;"
            })
        });
        
        this.el.select('>li div.navi-top').createChild({
            "class": 'navi-top-top',
            tag: 'div',
            style: 'margin-left:20px;background:url(/img/css/navi_hover_rechts.gif) right top no-repeat;'
        })
        this.el.select('>li div.navi-top-top').createChild({
            tag: 'div',
            style: 'height:11px'
        })
        
    },
    
    initEvents: function(){
        this.showTask = new Ext.util.DelayedTask(this.showMenu, this);
        this.hideTask = new Ext.util.DelayedTask(function(){
            this.showTask.cancel();
            this.hideAll();
            this.fireEvent('hide');
        }, this);
        
        this.el.hover(function(){
            this.hideTask.cancel();
        }, function(){
            this.hideTask.delay(this.delay * 1000);
        }, this);
        
        // for each item that has a submenu, create a mouseenter function that shows its submenu
        // delay 5 to make sure enter is fired after mouseover
        this.el.select('li.ux-menu-item-parent').on('mouseenter', this.onParentEnter, false, {
            me: this,
            delay: 5
        });
        
        // listen for mouseover events on items to hide other items submenus and remove hovers
        this.el.on('mouseover', function(ev, t){
            this.manageSiblings(t);
            // if this item does not have a submenu, the showMenu task for a sibling could potentially still be fired, so cancel it
            
            if (!Ext.fly(t).hasClass('ux-menu-item-parent')) {
                //  this.showTask.cancel();
            }
        }, this, {
            delegate: 'li'
        });
        
        this.el.on('click', function(ev, t){
            return this.fireEvent('click', ev, t, this);
        }, this, {
            delegate: 'a'
        })
    },
    
    onParentEnter: function(ev, link, o){
        var item = Ext.get(this), me = o.me;
        
        // if this item is in a submenu and contains a submenu, check if the submenu is not still animating
        if (!item.hasClass('ux-menu-item-main') && item.parent('ul').hasActiveFx()) {
            item.parent('ul').stopFx(true);
        }
        
        // if submenu is already shown dont do anything
        if (item.child('ul') && !item.child('ul').hasClass('ux-menu-hidden')) {
            return;
        }
        
        me.showTask.delay(me.delay * 1000, false, false, [item]);
    },
    
    showMenu: function(item){
        var menu = item.child('ul'), x = y = 0;
        
        item.select('>a').addClass('ux-menu-link-hover');
        
        item.select('.navi-top').addClass('navi-top-visible');
        
        if (!menu) 
            return;
        
        // some different configurations require different positioning
        if (this.direction == 'horizontal' && item.hasClass('ux-menu-item-main')) {
            y = item.getHeight() + 2 - 11;
        }
        else {
            x = item.getWidth() + 1;
        }
        
        // if its ie, force a repaint of the submenu
        if (Ext.isIE) {
            menu.select('ul').addClass('ux-menu-hidden');
            // ie bugs...
           /* if (Ext.isBorderBox || Ext.isIE7) {
                item.down('iframe').setStyle({
                    left: x + 'px',
                    top: y + 'px',
                    display: 'block'
                });
            }*/
        }
        
        menu.removeClass('ux-menu-hidden');
        x = ((item.getWidth() - menu.getWidth()) / 2) - 3;
        menu.setStyle({
            left: x + 'px',
            top: y + 'px'
        });
        
        if (this.animate) {
            switch (this.transitionType) {
                case 'slide':
                    if (this.direction == 'horizontal' && item.hasClass('ux-menu-item-main')) {
                        menu.slideIn('t', {
                            duration: this.transitionDuration
                        });
                    }
                    else {
                        menu.slideIn('l', {
                            duration: this.transitionDuration
                        });
                    }
                    break;
                    
                default:
                    menu.setOpacity(0.001).fadeIn({
                        duration: this.transitionDuration
                    });
                    break
            }
        }
        
        this.fireEvent('show', item, menu, this);
    },
    
    manageSiblings: function(item){
        var item = Ext.get(item);
        
        item.parent().select('li.ux-menu-item-parent').each(function(child){
        
            if (child.dom.id !== item.dom.id) {
                child.select('>a').removeClass('ux-menu-link-hover');
                child.select('ul').stopFx(false).addClass('ux-menu-hidden');
                this.container.select('div.navi-top-visible').removeClass('navi-top-visible');
                
                if (Ext.isBorderBox || Ext.isIE7) {
                    child.select('iframe').setStyle('display', 'none');
                }
            }
        }, this);
    },
    
    hideAll: function(){
        this.manageSiblings(this.el);
    },
    
    setCurrent: function(){
        var els = this.el.query('.' + this.currentClass);
        if (!els.length) {
            return;
        }
        var item = Ext.get(els[els.length - 1]).removeClass(this.currentClass).findParent('li', null, true);
        while (item && item.parent('.ux-menu')) {
            item.down('a').addClass(this.currentClass);
            item = item.parent('li');
        }
    },
    
    doAutoWidth: function(){
        var fixWidth = function(sub){
            var widest = 0;
            var items = sub.select('>li');
            
            sub.setStyle({
                width: 3000 + 'px'
            });
            items.each(function(item){
                widest = Math.max(widest, item.getWidth());
            });
            
            widest = Ext.isIE ? widest + 1 : widest;
            items.setWidth(widest + 'px');
            sub.setWidth(widest + 'px');
        }
        
        if (this.direction == 'vertical') {
            this.container.select('ul').each(fixWidth);
        }
        else {
            this.el.select('ul').each(fixWidth);
        }
    }
});

Ext.ux.Menu.zSeed = 10000;
