---
import PageLayout from "../../layouts/PageLayout.astro";
import { getCollection } from "astro:content";
import Date from "../../components/Date.astro";
const allArticles = await getCollection("blog");
const sortedArticles = allArticles.sort((a, b) => {
  return b.data.pubDate.valueOf() - a.data.pubDate.valueOf();
});
---

<PageLayout
  title="Blog"
  description="Friendly technical articles with a focus on web and GNU/Linux topics."
>
  <form class="flex flex-wrap gap-2">
    <label for="article-search">Search for an article:</label>
    <input
      type="text"
      id="article-search"
      class="border border-neutral-300 px-2 dark:border-neutral-600"
    />
  </form>
  {
    sortedArticles.map(({ id, data: { title, pubDate, description } }) => (
      <article
        class="mt-8 flex flex-col gap-2"
        data-article-title={title}
        data-article-description={description}
      >
        <Date date={pubDate} />
        <a
          class="max-w-fit text-blue-800 hover:no-underline active:bg-neutral-200 active:dark:bg-neutral-700"
          href={`/blog/${id}`}
        >
          <span id="article-title">{title}</span>
        </a>
        <p id="article-description" class="not-prose">
          {description}
        </p>
      </article>
    ))
  }
  <p id="no-results" class="mt-8 hidden italic">
    No articles found matching your search.
  </p>
</PageLayout>
<script>
  const setupSearch = () => {
    const searchInput = document.querySelector('input[id="article-search"]');
    const articles = document.querySelectorAll("[data-article-title]");
    const noResults = document.querySelector("#no-results");
    if (!searchInput || !articles.length || !noResults) return;

    const escapeRegex = (str: string) => {
      return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
    };

    const highlightText = (text: string, searchTerms: string[]) => {
      if (!searchTerms.length || searchTerms.every((term) => !term)) {
        return text;
      }

      let highlightedText = text;
      for (const term of searchTerms) {
        if (term) {
          const regex = new RegExp(`(${escapeRegex(term)})`, "gi");
          highlightedText = highlightedText.replace(regex, "<mark>$1</mark>");
        }
      }
      return highlightedText;
    };

    searchInput.addEventListener("input", (e) => {
      const target = e.target as HTMLInputElement;
      const searchValue = target.value.trim().replace(/\s+/g, " ");
      const searchTerms = searchValue
        .toLowerCase()
        .split(" ")
        .filter((term) => term);
      let hasResults = false;

      for (const article of articles) {
        const originalTitle = article.getAttribute("data-article-title") ?? "";
        const originalDescription =
          article.getAttribute("data-article-description") ?? "";
        const titleElement = article.querySelector("#article-title");
        const descriptionElement = article.querySelector(
          "#article-description",
        );

        if (!searchValue) {
          if (titleElement) {
            titleElement.innerHTML = originalTitle;
          }
          if (descriptionElement) {
            descriptionElement.innerHTML = originalDescription;
          }
          article.classList.remove("hidden");
          hasResults = true;
          continue;
        }

        const matchesSearch = searchTerms.every(
          (word) =>
            originalTitle.toLowerCase().includes(word) ||
            originalDescription.toLowerCase().includes(word),
        );

        if (matchesSearch) {
          if (titleElement) {
            titleElement.innerHTML = highlightText(originalTitle, searchTerms);
          }
          if (descriptionElement) {
            descriptionElement.innerHTML = highlightText(
              originalDescription,
              searchTerms,
            );
          }
          article.classList.remove("hidden");
          hasResults = true;
        } else {
          if (titleElement) {
            titleElement.innerHTML = originalTitle;
          }
          if (descriptionElement) {
            descriptionElement.innerHTML = originalDescription;
          }
          article.classList.add("hidden");
        }
      }
      noResults.classList.toggle("hidden", hasResults);
    });
  };

  setupSearch();
  document.addEventListener("astro:after-swap", setupSearch);
</script>
