import { render } from "preact";
import { templateClass } from "../lib/config";
import { ensureStyles } from "../lib/styles";
import { Popup } from "./Popup";

/**
 * Opens and closes the single comparison popup: locks page scrolling and
 * gives focus back to whatever opened it.
 *
 * No history entry on purpose: WordPress's Interactivity router (used by
 * WooCommerce blocks) handles `popstate` itself and may reload the page.
 */
let host = null;
let opener = null;
let scroll = null;

function emit(name) {
  document.dispatchEvent(
    new CustomEvent(`pcfw:${name}`, { detail: { context: "popup" } }),
  );
}

function lockScroll() {
  const root = document.documentElement;
  const gap = window.innerWidth - root.clientWidth;

  scroll = {
    overflow: root.style.overflow,
    padding: document.body.style.paddingRight,
  };
  root.style.overflow = "hidden";
  if (gap > 0) {
    document.body.style.paddingRight = `${gap}px`;
  }
}

function unlockScroll() {
  if (scroll) {
    document.documentElement.style.overflow = scroll.overflow;
    document.body.style.paddingRight = scroll.padding;
    scroll = null;
  }
}

function draw(closing) {
  render(
    <Popup closing={closing} onRequestClose={closePopup} onClosed={teardown} />,
    host,
  );
}

/** Removes the popup after its exit animation. */
function teardown() {
  if (!host) {
    return;
  }

  render(null, host);
  host.remove();
  host = null;
  unlockScroll();
  emit("close");

  if (opener && document.contains(opener)) {
    opener.focus();
  }
  opener = null;
}

/** Opens the popup (does nothing when it's already open). */
export function openPopup() {
  if (host) {
    return;
  }

  opener = document.activeElement;
  host = document.createElement("div");
  host.className = `pcfw-table-mount pcfw-popup-host ${templateClass()}`;
  document.body.appendChild(host);

  lockScroll();
  emit("open");

  // First open on a shop page: wait for the stylesheet to avoid a flash.
  ensureStyles().then(() => host && draw(false));
}

/** Closes the popup (after its exit animation). */
export function closePopup() {
  if (host) {
    draw(true);
  }
}
