"use strict";

import {Controller} from "@hotwired/stimulus";

/**
 * Copies a value to the clipboard and confirms it with the usual toast.
 *
 * Used by row actions that hand out a link (the signed application link on the
 * participant list). The confirmation goes through the global flash toast rather
 * than swapping the button's own label: these buttons live inside an `<el-menu
 * popover>`, which closes the moment the item is activated, so any feedback
 * rendered on the button itself would be torn out of the DOM before it is read.
 */
export default class extends Controller {
  static values = {
    text: String,
    done: String,
    failed: String,
  };

  async copy(event) {
    event.preventDefault();

    if (!this.textValue) {
      return;
    }

    try {
      await this.write(this.textValue);
      this.flash("success", this.doneValue || "Kopiert");
    } catch (e) {
      console.error("Copy failed", e);
      // Nothing landed on the clipboard, and the popover has already closed —
      // say so, or the user pastes something stale and never knows why.
      this.flash("error", this.failedValue || "Kopieren fehlgeschlagen");
    }
  }

  async write(text) {
    // The async Clipboard API needs a secure context; a tenant running plain
    // HTTP locally would otherwise get an unexplained failure.
    if (navigator.clipboard && window.isSecureContext) {
      return navigator.clipboard.writeText(text);
    }

    const area = document.createElement("textarea");
    area.value = text;
    area.setAttribute("readonly", "");
    area.style.position = "fixed";
    area.style.opacity = "0";
    document.body.appendChild(area);
    area.select();

    try {
      if (!document.execCommand("copy")) {
        throw new Error("execCommand copy rejected");
      }
    } finally {
      area.remove();
    }
  }

  flash(type, message) {
    window.dispatchEvent(new CustomEvent("admin:flash", {detail: {type, message}}));
  }
}
