import * as React from "react";

function removeFirstHash(str: string): string {
  return str.replace(/^#/, "");
}

/**
 * React hook to highlight a heading a user is currently reading.
 * @param headingList List of links to the headings (ex. "#title")
 * @param options Options for the Intersectionobserver (ex. rootMargin)
 * @returns The Id/Link to the heading, that is currently active.
 */
export function useActiveHeading(headingList: string[], options?: IntersectionObserverInit) {
  const [activeId, setActiveId] = React.useState("");

  React.useEffect(() => {
    const callback: IntersectionObserverCallback = (headingEntries) => {
      // Get all headings that are currently visible on the page
      const visibleHeadings = headingEntries.filter((e) => e.isIntersecting);

      if (visibleHeadings.length === 0) {
        //Necessary if a user scrolls down and then reloads.
        //In that case the IntersectionObserver didn't see the Heading onscreen
        const element = headingEntries.reverse().find((e) => e.boundingClientRect.bottom < 150);
        if (element) {
          setActiveId(`#${element.target.id}`);
        }
      } else {
        // If there is more than one visible heading,
        // choose the one that is closest to the top of the page
        // the entries are always sorted top to bottom.
        setActiveId(`#${visibleHeadings[0].target.id}`);
      }
    };

    const observer = new IntersectionObserver(callback, options);

    //Observe all (non-null) elements
    headingList
      .map((heading) => document?.querySelector(`[id='${removeFirstHash(heading)}']`))
      //Remove null elments
      .flatMap((f) => (f ? [f] : []))
      .forEach((element) => observer.observe(element));

    return () => observer.disconnect();
  }, [headingList, options]);
  return activeId;
}
