---
import { type MarkdownHeading } from "astro";

import { type Frontmatter, type KnownLanguageCode } from "../../config";
import { getIsRtlFromLangCode } from "../../languages";
import OnThisPageLinks from "../navigation/OnThisPageLinks";
import BreadCrumbs from "./breadCrumbs";
import OutdatedDocsBanner from "./outdatedDocsBanner.astro";
import Pagination from "./pagination.astro";

export interface Props {
  frontmatter: Frontmatter;
  path: string;
  headings: MarkdownHeading[];
}

const { frontmatter, path, headings } = Astro.props;
const title = frontmatter.title;

const [_1, _2, lang] = path.split("/");
const isRtl = getIsRtlFromLangCode((lang || "en") as KnownLanguageCode);
---

<article id="article" class="flex w-full max-w-screen-lg flex-col">
  {lang && lang !== "en" && <OutdatedDocsBanner path={path} />}
  <div class="mb-4 h-8">
    <BreadCrumbs client:only />
  </div>
  <OnThisPageLinks
    client:media="(max-width: 1024px)"
    headings={headings}
    title={title}
    isRtl={isRtl}
  />
  <section class="w-full">
    <h1
      id="overview"
      class="mb-4 px-4 text-3xl font-extrabold dark:text-t3-purple-100"
    >
      <a
        href="#overview"
        class="heading-link heading-link--hidden---effects"
        data-heading-link
      >
        {title}
      </a>
    </h1>
    <article class="markdown w-full">
      <slot />
    </article>
  </section>
</article>
<Pagination />
<script>
  const copySVG = `<svg width="1.3em" height="1.3em" viewBox="0 0 256 256"><path fill="currentColor" d="M216 36H88a4 4 0 0 0-4 4v44H40a4 4 0 0 0-4 4v128a4 4 0 0 0 4 4h128a4 4 0 0 0 4-4v-44h44a4 4 0 0 0 4-4V40a4 4 0 0 0-4-4Zm-52 176H44V92h120Zm48-48h-40V88a4 4 0 0 0-4-4H92V44h120Z"/></svg>`;

  let titles = document.querySelectorAll(
    ".remark-code-title",
  ) as NodeListOf<HTMLDivElement>;
  titles.forEach((title) => {
    title.dir = "ltr";
  });

  let blocks = document.querySelectorAll("pre");
  blocks.forEach((block) => {
    block.className = "relative flex w-full h-full";
    block.dir = "ltr";

    let copyButton = document.createElement("button");
    copyButton.className =
      "inline-flex absolute right-[.45em] top-[.5em] bg-zinc-100/20 rounded px-1 py-1 text-sm text-zinc-50 hover:bg-zinc-100/25 focus:outline-none focus:shadow-outline text-brand-primary";
    copyButton.innerHTML = copySVG;
    copyButton.addEventListener("click", () => {
      let text = "";
      const pre = copyButton.parentElement;
      let code = pre?.querySelector("code");
      if (code) {
        text = code.innerText;
      } else {
        const span = pre?.querySelector("span");
        if (span) {
          text = span.innerText;
        }
      }
      if (text) {
        try {
          navigator.clipboard.writeText(text);
        } catch (err) {
          console.error("Failed to copy: ", err);
        }
        copyButton.innerHTML = `<svg width="1.3em" height="1.3em" viewBox="0 0 256 256"><path fill="#22c55e" d="M104 192a8.5 8.5 0 0 1-5.7-2.3l-56-56a8.1 8.1 0 0 1 11.4-11.4l50.3 50.4L210.3 66.3a8.1 8.1 0 0 1 11.4 11.4l-112 112a8.5 8.5 0 0 1-5.7 2.3Z"/></svg>`;

        setTimeout(() => {
          copyButton.innerHTML = copySVG;
        }, 1000);
      }
    });

    block.appendChild(copyButton);
    block.setAttribute("tabindex", "0");
  });
</script>
<script is:inline>
  //FIXME: We can make this properly typed later
  /**
   * Allows us to animate the details element
   * for it to work make sure the details element contains a summary element
   * and a div element with the class of content
   * @param {*} element the details element which we wish to animate
   */
  const AnimateDetails = (element) => {
    const summary = element.querySelector("summary");
    const content = element.querySelector(".content");
    let props = { animation: null, isClosing: false, isExpanding: false };

    /**
     * onClick event handler for the summary element
     * @param {*} event the event object
     */
    const onClick = (event) => {
      event.preventDefault();

      element.style.overflow = "hidden";

      if (props.isClosing || !element.open) open();
      else if (props.isExpanded || element.open) close();
    };

    /**
     * Closes the details element
     * This function is in charge of animating the closing of the
     * details element
     */
    const close = () => {
      props.isClosing = true;

      const startHeight = `${element.offsetHeight}px`;
      const endHeight = `${summary.offsetHeight}px`;

      if (props.animation) props.animation.cancel();

      props.animation = element.animate(
        {
          height: [startHeight, endHeight],
        },
        {
          duration: 300,
          easing: "ease-in-out",
        },
      );

      props.animation.onfinish = () => onAnimationFinish(false);
      props.animation.oncancel = () => (props.isClosing = false);
    };

    /**
     * Opens the details element
     * requests the animation frame to animate the opening of the details element
     */
    const open = () => {
      element.style.height = `${summary.offsetHeight}px`;
      element.open = true;
      window.requestAnimationFrame(() => expand());
    };

    /**
     * Expands the details element
     * This function is in charge of animating the expansion of the
     * details element
     */
    const expand = () => {
      props.isExpanding = true;

      const startHeight = `${element.offsetHeight}px`;
      const endHeight = `${content.offsetHeight + summary.offsetHeight}px`;

      if (props.animation) props.animation.cancel();

      props.animation = element.animate(
        {
          height: [startHeight, endHeight],
        },
        {
          duration: 300,
          easing: "ease-in-out",
        },
      );

      props.animation.onfinish = () => onAnimationFinish(true);
      props.animation.oncancel = () => (props.isExpanding = false);
    };

    /**
     * Called when the animation is finished
     * @param {*} open whether the details element is open or not
     */
    const onAnimationFinish = (open) => {
      element.open = open;
      props.animation = null;
      props.isClosing = false;
      props.isExpanding = false;

      element.style.height = element.style.overflow = "";
    };

    /**
     * Adds our new event listener to the summary element
     */
    summary.addEventListener("click", (event) => onClick(event));
  };

  /**
   * Allows us to animate all the details elements on the page
   * Will check if the details element contains a div element with the class of content
   */
  const viableDetails = document.querySelectorAll("details");
  viableDetails.forEach((element) => {
    if (element.querySelector(".content")) {
      AnimateDetails(element);
    }
  });
</script>
<script>
  const main = () => {
    const codeElements = Array.from(document.querySelectorAll("code")).filter(
      (codeElement) => codeElement.parentNode?.nodeName !== "PRE",
    );

    codeElements.forEach((codeElement) => {
      const codeWrapper = document.createElement("div");
      codeWrapper.classList.add("code-wrapper");
      codeElement.parentNode?.insertBefore(codeWrapper, codeElement);

      codeWrapper.appendChild(codeElement);
    });
  };
  main();
</script>
