"use client";

import { useEffect, useRef, useState } from "react";

import Carousel from "./Carousel";
import MediaImage from "./MediaImage";

/**
 * A strip of images with a lightbox.
 *
 * Both arrow shapes are kept because the two places this component appears draw
 * them differently: the site's own carousels use a long line with a head in a
 * row under the strip, and the published project page puts a plain chevron
 * either side of the pictures instead.
 *
 * A note carried over from the Blade component: the project gallery used to
 * render two bare `carousel__arrow--prev`/`--next` buttons with no `data-dir` —
 * which is what the carousel reads to decide direction — so both stepped
 * backwards, and with no glyph inside they were two empty gold boxes doing the
 * same wrong thing. Direction lives on `data-dir`.
 */
export default function Gallery({
  items,
  name = "gallery",
  alt = "",
  arrows = "line",
  labels,
}: {
  items: any[];
  name?: string;
  alt?: string;
  arrows?: "line" | "chevron";
  labels: { previous: string; next: string; close?: string };
}) {
  const slides = (items ?? []).filter(Boolean);
  const dialog = useRef<HTMLDialogElement>(null);
  const [index, setIndex] = useState(0);

  useEffect(() => {
    const node = dialog.current;

    if (!node) {
      return;
    }

    const onKey = (event: KeyboardEvent) => {
      if (!node.open) {
        return;
      }
      if (event.key === "ArrowRight") step(1);
      if (event.key === "ArrowLeft") step(-1);
    };

    document.addEventListener("keydown", onKey);

    return () => document.removeEventListener("keydown", onKey);
  });

  if (slides.length === 0) {
    return null;
  }

  const step = (delta: number) =>
    setIndex((current) => (current + delta + slides.length) % slides.length);

  const open = (at: number) => {
    setIndex(at);
    dialog.current?.showModal();
  };

  const current = slides[index];

  return (
    <>
      <Carousel name={name} labels={labels} modifier={undefined}>
        {slides.map((image, i) => (
          <div className="gallery-item" key={i}>
            <button
              className="project-gallery-open"
              type="button"
              data-project-gallery-open
              data-gallery-index={i}
              data-gallery-src={image.src}
              data-gallery-alt={image.alt || alt}
              onClick={() => open(i)}
            >
              <MediaImage image={image} alt={image.alt || alt} />
            </button>
          </div>
        ))}
      </Carousel>

      <dialog className="project-gallery-dialog" data-project-gallery-dialog ref={dialog}>
        <div className="project-gallery-dialog__toolbar">
          <span data-project-gallery-count>
            {index + 1} / {slides.length}
          </span>
          <button
            type="button"
            data-project-gallery-close
            aria-label={labels.close ?? "Close"}
            onClick={() => dialog.current?.close()}
          >
            &times;
          </button>
        </div>

        <button
          className="project-gallery-dialog__arrow project-gallery-dialog__arrow--prev"
          type="button"
          data-project-gallery-prev
          aria-label={labels.previous}
          onClick={() => step(-1)}
        >
          &#x2039;
        </button>

        <figure>
          <img data-project-gallery-image src={current?.src} alt={current?.alt || alt} />
          <figcaption data-project-gallery-caption>{current?.caption ?? ""}</figcaption>
        </figure>

        <button
          className="project-gallery-dialog__arrow project-gallery-dialog__arrow--next"
          type="button"
          data-project-gallery-next
          aria-label={labels.next}
          onClick={() => step(1)}
        >
          &#x203A;
        </button>
      </dialog>
    </>
  );
}
