/**
 * Makes popup hero images/videos open a padded overlay (not browser fullscreen) on click.
 * Escape or backdrop click dismisses it. Clicks use stopPropagation so the
 * parent SEQTA popup does not close.
 */

import { settingsState } from "../listeners/SettingsState";
import { allowedPopupImageUrl } from "./allowedPopupImageUrl";

const FULLSCREENABLE_CLASS = "popup-media-fullscreenable";
const OVERLAY_VISIBLE_CLASS = "bsplus-popup-media-overlay-backdrop--visible";
const OVERLAY_ANIM_MS = 280;

function isImageOrVideo(el: Element): el is HTMLImageElement | HTMLVideoElement {
  return el instanceof HTMLImageElement || el instanceof HTMLVideoElement;
}

export function attachPopupMediaFullscreen(el: HTMLImageElement | HTMLVideoElement) {
  el.classList.add(FULLSCREENABLE_CLASS);
  el.setAttribute("tabindex", "0");
  el.setAttribute("role", "button");
  el.setAttribute("aria-label", "View larger");
  el.title = "Click to view larger";

  const open = (e: Event) => {
    e.preventDefault();
    e.stopPropagation();
    openMediaOverlayViewer(el);
  };

  el.addEventListener("click", open);
  el.addEventListener("keydown", (e) => {
    if (e.key === "Enter" || e.key === " ") {
      open(e);
    }
  });
}

function openMediaOverlayViewer(source: HTMLImageElement | HTMLVideoElement) {
  const backdrop = document.createElement("div");
  backdrop.id = "bsplus-popup-media-overlay";
  backdrop.className = "bsplus-popup-media-overlay-backdrop";

  const inner = document.createElement("div");
  inner.className = "bsplus-popup-media-overlay-inner";

  const slot = document.createElement("div");
  slot.className = "bsplus-popup-media-overlay-slot";

  let media: HTMLImageElement | HTMLVideoElement;
  if (source instanceof HTMLVideoElement) {
    const v = source;
    const nv = document.createElement("video");
    nv.classList.add("bsplus-popup-media-overlay-media");
    nv.controls = true;
    nv.playsInline = true;
    nv.loop = v.loop;
    nv.muted = v.muted;
    nv.volume = v.volume;
    let hasValidSource = false;
    for (const s of v.querySelectorAll("source")) {
      const src = allowedPopupImageUrl((s as HTMLSourceElement).src);
      if (!src) continue;
      hasValidSource = true;
      const ns = document.createElement("source");
      ns.src = src;
      const t = (s as HTMLSourceElement).type;
      if (t) ns.type = t;
      nv.appendChild(ns);
    }
    if (!hasValidSource) {
      const directSrc = allowedPopupImageUrl(v.currentSrc || v.src);
      if (!directSrc) return;
      nv.src = directSrc;
    }
    nv.addEventListener(
      "loadeddata",
      () => {
        try {
          nv.currentTime = v.currentTime;
        } catch {
          /* ignore */
        }
        void nv.play().catch(() => {});
      },
      { once: true },
    );
    v.pause();
    nv.load();
    media = nv;
  } else {
    const rawSrc = source.currentSrc || source.src;
    const safeSrc = allowedPopupImageUrl(rawSrc);
    if (!safeSrc) return;
    const img = document.createElement("img");
    img.classList.add("bsplus-popup-media-overlay-media");
    img.src = safeSrc;
    img.alt = source.alt || "";
    media = img;
  }

  media.addEventListener("click", (e) => e.stopPropagation());

  slot.appendChild(media);
  inner.append(slot);
  backdrop.appendChild(inner);
  document.body.append(backdrop);

  if (!settingsState.animations) {
    backdrop.classList.add("bsplus-popup-media-overlay--instant");
    backdrop.classList.add(OVERLAY_VISIBLE_CLASS);
  } else {
    requestAnimationFrame(() => {
      requestAnimationFrame(() => {
        backdrop.classList.add(OVERLAY_VISIBLE_CLASS);
      });
    });
  }

  inner.addEventListener("click", (e) => e.stopPropagation());

  let done = false;
  const removeOverlay = () => {
    if (source instanceof HTMLVideoElement && media instanceof HTMLVideoElement) {
      try {
        source.currentTime = media.currentTime;
      } catch {
        /* ignore */
      }
      void source.play().catch(() => {});
    }
    backdrop.remove();
  };

  const close = () => {
    if (done) return;
    done = true;
    document.removeEventListener("keydown", onDocKey, true);

    if (!settingsState.animations) {
      removeOverlay();
      return;
    }

    backdrop.classList.remove(OVERLAY_VISIBLE_CLASS);
    window.setTimeout(removeOverlay, OVERLAY_ANIM_MS);
  };

  const onDocKey = (ev: KeyboardEvent) => {
    if (ev.key === "Escape") {
      ev.stopPropagation();
      close();
    }
  };

  document.addEventListener("keydown", onDocKey, true);

  backdrop.addEventListener("click", () => {
    close();
  });
}

export function attachPopupMediaFullscreenIfPresent(
  root: ParentNode,
  selector: string,
) {
  const el = root.querySelector(selector);
  if (el && isImageOrVideo(el)) {
    attachPopupMediaFullscreen(el);
  }
}
