//<!--
/**
 * Usage:
 * var myMenu = new DropNav(
    {
        delay: 250,
        selector: '#nav',
        MenuHighlights:
        [{
            target: 'li.root',
            transition:
            {
                type: MenuHighlightTransitions.Appear
            }
        },
        {
            target: 'li.root li',
            transition:
            {
                type: MenuHighlightTransitions.BounceDown
            }
        }]
    });
 */


var DropNav = Class.create({
    initialize: function(options)
    {
        if (typeof(empty) != 'function')
            throw('DropNav.class.js :: Requires bootstrap.js.');
            
        this.options                      = empty(options)                                    ? {}                                        : options;
        this.selector                     = !empty(this.options.selector)                     ? this.options.selector                     : '.ulNav'; 
        this.fly_down_menu_class_name     = !empty(this.options.class_name)                   ? this.options.class_name                   : 'flyDownMenu';
        this.fly_up_menu_class_name       = !empty(this.options.fly_up_class_name)            ? this.options.fly_up_class_name            : 'flyUpMenu';
        this.click_menu_class_name        = !empty(this.options.click_menu_class_name)        ? this.options.click_menu_class_name        : 'clickMenu';
        this.click_menu_expand_class_name = !empty(this.options.click_menu_expand_class_name) ? this.options.click_menu_expand_class_name : 'clickMenu';
        this.delay                        = !empty(this.options.delay)                        ? this.options.delay                        : 250;
        this.iframe                       = !empty(this.options.iframe)                       ? this.options.iframe                       : true;
        this.parent_li_class_name         = !empty(this.options.parent_li_class_name)         ? this.options.parent_li_class_name         : 'branch';
        this.menuHighlights               = !empty(this.options.MenuHighlights)               ? this.options.MenuHighlights               : false;
        this.timers                       = []; //array of objects with 2 props: element + timer
        this.uls                          = $$('ul' + this.selector);
        this.t                            = 0;
        var dn                            = this;
        
        this.uls.each(function(ul)
        {
            lis = ul.select('li');
            if(this.menuHighlights)
            {
                this.menuHighlights.each(function(i)
                {                    
                    highlight = new MenuHighlight(ul.select(i.target), i);
                });
            }
            lis.each(function(li)
            {
                
                if(!empty(li.down('ul')))
                {
                    li.fly_up        = false;
                    li.has_offset    = false;
                    li.need_timeout  = false;
                    li.addClassName(this.parent_li_class_name);
                    
                    if (ul.hasClassName(this.click_menu_class_name)) // click deployment 
                    {
                        if(!li.hasClassName('bgIFrameCont'))
                        {
                            var a = li.down('a');
                            Event.observe(a, 'click', dn.clickmenu.bindAsEventListener(dn, a));
                        }
                    }
                    else // simple drop down (default)
                    {
                        li.timerID = dn.t++;
                        
                        // possible for menu to fly up
                        if (ul.hasClassName(dn.fly_up_menu_class_name))
                            li.fly_up = true;
                        
                        d_ul = li.down('ul');
                        
                        dn.addIFrame(d_ul); //Add an iframe to this menu
                        
                        if(li.fly_up)
                            d_ul.setStyle({top: (d_ul.offsetTop - d_ul.offsetHeight + "px")});
                        
                        li.need_timeout       = true;
                        dn.timers[li.timerID] = {
                            element:        li,
                            timer:          null
                        };
                        
                        //assign mouseover/out
                        Event.observe(li, 'mouseover', dn.flyMenuMouseOver.bindAsEventListener(dn, li));
                        Event.observe(li, 'mouseout', dn.flyMenuMouseOut.bindAsEventListener(dn, li));                    
                    }
                }                 
            }, dn);
        }, dn);
    }, // end init()
            
    /*
     * flyMenuMouseOver : handles the li mouseover functions of flyDown or flyUp menu
     *
     */
    flyMenuMouseOver: function(e) 
    {
        var li = arguments[1];
        var dn = this;
        
        //Remove the hover from adjacent lis when moving between menus
        li.adjacent('li.' + this.parent_li_class_name).each(function(node)
        {
            if(!empty(this.timers[node.timerID]) && !empty(this.timers[node.timerID].timer))
                this.removeHover(node.timerID);
        }, dn);
        
        if (li.hasClassName('hover') && !empty(this.timers[li.timerID].timer))
        {
            this.timers[li.timerID].timer.stop();
            this.timers[li.timerID].timer = null;
        }
        
        if (!li.hasClassName('hover'))
            li.addClassName('hover');
        
        // check for offscreen menu
        li.select('ul').each(function(ul)
        {
            var li_left   = parseInt(ul.offsetLeft, 10);
            var li_width  = parseInt(ul.offsetWidth, 10);
            var doc_width = parseInt(document.documentElement.offsetWidth, 10);
        
            if (li_left + li_width > doc_width)
            {
                var offside   = (li_left + li_width) - doc_width;
                li.has_offset = true;
                ul.setStyle({left: (li_left - offside - 20 + "px")});
            }
        }, li);
    }, // end flyMenuMouseover     
     
    /*
     * flyMenuMouseOut : handles the li mouseout functions of flyDown or flyUp menu
     *
     */
    flyMenuMouseOut: function()
    {
        var li      = arguments[1];
        var timerID = li.timerID;
        var delay   = (li.need_timeout) ? this.delay : 0;
         
        if (!empty(this.timers[timerID]) && !empty(this.timers[timerID].timer))
            this.timers[timerID].timer.stop();
            
        this.timers[timerID] =
        {
            element: li,
            timer:   new PeriodicalExecuter(this.removeHover.bind(this, timerID), delay / 1000)
        };        
    }, // end flyMenuMouseout       
        
    /*
     * removeHover : removes hover state from li
     * @param timerID    : Number - index in timers[]
     * 
     */
    removeHover: function(timerID)
    {
        var li = this.timers[timerID].element;
        this.timers[timerID].timer.stop();
        this.timers[timerID].timer = null;
        
        li.removeClassName('hover');
        
        if (li.has_offset) 
        {
            li.select('ul').each(function(ul)
            {
                ul.style.left = null;
                li.has_offset = false;
            }, li);
        }
    }, // end removeHover    
    
    /*
     * addIframe: Create a transparent Iframe, and shim it underneath the dropdown UL, to compensate for lack of z-index on windowed elements
     * @param el        : HTMLListItemElement
     * @param ul_node    : HTMLListElement
     */
    addIFrame: function(ul_node) 
    {
        if(this.iframe)
        {
            var frame  = new Element('iframe')            
                            .setStyle({
                               position: 'absolute',
                               zIndex:   '-1',
                               filter:   'alpha(opacity=0)',
                               opacity:  0,
                               height:   parseInt(ul_node.offsetHeight, 10) + 'px',
                               width:    parseInt(ul_node.offsetWidth, 10) + 'px',
                               top:      '0px',
                               left:     '0px'
                            });
            var new_li = new Element('li')
                            .setStyle({
                               borderWidth: '0px',
                               height:      '0px',
                               bottom:      '0px'
                            });
            new_li.insert({top: frame});
            ul_node.insert({top: new_li});
        }        
    }, // end addIFrame    
    
    /*
     * clickMenu : When the A within the menu LI is clicked, toggle expansion of parent LI
     *
     */
    clickMenu: function() 
    {
        var a  = arguments[1];
        var li = a.up();
        
        if (li.hasClassName("sfhide"))
            li.removeClassName(this.click_menu_expand_class_name);
        else
            li.addClassName(this.click_menu_expand_class_name);
    } // end clickMenu          
});
//-->
