'use strict';

{
  function setupTheme() {
    const kCustomPreference = 'customDarkTheme';
    const userSettings = sessionStorage.getItem(kCustomPreference);
    const themeToggleButton = document.getElementById('theme-toggle-btn');

    if (userSettings === null && window.matchMedia) {
      const mq = window.matchMedia('(prefers-color-scheme: dark)');

      if ('onchange' in mq) {
        function mqChangeListener(e) {
          document.documentElement.classList.toggle('dark-mode', e.matches);
        }
        mq.addEventListener('change', mqChangeListener);
        if (themeToggleButton) {
          themeToggleButton.addEventListener(
            'click',
            function() {
              mq.removeEventListener('change', mqChangeListener);
            },
            { once: true }
          );
        }
      }

      if (mq.matches) {
        document.documentElement.classList.add('dark-mode');
      }
    } else if (userSettings === 'true') {
      document.documentElement.classList.add('dark-mode');
    }

    if (themeToggleButton) {
      themeToggleButton.hidden = false;
      themeToggleButton.addEventListener('click', function() {
        sessionStorage.setItem(
          kCustomPreference,
          document.documentElement.classList.toggle('dark-mode')
        );
      });
    }
  }

  function setupPickers() {
    function closeAllPickers() {
      for (const picker of pickers) {
        picker.parentNode.classList.remove('expanded');
      }

      window.removeEventListener('click', closeAllPickers);
      window.removeEventListener('keydown', onKeyDown);
    }

    function onKeyDown(e) {
      if (e.key === 'Escape') {
        closeAllPickers();
      }
    }

    const pickers = document.querySelectorAll('.picker-header > a');

    for (const picker of pickers) {
      const parentNode = picker.parentNode;

      picker.addEventListener('click', function(e) {
        e.preventDefault();

        /*
          closeAllPickers as window event trigger already closed all the pickers,
          if it already closed there is nothing else to do here
        */
        if (parentNode.classList.contains('expanded')) {
          return;
        }

        /*
          In the next frame reopen the picker if needed and also setup events
          to close pickers if needed.
        */

        requestAnimationFrame(function() {
          parentNode.classList.add('expanded');
          window.addEventListener('click', closeAllPickers);
          window.addEventListener('keydown', onKeyDown);
        });
      });
    }
  }

  function setupStickyHeaders() {
    const header = document.querySelector('.header');
    let ignoreNextIntersection = false;

    new IntersectionObserver(
      function(e) {
        const currentStatus = header.classList.contains('is-pinned');
        const newStatus = e[0].intersectionRatio < 1;

        // Same status, do nothing
        if (currentStatus === newStatus) {
          return;
        } else if (ignoreNextIntersection) {
          ignoreNextIntersection = false;
          return;
        }

        /*
          To avoid flickering, ignore the next changes event that is triggered
          as the visible elements in the header change once we pin it.

          The timer is reset anyway after few milliseconds.
        */
        ignoreNextIntersection = true;
        setTimeout(function() {
          ignoreNextIntersection = false;
        }, 50);

        header.classList.toggle('is-pinned', newStatus);
      },
      { threshold: [1] }
    ).observe(header);
  }

  function setupAltDocsLink() {
    const linkWrapper = document.getElementById('alt-docs');

    function updateHashes() {
      for (const link of linkWrapper.querySelectorAll('a')) {
        link.hash = location.hash;
      }
    }

    addEventListener('hashchange', updateHashes);
    updateHashes();
  }

  function bootstrap() {
    // Check if we have JavaScript support.
    document.documentElement.classList.add('has-js');

    // Restore user mode preferences.
    setupTheme();

    // Handle pickers with click/taps rather than hovers.
    setupPickers();

    // Track when the header is in sticky position.
    setupStickyHeaders();

    // Make link to other versions of the doc open to the same hash target (if it exists).
    setupAltDocsLink();
  }

  if (document.readyState === 'loading') {
    document.addEventListener('DOMContentLoaded', bootstrap, { once: true });
  } else {
    bootstrap();
  }
}
