
var Menubar = class {
    static #config;
    static #settings;
    static #animationShow;
    static #animationName;
    static #menubar;
    static #menubarVertical;
    static #toolbar;
    static #mainNavigation;
    static #mobileButton;
    static #mobileNavigation;
    static #actionButton;
    static #userPanel;
    static #accordion;
    static #collapseMenu;
    static #submenus;


    closePanel() {
        this.#closepanelOpened();
    }
    constructor(settings) {
        Menubar.#config = this.#configs();
        Menubar.#settings = { ...Menubar.#config.settings, ...settings };
        Menubar.#animationShow = Menubar.#settings.animation.show !== undefined ? Menubar.#settings.animation.show : Menubar.#config.settings.animation.show;
        Menubar.#animationName = Menubar.#settings.animation.name ? Menubar.#settings.animation.name : Menubar.#config.settings.animation.name;
        Menubar.#menubar = document.querySelector(Menubar.#config.selectors.menubar);
        Menubar.#menubarVertical = document.querySelector(Menubar.#config.selectors.menubarVertical);
        Menubar.#toolbar = document.querySelector(Menubar.#config.selectors.toolbar);
        Menubar.#mainNavigation = Menubar.#menubar.querySelector(Menubar.#config.selectors.mainNavigation);
        Menubar.#mobileButton = Menubar.#menubar.querySelector(Menubar.#config.selectors.mobileButton);
        Menubar.#mobileNavigation = Menubar.#menubar.querySelector(Menubar.#config.selectors.mobileNavigation);
        Menubar.#actionButton = document.querySelectorAll(Menubar.#config.selectors.actionButton);
        Menubar.#accordion = document.querySelectorAll(Menubar.#config.selectors.accordion);
        Menubar.#collapseMenu = Menubar.#menubar.querySelector(Menubar.#config.selectors.switchMenuPosition);
        Menubar.#submenus = Menubar.#menubar.querySelectorAll(Menubar.#config.selectors.submenu);

        // init
        this.#init();
    };

    /**
     * Método de configuração
     * @private
     * @returns {object} config
     */
    #configs() {
        const config = {
            selectors: {
                menubar: '.ae-menubar',
                menubarVertical: '.ae-menubar.menubar[aria-orientation="vertical"]',
                toolbar: '.ae-menubar [role="toolbar"]',
                mainNavigation: '.main-navigation',
                hasSubmenu: '[role="menuitem"][aria-haspopup="true"]',
                isActive: '[role="menuitem"][data-active="true"]',
                mobileButton: '.menu-mobile-control',
                mobileButtonIconControl: '#hamburger-icon-control',
                mobileNavigation: '.ae-menu-mobile',
                mobileNavigationOverlay: '#mobile-navigation-overlay',
                panels: '.panel',
                actionButton: '.action-button',
                userActionsMenu: '.section.actions',
                accordion: '.ae-menubar-accordion',
                switchMenuPosition: '#switch-menu-position',
                wrapperUser: '.wrapper-user',
                userButton: '.user.action-button',
                userMenu: '.user-menu',
                userInfo: '.user-info',
                userMenuContent: '.user-menu-content',
                submenu: '.submenu',
            },
            menubar: {
                loadingTime: 500
            },
            settings: {
                keepOpen: false,
                animation: {
                    show: true,
                    name: 'slide-left'
                },
                overlay: {
                    show: true,
                    bgColor: 'rgba(0,0,0,.55)'
                },
                panel: {
                    offset: 4, //pixels
                    animation: 'slide-right-top'
                }
            },
            layers: {
                layer_1: 'layer-900',
                layer_2: 'layer-800',
            },
            animation: {
                className: [
                    'slide-top-bouncy',
                    'slide-right-bouncy',
                    'slide-bottom-bouncy',
                    'slide-left-bouncy',
                    'slide-top',
                    'slide-right',
                    'slide-bottom',
                    'slide-left',
                    'reveal-opacity',
                    'reveal-blur'
                ],
                duration: 650,
            }
        }
        return config;
    }

    #init() {
        // inic. métodos
        // -----------------------------------
        if (Menubar.#menubar && Menubar.#menubar.classList.contains('menubar') && Menubar.#menubar.getAttribute('aria-orientation') === 'horizontal') {
            if (Menubar.#mainNavigation) {
                this.#responsiveObserver()
            } else if (Menubar.#mobileNavigation) {
                Menubar.#mobileButton.style.display = 'grid';
                Menubar.#mobileNavigation.style.top = `${Menubar.#menubar.getBoundingClientRect().height}px`;
                Menubar.#mobileNavigation.classList.add(Menubar.#config.layers.layer_1);
            }
        }

        if (Menubar.#menubar.getAttribute('aria-orientation') === 'horizontal') {
            this.#submenusCheckVisibilityInViewport()
        }

        if (Menubar.#mobileButton && Menubar.#mobileNavigation) {
            this.#mobileControl();

            document.addEventListener('click', () => {
                if (Menubar.#mobileButton.getAttribute('aria-pressed') === 'true') {
                    Menubar.#mobileButton.click();
                }
            });
        }

        if (Menubar.#accordion) {
            Menubar.#accordion.forEach(accordion => {
                this.#menubarAccordion(accordion);
            });
        }

        if (Menubar.#menubarVertical) {
            if (Menubar.#collapseMenu) {
                Menubar.#collapseMenu.addEventListener('click', () => {

                    if (Menubar.#collapseMenu.getAttribute('aria-checked') === 'false') {
                        Menubar.#collapseMenu.setAttribute('aria-checked', 'true');
                        Menubar.#collapseMenu.classList.remove('fa-expand');
                        Menubar.#collapseMenu.classList.add('fa-compress');
                    } else {
                        Menubar.#collapseMenu.setAttribute('aria-checked', 'false');
                        Menubar.#collapseMenu.classList.remove('fa-compress');
                        Menubar.#collapseMenu.classList.add('fa-expand');
                    }

                    if (Menubar.#menubarVertical.getAttribute('data-collapsible') === 'true') {
                        Menubar.#menubarVertical.setAttribute('data-collapsible', 'false');
                    } else {
                        Menubar.#menubarVertical.setAttribute('data-collapsible', 'true');
                    }

                    this.#collapsibleMenu();
                });
            }

            Menubar.#menubarVertical.addEventListener('mouseenter', () => {
                if (Menubar.#menubarVertical.classList.contains('collapsed')) {
                    this.#collapsibleMenu();
                }
            });
            Menubar.#menubarVertical.addEventListener('mouseleave', () => {
                if (Menubar.#menubarVertical.classList.contains('expanded')) {
                    this.#collapsibleMenu();
                }
            });

            if (Menubar.#menubarVertical.querySelector(Menubar.#config.selectors.wrapperUser)) {
                this.#userMenu();
            }
        }

        if (document.querySelectorAll(`${Menubar.#config.selectors.menubar} ${Menubar.#config.selectors.panels}`).length !== 0) {
            this.#panel();

            document.addEventListener('click', () => {
                const keepOpened = document.querySelector("[data-keep-open='true']");

                if (keepOpened.style.visibility === "hidden" || keepOpened.style.visibility === "") {
                    this.#closepanelOpened();
                }
            });
        }

        this.#close();

        // Configurações do objeto
        // -----------------------------------
        Object.preventExtensions(this);
    }

    /**
     * Controla a responsividade da barra de menu e de seus elementos
     * @private
     */
    #responsiveObserver() {
        const gridGap = window.getComputedStyle(Menubar.#menubar.firstElementChild).columnGap;
        const menubarSplit = document.querySelector('.ae-menubar.menubar.split');

        const mainNavigationControl = (visibility) => {
            if (visibility === 'show') {
                Menubar.#mobileButton.style.display = 'none';
                Menubar.#mainNavigation.style.display = 'flex';
                Menubar.#mainNavigation.classList.remove('hide');
                Menubar.#mainNavigation.removeAttribute('aria-hidden');
                Menubar.#mainNavigation.removeAttribute('aria-hidden');
            } else if (visibility === 'hide') {
                Menubar.#mobileButton.style.display = 'grid';
                Menubar.#mainNavigation.style.display = 'none';
                Menubar.#mainNavigation.classList.add('hide');
                Menubar.#mainNavigation.classList.remove('show');
                Menubar.#mainNavigation.setAttribute('aria-hidden', 'true');
            }
        }

        const responseMobile = () => {
            //oculta mainNavigation
            mainNavigationControl('hide');
        };

        setTimeout(() => {
            let menubarMinWidth = null;

            if (menubarSplit) {
                menubarMinWidth = Menubar.#mainNavigation.offsetWidth;
            } else {
                menubarMinWidth = sumElementsWidth(Array.from(Menubar.#menubar.children).splice(0, 2));
            }

            const mobileObserver = new ResizeObserver(entries => {
                entries.forEach(entry => {
                    if (entry.target.classList.contains((Menubar.#config.selectors.menubar).replace('.', ''))) {
                        if (menubarMinWidth > entry.borderBoxSize[0].inlineSize) {
                            responseMobile();
                        } else {
                            mainNavigationControl('show');
                            if (Menubar.#mobileNavigation && Menubar.#mobileButton.getAttribute('aria-pressed') === 'true') {
                                this.#mobileButtonControl();
                                this.#mobileNavigationControl();
                            }
                        }
                    }
                });
            });
            mobileObserver.observe(Menubar.#menubar);

            if (Menubar.#mobileNavigation) {
                Menubar.#mobileNavigation.style.top = `${Menubar.#menubar.getBoundingClientRect().height}px`;
                Menubar.#mobileNavigation.classList.add(Menubar.#config.layers.layer_1);
            }

        }, Menubar.#config.menubar.loadingTime);
    }

    /**
     * Controla o botão de disparo do menu mobile
     * @private
     */
    #mobileButtonControl() {
        const mobileButtonIconControl = Menubar.#mobileButton.querySelector(Menubar.#config.selectors.mobileButtonIconControl);
        let ariaPressed = Menubar.#mobileButton.getAttribute('aria-pressed');

        if (ariaPressed === 'true') {
            Menubar.#mobileButton.setAttribute('aria-pressed', 'false');
            mobileButtonIconControl.checked = false;

        } else {
            Menubar.#mobileButton.setAttribute('aria-pressed', 'true');
            mobileButtonIconControl.checked = true;
        }
    }

    /**
     * Controla a visibilidade e animação da navegação mobile
     * @private
     */
    #mobileNavigationControl() {
        const overlayShow = Menubar.#settings.overlay.show !== undefined ? Menubar.#settings.overlay.show : Menubar.#config.settings.overlay.show;

        const showMobile = () => {
            // props
            Menubar.#mobileNavigation.setAttribute('aria-hidden', 'false');
            Menubar.#mobileNavigation.setAttribute('data-show', 'true');
            if (!Menubar.#animationShow) {
                Menubar.#mobileNavigation.style.setProperty('display', 'block');
            }
            // adiciona overlay
            if (overlayShow) {
                document.body.appendChild(this.#createOverlay());
                Menubar.#mobileButton.classList.add(Menubar.#config.layers.layer_1);
            }
            // Fecha o painel aberto
            this.#closepanelOpened();
        }
        const hideMobile = () => {
            // props
            Menubar.#mobileNavigation.setAttribute('aria-hidden', 'true');
            Menubar.#mobileNavigation.setAttribute('data-show', 'false');
            if (!Menubar.#animationShow) {
                Menubar.#mobileNavigation.style.setProperty('display', 'none');
            }
            // remove overlay
            if (overlayShow) {
                this.#removeOverlay(document.getElementById(Menubar.#config.selectors.mobileNavigationOverlay));
            }
        }

        if (Menubar.#mobileNavigation.getAttribute('data-show') === 'false') {
            showMobile();
        }
        else {
            hideMobile();
        }

        // controle de animação
        if (Menubar.#animationShow) {
            this.#animationClassControl(Menubar.#mobileNavigation);
        }
    }

    /**
     * Controla o status do botão mobile, a exibição do menu mobile e configurações iniciais do menu
     * @private
     */
    #mobileControl() {
        if (Menubar.#mobileButton) {
            Menubar.#mobileButton.addEventListener('click', () => {
                event.preventDefault();
                event.stopImmediatePropagation();
                this.#mobileButtonControl();
                this.#mobileNavigationControl();
                this.#isActive();
            });
        }

        if (Menubar.#mobileNavigation) {
            const mainNavMobile = Menubar.#mobileNavigation.querySelector('.main-navigation-mobile');
            mainNavMobile.style.paddingBottom = `${parseInt(window.getComputedStyle(mainNavMobile).paddingBottom.replace('px', '')) + Menubar.#menubar.offsetHeight}px`;
        }
    }

    /**
     * Expande ou colapsa o submenu da navegação mobile
     * @private
     */
    #menubarAccordion(element) {
        if (element) {
            const hasSubmenu = element.querySelectorAll(Menubar.#config.selectors.hasSubmenu);
            let animExpandId = null;

            if (hasSubmenu) {
                hasSubmenu.forEach(menuitem => {
                    // Funcionalidades
                    // ----------------------------------------------
                    function toggle() {
                        const nestingSubmenuOpen = menuitem.nextElementSibling.querySelectorAll('.submenu.isOpen');
                        let start;

                        // accordion: animações
                        // -----------------------
                        const animExpand = (timestamp) => {
                            if (start === undefined) { start = timestamp };

                            const elapsed = timestamp - start;

                            if (menuitem.nextElementSibling.offsetHeight < menuitem.nextElementSibling.firstElementChild.offsetHeight) {
                                menuitem.nextElementSibling.style.height = `${menuitem.nextElementSibling.offsetHeight + Math.round(0.1 * elapsed)}px`;
                                menuitem.classList.add('animating');
                                animExpandId = requestAnimationFrame(animExpand);
                            }
                            // aplica altura flexível para comportar automaticamente a altura dos submenus aninhados (filhos)
                            if (menuitem.nextElementSibling.offsetHeight >= menuitem.nextElementSibling.firstElementChild.offsetHeight) {
                                menuitem.nextElementSibling.style.height = '100%';
                                menuitem.classList.remove('animating');
                            }
                        };
                        const animCollapse = (timestamp) => {
                            if (start === undefined) { start = timestamp };

                            const elapsed = timestamp - start;

                            if (menuitem.nextElementSibling.offsetHeight > 0) {
                                menuitem.nextElementSibling.style.height = `${menuitem.nextElementSibling.offsetHeight - Math.round(0.1 * elapsed)}px`;
                                menuitem.classList.add('animating');
                                requestAnimationFrame(animCollapse);
                            }
                            // verifica se o resultado da subtração é um número negativo e iguala altura a zero
                            if (Math.sign(menuitem.nextElementSibling.offsetHeight - Math.round(0.1 * elapsed)) === -1) {
                                menuitem.nextElementSibling.style.height = '0px';
                                menuitem.classList.remove('animating');
                            }
                        };
                        // -----------------------

                        // accordion: expande submenu
                        if (menuitem.nextElementSibling.offsetHeight === 0) {
                            requestAnimationFrame(animExpand);
                            menuitem.setAttribute('aria-expanded', 'true');
                            menuitem.nextElementSibling.firstElementChild.setAttribute('aria-hidden', 'false');
                        }
                        // accordion: colapsa submenu
                        else {
                            if (!Menubar.#settings.keepOpen) {
                                //fechar todos os submenus aninhados
                                let nestedMenuitems = menuitem.parentElement.querySelectorAll('[role="menuitem"][aria-haspopup="true"][aria-expanded="true"]');
                                nestedMenuitems = Array.from(nestedMenuitems);
                                for (let i = 1; i < nestedMenuitems.length; i++) {
                                    nestedMenuitems[i].click();
                                }
                            }
                            requestAnimationFrame(animCollapse);
                            menuitem.setAttribute('aria-expanded', 'false');
                            menuitem.nextElementSibling.firstElementChild.setAttribute('aria-hidden', 'true');
                        }
                        //submenu aninhado
                        if (menuitem.parentElement.parentElement.classList.contains('submenu')) {
                            const globalWrapper = menuitem.parentElement.parentElement.parentElement;

                            if (!menuitem.nextElementSibling.firstElementChild.classList.contains('isOpen')) {
                                menuitem.nextElementSibling.firstElementChild.classList.add('isOpen');
                            }
                            else {
                                menuitem.nextElementSibling.firstElementChild.classList.remove('isOpen');
                            }
                        }
                    }

                    // Eventos
                    // ----------------------------------------------
                    menuitem.addEventListener('click', () => {
                        event.stopPropagation();
                        toggle();
                    })
                })
            }
        }
    }

    /**
     * Verifica a visibilidade dos submenus em relação a viewport, e corrige sua posição horizontal
     */
    #submenusCheckVisibilityInViewport() {
        function isElementPartiallyInViewport(el) {
            const rect = el.getBoundingClientRect();

            return (
                (rect.left + rect.width) <= window.innerWidth
            );
        }

        function checkSubmenusVisibility() {
            Menubar.#submenus.forEach(submenu => {
                submenu.style.removeProperty("right");
                submenu.style.removeProperty("left");

                if (!isElementPartiallyInViewport(submenu)) {
                    submenu.style.setProperty("right", "calc(100% - 0.5em)");
                    submenu.style.setProperty("left", "auto");
                }
            });
        }

        const menuitens = document.querySelectorAll(".ae-menubar[aria-orientation='horizontal'] [role='menuitem']");

        menuitens.forEach(menuitem => {
            menuitem.addEventListener('mouseenter', checkSubmenusVisibility);
        })
    }

    /**
     * Fecha o elemento aberto ao apertar a tecla ESC (menubar e/ou painel)
     * @private
     */
    #close() {
        const closeAll = () => {
            // fecha o menu mobile
            if (Menubar.#mobileNavigation && Menubar.#mobileNavigation.getAttribute('data-show') === 'true') {
                Menubar.#mobileButton.click();
            }

            // fecha painel aberto
            this.#closepanelOpened();
        }

        window.addEventListener('keydown', () => {
            if (event.keyCode === 27) {
                closeAll();
            }
        });
    }

    /**
     * Fecha o painel aberto
     */
    #closepanelOpened() {
        const panelOpeneds = document.querySelectorAll(`${Menubar.#config.selectors.panels}[is-open]`);

        if (panelOpeneds) {
            panelOpeneds.forEach(panel => {
                const evtDispatch = new CustomEvent('panel-closed', {detail: {panel: panel}});
                document.querySelector(`[aria-owns="${panel.getAttribute('id')}"]`).click();
                document.dispatchEvent(evtDispatch);
            });
        }
    }

    /**
     * Configura e controla comportamentos padrões de painéis da toolbar
     * @private
     */
    #panel() {
        const panelAnimationName = Menubar.#settings.panel.animation;
        let panelCloseButton = null;

        const addClass = (panel) => {
            if (panel) {
                panel.classList.add(panelAnimationName);
            } else {
                event.target.classList.add(panelAnimationName);
            }
        }
        const removeClass = (panel) => {
            if (panel) {
                panel.classList.remove(panelAnimationName);
            } else {
                event.target.classList.remove(panelAnimationName);
            }
        }
        const startAnimation = (event) => {
            removeClass();
            event.target.removeEventListener('animationend', startAnimation);
        }
        const endAnimation = (event) => {
            removeClass();
            event.target.style.opacity = '0';
            event.target.style.visibility = 'hidden';
            event.target.removeEventListener('animationend', endAnimation);
        }
        const setPanelPosition = (panel, button) => {

            let offsetTop;

            if (document.querySelector('.ae-menubar.menubar[aria-orientation="horizontal"]')) {
                if (document.querySelector('.ae-menubar.menubar.split')) {
                    offsetTop = `${((parseInt(window.getComputedStyle(document.querySelector('.ae-menubar.menubar')).height.replace('px', ''))) / 2) + Menubar.#settings.panel.offset}px`
                } else {
                    offsetTop = `${(parseInt(window.getComputedStyle(document.querySelector('.ae-menubar.menubar')).height.replace('px', ''))) + Menubar.#settings.panel.offset}px`
                }
            } else {
                offsetTop = `${(parseInt(window.getComputedStyle(document.querySelector('.ae-menubar.toolbar')).height.replace('px', ''))) + Menubar.#settings.panel.offset}px`
            }

            panel.style.position = 'absolute';
            panel.style.top = offsetTop;

            // if (!Menubar.#menubar.classList.contains('is-rtl')) {
            if (document.querySelector('html').getAttribute('dir') != "RTL") {
                if (document.querySelector('.ae-menubar.toolbar')) {
                    panel.style.left = button.getBoundingClientRect().right - panel.offsetWidth - document.querySelector('.ae-menubar.toolbar').offsetLeft + 'px';
                }
                else if (document.querySelector('.ae-menubar.menubar .toolbar') || document.querySelector('.ae-menubar.menubar .user.action-button')) {
                    panel.style.left = button.getBoundingClientRect().right - panel.offsetWidth - document.querySelector('.ae-menubar.menubar').offsetLeft + 'px';
                }
            } else {
                if (document.querySelector('.ae-menubar.toolbar')) {
                    panel.style.left = button.getBoundingClientRect().right - button.offsetWidth - document.querySelector('.ae-menubar.toolbar').offsetLeft + 'px';
                }
                else if (document.querySelector('.ae-menubar.menubar .toolbar') || document.querySelector('.ae-menubar.menubar .user.action-button')) {
                    panel.style.left = button.getBoundingClientRect().right - button.offsetWidth - document.querySelector('.ae-menubar.menubar').offsetLeft + 'px';
                }
            }

        }

        // configurações iniciais dos painéis
        document.querySelectorAll(Menubar.#config.selectors.panels).forEach(panel => {
            const panelButton = document.querySelector(`[aria-owns="${panel.getAttribute('id')}"]`);
            panelCloseButton = panel.querySelector("[data-close]");

            // adiciona classe de animação na inicialização dos painéis
            if (panel && !panel.classList.contains(panelAnimationName)) {
                panel.style.setProperty('animation-direction', 'normal', 'important');
                addClass(panel, panelAnimationName);
                panel.addEventListener('animationend', startAnimation);
            }

            if (panel) {
                if (panelButton) {
                    // reposicionamento dinâmico
                    window.addEventListener('resize', () => {
                        setPanelPosition(panel, panelButton);
                    });
                    // reposicionamento no click
                    panelButton.addEventListener('click', () => {
                        setPanelPosition(panel, panelButton);
                    });
                }
            }
        });

        // controle de exibição
        Menubar.#actionButton.forEach(button => {
            button.addEventListener('click', () => {
                event.stopImmediatePropagation();

                const panelOpened = document.querySelector(`${Menubar.#config.selectors.panels}[is-open]`);
                let panel = button.getAttribute('aria-owns');
                panel = document.getElementById(panel);
                const evtDispatch = new CustomEvent('panel-oppened', {detail: {panel: panel}});

                if (panelOpened && panelOpened.getAttribute('id') !== panel.getAttribute('id')) {
                    const panelOwns = document.querySelector(`[aria-owns="${panelOpened.getAttribute('id')}"]`);
                    panelOwns.setAttribute('aria-expanded', 'false');
                    panelOpened.style.opacity = '0';
                    panelOpened.style.visibility = 'hidden';
                    panelOpened.removeAttribute('is-open');
                    panelOpened.setAttribute('aria-hidden', 'true');
                }

                try {
                    if (panel.hasAttribute('is-open')) {
                        panel.removeAttribute('is-open');
                        panel.setAttribute('aria-hidden', 'true');
                        panel.style.setProperty('animation-direction', 'reverse', 'important');
                        addClass(panel);
                        panel.addEventListener('animationend', endAnimation);
                        button.setAttribute('aria-expanded', 'false');

                    } else {
                        panel.setAttribute('is-open', 'true');
                        panel.style.opacity = '1';
                        panel.style.visibility = 'visible';
                        panel.setAttribute('aria-hidden', 'false');
                        panel.style.setProperty('animation-direction', 'normal', 'important');
                        addClass(panel)
                        panel.addEventListener('animationend', startAnimation);
                        button.setAttribute('aria-expanded', 'true');
                        // fecha o menu mobile
                        if (Menubar.#mobileNavigation && Menubar.#mobileNavigation.getAttribute('data-show') === 'true') {
                            Menubar.#mobileButton.click();
                        }
                    }
                } catch (err) {
                    console.debug('Este trigger não possui um painel associado!', err);
                }
                document.dispatchEvent(evtDispatch);


            })
        })

        // fecha o painel no botão data-close
        if (panelCloseButton) {
            panelCloseButton.addEventListener("click", ev => {
                // const ownButton = document.getElementById(ev.currentTarget.dataset.close);
                // ownButton.click();
                this.#closepanelOpened();
            });
        }
    }

    /**
     * Verifica se um item do menu tem o status ativo e realiza ações complementares
     * @private
     */
    #isActive() {
        const isActive = Menubar.#mobileNavigation.querySelectorAll(Menubar.#config.selectors.isActive);

        if (isActive) {
            isActive.forEach(menuitem => {
                if (!menuitem.getAttribute('href') && menuitem.getAttribute('aria-expanded') === 'false') {
                    menuitem.click();
                }
            })
        }
    }

    /**
     * Cria um overlay para impedir interações com os elementos abaixo deste
     * @private
     * @return { DOM Element} overlay
     */
    #createOverlay() {
        const overlay = document.createElement('div');

        overlay.style.position = 'fixed';
        overlay.style.top = '0';
        overlay.style.left = '0';
        overlay.style.width = '100%';
        overlay.style.height = '100%';
        overlay.style.backgroundColor = Menubar.#settings.overlay.bgColor ? Menubar.#settings.overlay.bgColor : Menubar.#config.settings.overlay.bgColor;
        overlay.classList.add('ae-overlay', Menubar.#config.layers.layer_2);
        overlay.setAttribute('id', Menubar.#config.selectors.mobileNavigationOverlay);

        return overlay;
    }

    /**
     * Remove uma overlay ativa
     * @param {DOM Element} overlay ['mobile-navigation' || 'main-navigation'] Informa ao método qual overlay remover.
     */
    #removeOverlay(target) {
        document.querySelector('body').removeChild(target);
    }

    /**
     * Controla a animação de entrada e saída do elemento
     * @param {DOM Element} element Elemento que receberá a classe de animação
     */
    #animationClassControl(element) {
        const startAnimation = () => {
            switch (Menubar.#animationName) {
                case 'slide-top-bouncy':
                    element.classList.add('slide-top-bouncy');
                    break;
                case 'slide-right-bouncy':
                    element.classList.add('slide-right-bouncy');
                    break;
                case 'slide-bottom-bouncy':
                    element.classList.add('slide-bottom-bouncy');
                    break;
                case 'slide-left-bouncy':
                    element.classList.add('slide-left-bouncy');
                    break;
                case 'slide-top':
                    element.classList.add('slide-top');
                    break;
                case 'slide-right':
                    element.classList.add('slide-right');
                    break;
                case 'slide-bottom':
                    element.classList.add('slide-bottom');
                    break;
                case 'slide-left':
                    element.classList.add('slide-left');
                    break;
                case 'reveal-opacity':
                    element.classList.add('reveal-opacity');
                    break;
                case 'reveal-blur':
                    element.classList.add('reveal-blur');
                    break;
            }

            Menubar.#mobileButton.style.setProperty('pointer-events', 'none');
            element.style.setProperty('display', 'block');
            element.addEventListener('animationend', endAnimation);
        }

        const endAnimation = () => {
            if (Menubar.#animationShow) {
                Menubar.#config.animation.className.forEach(className => {
                    if (element.classList.contains(className)) {
                        element.classList.remove(className);
                    }
                });

                element.style.setProperty('animation-direction', 'reverse', 'important');
                Menubar.#mobileButton.style.removeProperty('pointer-events');
                element.removeEventListener('animationend', endAnimation);
            }

            if (element.getAttribute('data-show') === 'false') {
                element.style.setProperty('display', 'none');

                if (Menubar.#animationShow) {
                    element.style.setProperty('animation-direction', 'normal', 'important');
                }
            }
        }


        if (Menubar.#animationShow) {
            startAnimation();
        }
    }

    /**
     * Controla a interação de visualização do menu vertical entre colapsada e extendida
     */
    #collapsibleMenu() {
        if (Menubar.#menubarVertical) {
            let logos = Menubar.#menubarVertical.querySelectorAll('.logo img');
            let menubarVert_width = Menubar.#menubarVertical.offsetWidth;
            const menuitems = Menubar.#menubarVertical.querySelectorAll('.wrapper-navigation [role="menuitem"]');
            const menuitems_labels = Menubar.#menubarVertical.querySelectorAll('.wrapper-navigation [role="menubar"] > .wrapper > [role="menuitem"] > .label');
            const navgroup_labels = Menubar.#menubarVertical.querySelectorAll('.wrapper-navigation [role="menubar"] .navigation-group > .label');
            const menuitems_opened = Menubar.#menubarVertical.querySelectorAll('.wrapper-navigation [role="menubar"] [role="menuitem"][aria-expanded="true"]');

            const wrapperUser = Menubar.#menubarVertical.querySelector(Menubar.#config.selectors.wrapperUser);
            let userMenu, userInfo, userInfoGroup, userButton;
            const wrapperHeader = Menubar.#menubarVertical.querySelector(".wrapper-header");

            if (wrapperUser) {
                userMenu = wrapperUser.querySelector(Menubar.#config.selectors.userMenu);
                userInfo = wrapperUser.querySelector(Menubar.#config.selectors.userInfo);
                userInfoGroup = wrapperUser.querySelector(`${Menubar.#config.selectors.userInfo} > .group`);
                userButton = wrapperUser.querySelector(Menubar.#config.selectors.userButton);
            }

            let start, previousTimestamp;

            const animate_expand = timestamp => {
                if (start === undefined) { start = timestamp };

                const menubarMaxWidth = parseInt(Menubar.#menubarVertical.getAttribute('data-width'));
                const menubarWidth = Menubar.#menubarVertical.offsetWidth;
                const elapsed = timestamp - start;

                if (previousTimestamp !== timestamp) {
                    const width = Math.min(menubarWidth + elapsed, menubarMaxWidth);
                    Menubar.#menubarVertical.style.width = `${width}px`;
                }

                if (menubarWidth !== menubarMaxWidth) {
                    requestAnimationFrame(animate_expand)
                } else {
                    Menubar.#menubarVertical.style.width = '260px';
                    Menubar.#menubarVertical.classList.add('expanded');
                }
            }

            const animate_collapse = timestamp => {
                if (start === undefined) { start = timestamp };

                const menubarWidth = Menubar.#menubarVertical.offsetWidth;
                const elapsed = timestamp - start;

                if (menubarWidth === menubarVert_width) {
                    Menubar.#menubarVertical.setAttribute('data-width', menubarWidth);
                }

                if (previousTimestamp !== timestamp) {
                    const width = Math.max(menubarWidth - elapsed, 80);
                    Menubar.#menubarVertical.style.width = `${width}px`;
                    Menubar.#menubarVertical.style.minWidth = `${width}px`;
                }

                if (menubarWidth !== 80) {
                    requestAnimationFrame(animate_collapse)
                } else if (menubarWidth === 80) {
                    Menubar.#menubarVertical.classList.add('collapsed');
                }
            }

            const handler_collapse = () => {
                requestAnimationFrame(animate_collapse);

                Menubar.#menubarVertical.classList.remove('expanded');
                Menubar.#collapseMenu.classList.add('d-none');

                wrapperHeader.style.setProperty("justify-content", "center");

                logos[0].classList.add('d-none');
                logos[0].classList.remove('d-block');
                logos[1].classList.add('d-block');
                logos[1].classList.remove('d-none');

                let checkWrapperUserAnimating = null;
                const checkWrapperUserClassAnimating = () => {
                    if (wrapperUser && !wrapperUser.classList.contains('animating')) {
                        clearInterval(checkWrapperUserAnimating);

                        wrapperUser.style.display = 'flex';
                        wrapperUser.style.flexFlow = 'row nowrap';
                        wrapperUser.style.justifyContent = 'center';
                        userMenu.classList.add('d-none');
                        userInfoGroup.classList.add('d-none');
                        userInfo.setAttribute('data-expanded', userInfo.getAttribute('aria-expanded'));
                        userInfo.removeAttribute('aria-expanded');
                    }
                }

                if (wrapperUser) {
                    checkWrapperUserAnimating = setInterval(checkWrapperUserClassAnimating, 50);
                }

                let checkMenuitemAnimation = null;
                const checkMenuitemClassAnimation = () => {
                    menuitems.forEach(menuitem => {
                        if (!menuitem.classList.contains('animating')) {
                            clearInterval(checkMenuitemAnimation);

                            menuitems_opened.forEach(menuitem => {
                                menuitem.nextElementSibling.classList.add('d-none');
                            });

                            menuitems_labels.forEach(label => {
                                label.classList.add('d-none');
                                label.parentElement.style.justifyContent = 'center';
                            });

                            navgroup_labels.forEach(label => {
                                label.classList.add('d-none');
                                label.previousElementSibling.classList.remove('d-none');
                                label.parentElement.style.justifyContent = 'center';
                            });
                        }
                    })
                }

                checkMenuitemAnimation = setInterval(checkMenuitemClassAnimation, 50);
            }

            const handler_expand = () => {
                requestAnimationFrame(animate_expand);

                Menubar.#menubarVertical.classList.remove('collapsed');
                Menubar.#collapseMenu.classList.remove('d-none');

                wrapperHeader.style.removeProperty("justify-content");

                logos[1].classList.add('d-none');
                logos[1].classList.remove('d-block');
                logos[0].classList.add('d-block');
                logos[0].classList.remove('d-none');

                let checkWrapperUserAnimating = null;
                const checkWrapperUserClassAnimating = () => {
                    if (wrapperUser && !wrapperUser.classList.contains('animating')) {
                        clearInterval(checkWrapperUserAnimating);

                        wrapperUser.style.display = 'block';
                        wrapperUser.style.flexFlow = '';
                        wrapperUser.style.justifyContent = '';
                        userMenu.classList.remove('d-none');
                        userInfoGroup.classList.remove('d-none');
                        userInfo.setAttribute('aria-expanded', userInfo.getAttribute('data-expanded'));
                        userInfo.removeAttribute('data-expanded');
                    }
                }

                if (wrapperUser) {
                    checkWrapperUserAnimating = setInterval(checkWrapperUserClassAnimating, 50);
                }

                let checkMenuitemAnimation = null;
                const checkMenuitemClassAnimation = () => {
                    menuitems.forEach(menuitem => {
                        if (!menuitem.classList.contains('animating')) {
                            clearInterval(checkMenuitemAnimation);

                            menuitems_opened.forEach(menuitem => {
                                menuitem.nextElementSibling.classList.remove('d-none');
                            });

                            menuitems_labels.forEach(label => {
                                label.classList.remove('d-none');
                                label.parentElement.style.justifyContent = 'flex-start';
                            });

                            navgroup_labels.forEach(label => {
                                label.classList.remove('d-none');
                                label.previousElementSibling.classList.add('d-none');
                                label.parentElement.style.justifyContent = 'flex-start';
                            });
                        }
                    })
                }

                checkMenuitemAnimation = setInterval(checkMenuitemClassAnimation, 50);
            }

            if (Menubar.#menubarVertical.getAttribute('data-collapsible') === 'true') {
                if (!Menubar.#menubarVertical.classList.contains('collapsed')) {
                    handler_collapse();
                } else {
                    handler_expand();
                }
            }

        }
    }

    /**
     * Controla o menu do usuário da menubar vertical
     */
    #userMenu() {
        const wrapperUser = Menubar.#menubarVertical.querySelector(Menubar.#config.selectors.wrapperUser);
        const userInfo = wrapperUser.querySelector(Menubar.#config.selectors.userInfo)

        if (wrapperUser) {
            userInfo.addEventListener('click', () => {
                const expanded = userInfo.getAttribute('aria-expanded');
                const userMenu = wrapperUser.querySelector(Menubar.#config.selectors.userMenu);
                const userMenuWrapper = wrapperUser.querySelector(`${Menubar.#config.selectors.userMenu} > .wrapper`);
                const userMenuContentHeight = wrapperUser.querySelector(Menubar.#config.selectors.userMenuContent).offsetHeight;
                let start;

                const animExpand = timestamp => {
                    if (start === undefined) { start = timestamp };

                    const elapsed = timestamp - start;

                    if (userMenuWrapper.offsetHeight < userMenuContentHeight) {
                        userMenuWrapper.style.height = `${Math.min(userMenuWrapper.offsetHeight + (0.1 * elapsed), userMenuContentHeight)}px`;
                        wrapperUser.classList.add('animating');
                        requestAnimationFrame(animExpand);
                    } else {
                        userInfo.setAttribute('aria-expanded', 'true');
                        userMenuWrapper.style.height = 'fit-content';
                        wrapperUser.classList.remove('animating');
                    }
                }

                const animCollapse = timestamp => {
                    if (start === undefined) { start = timestamp };

                    const elapsed = timestamp - start;

                    if (userMenuWrapper.offsetHeight !== 0) {
                        userMenuWrapper.style.height = `${Math.max(userMenuWrapper.offsetHeight - (0.1 * elapsed), 0)}px`;
                        wrapperUser.classList.add('animating');
                        requestAnimationFrame(animCollapse);
                    } else {
                        userInfo.setAttribute('aria-expanded', 'false');
                        userMenu.classList.remove('m-top-4');
                        wrapperUser.classList.remove('animating');
                    }
                }

                if (expanded === 'false') {
                    requestAnimationFrame(animExpand);
                    userMenu.classList.add('m-top-4');
                } else {
                    requestAnimationFrame(animCollapse);
                }
            })
        }
    }
}

// Funções auxiliares
// ----------------------------------------------------------
function sumElementsWidth(nodeElements) {
    let width = 0;
    if (nodeElements) {
        nodeElements.forEach(element => {
            width += element.offsetWidth;
        });
        return width;
    }
}