Drupal.behaviors.siteLayout = {
  attach(context) {
    const HTML = document.documentElement;

    const MENU_TOGGLE = context.querySelector('[data-js="menu-toggle"]');
    if (!MENU_TOGGLE) return;

    const SITE_HEADER = context.querySelector('[data-js="site-header"]');
    if (!SITE_HEADER) return;

    const SITE_HEADER_CONTENT = SITE_HEADER.querySelector('.site-header__content');
    if (!SITE_HEADER_CONTENT) return;

    const SITE_HEADER_MENU_CONTENT = SITE_HEADER.querySelector('.site-header__menu-content');
    if (!SITE_HEADER_MENU_CONTENT) return;

    const FOCUSABLE_SELECTORS = `
      a[href]:not([disabled]),
      button:not([disabled]),
      [tabindex]:not([tabindex="-1"])
    `;

    let focusableHeaderElements = [...SITE_HEADER_CONTENT.querySelectorAll(FOCUSABLE_SELECTORS)];
    let focusableMenuElements = [...SITE_HEADER_MENU_CONTENT.querySelectorAll(FOCUSABLE_SELECTORS)];

    let focusableElements = [...focusableHeaderElements, ...focusableMenuElements];
    let firstFocusableElement = focusableElements[0];
    let lastFocusableElement = focusableElements[focusableElements.length - 1];

    const closeMenu = () => {
      document.removeEventListener('keydown', handleKeyDown);
      window.dispatchEvent(new CustomEvent('main-menu:animate-out:start'));
      window.addEventListener('main-menu:animate-out:complete', handleMainMenuAnimateOutComplete);
    }

    const openMenu = () => {
      MENU_TOGGLE.setAttribute('aria-expanded', true);

      SITE_HEADER.setAttribute('data-menu-opened', true);
      SITE_HEADER_MENU_CONTENT.addEventListener('transitionend', handleSiteHeaderMenuContentTransitionEnd);

      window.addEventListener('main-menu:animate-in:complete', handleMainMenuAnimateInComplete);
    }

    MENU_TOGGLE.addEventListener('click', () => {
      // Prevent the toggle button from trigger multiple open / close events.
      MENU_TOGGLE.setAttribute('disabled', true);

      // Open the menu.
      if (MENU_TOGGLE.getAttribute('aria-expanded') === 'false') {
        openMenu();
      }
      // Close the menu.
      else {
        closeMenu();
      }
    });

    /**
     * Handles the completion of the main menu animate-in sequence.
     * Re-enables the menu toggle button and cleans up event listeners.
     */
    const handleMainMenuAnimateInComplete = () => {
      MENU_TOGGLE.removeAttribute('disabled');

      document.addEventListener('keydown', handleKeyDown);
      window.removeEventListener('main-menu:animate-in:complete', handleMainMenuAnimateInComplete);

      focusableMenuElements[0].focus();
    }

    /**
     * Handles the completion of the main menu animate-out sequence.
     * Resets menu state, updates ARIA attributes, and cleans up event listeners.
     */
    const handleMainMenuAnimateOutComplete = () => {
      HTML.style.overflow = 'auto';

      MENU_TOGGLE.removeAttribute('disabled');
      MENU_TOGGLE.setAttribute('aria-expanded', false);

      SITE_HEADER.removeAttribute('data-menu-opened');

      window.removeEventListener('main-menu:animate-out:complete', handleMainMenuAnimateOutComplete);

      document.activeElement = MENU_TOGGLE;
    }

    /**
     * Handles the CSS transition end event for the site header menu content.
     * Triggers the main menu animation start when the transform transition
     * completes and cleans up event listeners.
     *
     * @param {TransitionEvent} event
     * @listens transitionend
     * @fires main-menu:animate-in:start
     */
    const handleSiteHeaderMenuContentTransitionEnd = (event) => {
      if (event.propertyName === 'transform') {
        HTML.style.overflow = 'hidden';

        window.dispatchEvent(new CustomEvent('main-menu:animate-in:start'));

        SITE_HEADER_MENU_CONTENT.removeEventListener('transitionend', handleSiteHeaderMenuContentTransitionEnd);
      }
    }

    /**
     *
     * @param {KeyboardEvent} event
     */
    const handleKeyDown = (event) => {
      switch (event.key) {
        case 'Escape':
          closeMenu();
          break;

        case 'Tab':
          if (focusableElements.length === 0) {
            event.preventDefault();
            return;
          }

          if (event.shiftKey) {
            if (document.activeElement === firstFocusableElement) {
              lastFocusableElement.focus();
              event.preventDefault();
            }
          }
          else if (document.activeElement === lastFocusableElement) {
            firstFocusableElement.focus();
            event.preventDefault();
          }
          break;
      }
    }
  }
}
