import {mergeObject} from "../../utils/helpers.mjs";
import ImageNode from "./image-node.mjs";
import LinkMark from "./link-mark.mjs";
import SchemaDefinition from "./schema-definition.mjs";
import AttributeCapture from "./attribute-capture.mjs";

/**
 * A class responsible for encapsulating logic around image-link nodes in the ProseMirror schema.
 * @extends {SchemaDefinition}
 */
export default class ImageLinkNode extends SchemaDefinition {
  /** @override */
  static tag = "a";

  /* -------------------------------------------- */

  /**
   * Cached attribute capture instance.
   * @type {AttributeCapture}
   */
  static #capture = new AttributeCapture();

  /* -------------------------------------------- */

  /** @override */
  static get attrs() {
    const attrs = mergeObject(ImageNode.attrs, LinkMark.attrs);
    attrs._img = { default: null };
    return attrs;
  }

  /* -------------------------------------------- */

  /** @override */
  static getAttrs(el) {
    if ( (el.children.length !== 1) || (el.children[0].tagName !== "IMG") ) return false;
    const attrs = ImageNode.getAttrs(el.children[0]);
    attrs.href = el.href;
    attrs.title = el.title;
    attrs._img = ImageLinkNode.#capture._captureAttributes(el.children[0], {
      styles: ["float"], classes: ["centered"]
    });
    return attrs;
  }

  /* -------------------------------------------- */

  /** @override */
  static toDOM(node) {
    const spec = LinkMark.toDOM(node);
    const img = ImageNode.toDOM(node);
    const [, attrs] = img;
    mergeObject(attrs, node.attrs._img);
    spec.push(img);
    return spec;
  }

  /* -------------------------------------------- */

  /** @inheritdoc */
  static make() {
    return mergeObject(super.make(), {
      group: "block",
      draggable: true,
      managed: { styles: ["float"], classes: ["centered"] }
    });
  }

  /* -------------------------------------------- */

  /**
   * Handle clicking on image links while editing.
   * @param {EditorView} view     The ProseMirror editor view.
   * @param {number} pos          The position in the ProseMirror document that the click occurred at.
   * @param {PointerEvent} event  The click event.
   * @param {Node} node           The Node instance.
   */
  static onClick(view, pos, event, node) {
    if ( (event.ctrlKey || event.metaKey) && node.attrs.href ) window.open(node.attrs.href, "_blank");
    // For some reason, calling event.preventDefault in this (mouseup) handler is not enough to cancel the default click
    // behaviour. It seems to be related to the outer anchor being set to contenteditable="false" by ProseMirror.
    // This workaround seems to prevent the click.
    const parent = event.target.parentElement;
    if ( (parent.tagName === "A") && !parent.isContentEditable ) parent.contentEditable = "true";
    return true;
  }
}
