/**
 * Copyright (c) 2017-present, Facebook, Inc.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */

/* eslint-disable prefer-arrow-callback */
(function scrollSpy() {
  const OFFSET = 10;
  let timer;
  let headingsCache;
  const findHeadings = function findHeadings() {
    return headingsCache || document.querySelectorAll('.toc-headings > li > a');
  };
  const onScroll = function onScroll() {
    if (timer) {
      // throttle
      return;
    }
    timer = setTimeout(function() {
      timer = null;
      let activeNavFound = false;
      const headings = findHeadings(); // toc nav anchors
      /**
       * On every call, try to find header right after  <-- next header
       * the one whose content is on the current screen <-- highlight this
       */
      for (let i = 0; i < headings.length; i++) {
        // headings[i] is current element
        // if an element is already active, then current element is not active
        // if no element is already active, then current element is active
        let currNavActive = !activeNavFound;
        /**
         * Enter the following check up only when an active nav header is not yet found
         * Then, check the bounding rectangle of the next header
         * The headers that are scrolled passed will have negative bounding rect top
         * So the first one with positive bounding rect top will be the nearest next header
         */
        if (currNavActive && i < headings.length - 1) {
          const heading = headings[i + 1];
          const next = decodeURIComponent(heading.href.split('#')[1]);
          const nextHeader = document.getElementById(next);

          if (nextHeader) {
            const top = nextHeader.getBoundingClientRect().top;
            currNavActive = top > OFFSET;
          } else {
            console.error('Can not find header element', {
              id: next,
              heading,
            });
          }
        }
        /**
         * Stop searching once a first such header is found,
         * this makes sure the highlighted header is the most current one
         */
        if (currNavActive) {
          activeNavFound = true;
          headings[i].classList.add('active');
        } else {
          headings[i].classList.remove('active');
        }
      }
    }, 100);
  };

  document.addEventListener('scroll', onScroll);
  document.addEventListener('resize', onScroll);
  document.addEventListener('DOMContentLoaded', function() {
    // Cache the headings once the page has fully loaded.
    headingsCache = findHeadings();
    onScroll();
  });
})();
