// (C) Copyright 2020 Hewlett-Packard Enterprise Company, L.P.

define(['jquery'], function() {
    (function($) {
        // jQuery plugin definition
        
        // You can describe the control completely in HTML or
        // by passing in configuration options here, for example:
        // {label: 'Label', options:['Value 1', ...]}
        // or
        // {label: 'Label', options:['<a href="#/somewhere">Value 1</a>', ...]}
        $.fn.hpDropMenu = function(options) {
          
            var BODY = '#hp-body-div';
            var LABEL = '> label';
            var OPTIONS = '.hp-options';
            var OPTION = OPTIONS + ' li';
            var ACTIVE = 'hp-active';
            var DISABLED = 'hp-disabled';
            var SPACE = 32;
            var TAB = 9;
            var ESCAPE = 27;
            var ENTER = 13;
            var UP_ARROW = 38;
            var DOWN_ARROW = 40;

            function hpDropMenu(elem) {
              
                var container;
                
                function initialActive() {
                    if ($(OPTION + '.' + ACTIVE, container).length === 0) {
                        var first = $(OPTION, container).first();
                        first.addClass(ACTIVE);
                        return false;
                    } else {
                        return true;
                    }
                }
                
                function nextActive() {
                    if (initialActive()) {
                        var options = $(OPTION, container);
                        options.each(function (index, elem) {
                            if ($(elem).hasClass(ACTIVE)) {
                                if (options.length > (index + 1)) {
                                    $(elem).removeClass(ACTIVE);
                                    $(options[index+1]).addClass(ACTIVE);
                                }
                                return false;
                            }
                        });
                    }
                }
                
                function previousActive() {
                    if (initialActive()) {
                        var options = $(OPTION, container);
                        options.each(function (index, elem) {
                            if ($(elem).hasClass(ACTIVE)) {
                                if (index > 0) {
                                    $(elem).removeClass(ACTIVE);
                                    $(options[index-1]).addClass(ACTIVE);
                                }
                                return false;
                            }
                        });
                    }
                }
                
                function onKeypress(ev) {
                    var keyCode = (ev.which ? ev.which : ev.keyCode);
                    if (keyCode == ENTER) {
                        var anchor = $(OPTION + '.' + ACTIVE + ' a',
                            container);
                        deactivate();
                        // follow anchor, if any
                        if (anchor.length > 0) {
                            anchor.trigger('click');
                        }
                    } else if (keyCode == ESCAPE || keyCode == TAB) {
                        deactivate();
                    } else if (keyCode == DOWN_ARROW) {
                        nextActive();
                        ev.preventDefault();
                    } else if (keyCode == UP_ARROW) {
                        previousActive();
                        ev.preventDefault();
                    }
                }
                
                function deactivate() {
                    $(BODY).unbind('click', deactivate);
                    $(document).unbind('keydown', onKeypress);
                    $(OPTIONS, container).css({left: '', right: '', top: '', bottom: ''});
                    $(OPTION, container).removeClass(ACTIVE);
                    container.removeClass(ACTIVE);
                }
                
                function activate() {
                    var options = $(OPTIONS, container);
                    
                    container.addClass(ACTIVE);
                    
                    // tune the position of the options in case they aren't visible
                    var boundary = options.
                        parents('.hp-menu-boundary, body').first();
                    if ((options.offset().left + options.outerWidth()) >
                        (boundary.offset().left + boundary.innerWidth()) &&
                        options.offset().left > options.outerWidth()) {
                        
                        options.css({left: 'auto', right: '0px'});
                    }
                    
                    $(document).bind('keydown', onKeypress);
                    // avoid bouncing
                    setTimeout(function () {
                        $(BODY).bind('click', deactivate);
                    }, 50);
                }
                
                function onKeyUp(ev) {
                    var keyCode = (ev.which ? ev.which : ev.keyCode);
                    if (keyCode == SPACE) {
                        if (!container.hasClass(ACTIVE)) {
                            activate();
                        }
                    }
                }
                
                function build() {
                    container.addClass('hp-drop-menu').attr('tabindex', 0);
                    
                    // set up required DOM elements if they aren't already there.
                    
                    if ($(OPTIONS, container).length === 0) {
                        container.append('<ol class="hp-options"></div>');
                    }
                  
                    // populate with any supplied options
                    
                    if (options) {
                        if (options.hasOwnProperty('label')) {
                            if ($(LABEL, container).length === 0) {
                                container.prepend('<label></label>');
                            }
                            $(LABEL, container).text(options.label);
                        }
                    
                        if (options.hasOwnProperty('options')) {
                            $.each(options.options, function(index, value) {
                                $(OPTIONS, container).
                                  append($('<li>' + value + '</li>'));
                            });
                        }
                    }
                }

                function initialize() {
                    container = $(elem);
                    
                    build();
                    
                    container.removeClass(ACTIVE);
                    
                    container.bind('click', function () {
                        if (!container.hasClass(ACTIVE) && !container.hasClass(DISABLED)) {
                            activate();
                        }
                    });
                    container.bind('keyup', onKeyUp);
                }
                
                initialize();
            }
            
            // pluginify
            var ret;
            var instance = null;
            this.each(function() {
                var $elem = $(this);
                instance = new hpDropMenu($elem[0]);
                ret = ret ? ret.add($elem) : $elem;
            });
            return ret;
        };
    }(jQuery));
});
