import topbar from "topbar";
import scrollIntoView from "scroll-into-view-if-needed";

import { waitUntilVisible } from "./lib/utils";

export function registerTopbar() {
  topbar.config({
    barColors: { 0: "#b2c1ff" },
    shadowColor: "rgba(0, 0, 0, .3)",
  });

  window.addEventListener("phx:page-loading-start", () => {
    topbar.show(500);
  });

  window.addEventListener("phx:page-loading-stop", () => {
    topbar.hide();
  });
}

export function registerGlobalEventHandlers() {
  window.addEventListener("lb:focus", (event) => {
    // The element may be about to show up via JS.show, which wraps the
    // change in requestAnimationFrame, so we do the same to make sure
    // the focus is applied only after we change the element visibility
    requestAnimationFrame(() => {
      event.target.focus();
    });
  });

  window.addEventListener("lb:set_value", (event) => {
    event.target.value = event.detail.value;
  });

  window.addEventListener("lb:check", (event) => {
    event.target.checked = true;
  });

  window.addEventListener("lb:uncheck", (event) => {
    event.target.checked = false;
  });

  window.addEventListener("lb:set_text", (event) => {
    event.target.textContent = event.detail.value;
  });

  window.addEventListener("lb:clipcopy", (event) => {
    if ("clipboard" in navigator) {
      if (event.detail.content) {
        navigator.clipboard.writeText(event.detail.content);
      } else if (event.target.tagName === "INPUT") {
        navigator.clipboard.writeText(event.target.value);
      } else {
        navigator.clipboard.writeText(event.target.textContent);
      }
    } else {
      alert(
        "Sorry, your browser does not support clipboard copy.\nThis generally requires a secure origin — either HTTPS or localhost.",
      );
    }
  });

  window.addEventListener("lb:scroll_into_view", (event) => {
    const options = event.detail || {};

    // If the element is going to be shown, we want to wait for that
    waitUntilVisible(event.target).then(() => {
      scrollIntoView(event.target, {
        scrollMode: "if-needed",
        behavior: "smooth",
        block: "nearest",
        inline: "nearest",
        ...options,
      });
    });
  });

  window.addEventListener("phx:lb:exec_js", (event) => {
    const selector = event.detail.to || "body";

    document.querySelectorAll(selector).forEach((element) => {
      window.liveSocket.execJS(element, event.detail.js);
    });
  });

  window.addEventListener("lb:session_list:on_selection_change", () => {
    const anySessionSelected = !!document.querySelector(
      "[name='session_ids[]']:checked",
    );
    const disconnect = document.querySelector(
      "#edit-sessions [name='disconnect']",
    );
    const closeAll = document.querySelector(
      "#edit-sessions [name='close_all']",
    );
    disconnect.parentElement.classList.toggle(
      "pointer-events-none",
      !anySessionSelected,
    );
    disconnect.parentElement.classList.toggle(
      "opacity-50",
      !anySessionSelected,
    );
    closeAll.parentElement.classList.toggle(
      "pointer-events-none",
      !anySessionSelected,
    );
    closeAll.parentElement.classList.toggle("opacity-50", !anySessionSelected);
  });

  window.addEventListener("contextmenu", (event) => {
    const target = event.target.closest("[data-contextmenu-trigger-click]");

    if (target) {
      event.preventDefault();
      // LV dispatches phx-click to the target of the preceding mousedown event
      target.dispatchEvent(new Event("mousedown", { bubbles: true }));
      target.dispatchEvent(new Event("click", { bubbles: true }));
    }
  });

  // Ignore submit events on elements with phx-nosubmit
  window.addEventListener(
    "submit",
    (event) => {
      if (event.target.hasAttribute("phx-nosubmit")) {
        event.preventDefault();
        event.stopPropagation();
      }
    },
    { capture: true },
  );
}

/**
 * Disables the auto-zoom behavior when focusing an input on a touch device.
 *
 * It is important that this should not prevent users from manually
 * zooming if they wish. There isn't a portable solution to this
 * problem, so this hook is a no-op if the detected device is not
 * known to behave well.
 *
 * See: https://stackoverflow.com/questions/2989263/disable-auto-zoom-in-input-text-tag-safari-on-iphone
 */
export function disableZoomOnInputFocus() {
  const isWebKit = /AppleWebKit/.test(navigator.userAgent);
  const isTouchScreen =
    "ontouchstart" in window || navigator.maxTouchPoints > 0;

  if (isWebKit && isTouchScreen) {
    const viewportTag = document.querySelector("meta[name='viewport']");

    if (viewportTag) {
      viewportTag.content += ", maximum-scale=1.0";
    }
  }
}
