<script lang="ts">
  import cat1 from '@assets/img/cat1.jpg';
  import cat2 from '@assets/img/cat2.jpg';
  import { tick, untrack } from 'svelte';

  // html bindings
  let imageContainer: HTMLDivElement;

  // types
  interface Props {
    images?: { path: string; text?: string }[];
  }

  // states
  const { images = [{ path: cat1.src }, { path: cat2.src }] }: Props = $props();

  let currentImageIdx = $state<number | null>(images.length > 0 ? 0 : null);
  let initialCurrentImageIdxEffect = $state(false);

  let activeImageIdx = $state<number | null>(null);
  let activeImageHtmlDialog = $state<HTMLDialogElement | null>(null);

  // lifecycle
  $effect(() => {
    // this check must be first. otherwise this effect will not be called besides on mount
    if (currentImageIdx == null) return;
    else if (untrack(() => (initialCurrentImageIdxEffect ? false : (initialCurrentImageIdxEffect = true)))) return;
    imageContainer.children.item(currentImageIdx)!.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
  });

  // callback
  function scrollToIdx(idx: number) {
    currentImageIdx = idx;
  }

  function scrollPrev() {
    if (currentImageIdx == null || currentImageIdx == 0) return;
    currentImageIdx -= 1;
  }

  function scrollNext() {
    if (currentImageIdx == null || currentImageIdx == images.length - 1) return;
    currentImageIdx += 1;
  }

  async function showImagePopup(imageIndex: number) {
    activeImageIdx = imageIndex;
    // wait for dialog dom element
    await tick();
    activeImageHtmlDialog!.showModal();
  }
</script>

<div class="relative">
  <div class="carousel w-full aspect-video rounded items-center overflow-hidden" bind:this={imageContainer}>
    {#each images as image, i (image.path)}
      <button class="carousel-item w-full cursor-zoom-in z-10" onclick={() => showImagePopup(i)}>
        <img src={image.path} class="w-full object-cover" alt={image.text ?? image.path} />
      </button>
    {/each}
  </div>
  {#if currentImageIdx != null}
    <div class="absolute bottom-6 w-full flex justify-center gap-1.5">
      {#each images as image, i (image.path)}
        <button
          class="flex p-0.5 cursor-pointer z-20"
          aria-label={`scroll to image ${i}`}
          onclick={() => scrollToIdx(i)}
          ><span class="block w-2.5 h-2.5 bg-white opacity-50 rounded-full" class:opacity-100={currentImageIdx === i}
          ></span></button
        >
      {/each}
    </div>
    {#if images.length > 1}
      <div class="absolute top-0 left-2 h-full flex items-center">
        <button
          class="backdrop-invert-75 w-10 h-10 rounded-full flex justify-center items-center cursor-pointer z-20"
          aria-label="previous"
          onclick={scrollPrev}><span class="iconify iconify-[heroicons--chevron-left] w-2/5 h-2/5"></span></button
        >
      </div>
      <div class="absolute top-0 right-2 h-full flex items-center">
        <button
          class="backdrop-invert-75 w-10 h-10 rounded-full flex justify-center items-center cursor-pointer z-20"
          aria-label="next"
          onclick={scrollNext}><span class="iconify iconify-[heroicons--chevron-right] w-2/5 h-2/5"></span></button
        >
      </div>
    {/if}
  {/if}
</div>

{#if activeImageIdx != null}
  <dialog
    class="modal"
    bind:this={activeImageHtmlDialog}
    onclose={() => setTimeout(() => (activeImageIdx = null), 300)}
  >
    <div class="max-w-4/6 max-h-5/6 modal-box bg-transparent p-0 rounded-none">
      <img class="object-cover" src={images[activeImageIdx].path} alt={images[activeImageIdx].path} />
    </div>
    <form method="dialog" class="modal-box w-[initial] h-[initial] bg-transparent p-0 absolute top-5 right-5">
      <button class="text-2xl cursor-pointer">✖</button>
    </form>
    <form method="dialog" class="modal-backdrop">
      <button class="cursor-default">close</button>
    </form>
  </dialog>
{/if}
