"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var extension_exports = {};
__export(extension_exports, {
  spotlight: () => spotlight
});
module.exports = __toCommonJS(extension_exports);
var import_classnames = __toESM(require("classnames"));
var import_log_invariant = require("./../../_shared/log-invariant.js");
var import_state = require("./../../tiptap/pm/state.js");
var import_view = require("./../../tiptap/pm/view.js");
var import_wix_rich_content_common = require("./../../wix-rich-content-common/index.js");
var import_tiptap_extensions = require("./../../tiptap-extensions/index.js");
const SPOTLIGHT_RANGE_CLASS = "ricos-spotlight";
const SPOTLIGHT_BACKGROUND_RANGE_CLASS = "ricos-spotlight-background";
const SPOTLIGHT_RANGE_FIRST_CLASS = "ricos-spotlight-first";
const SPOTLIGHT_RANGE_LAST_CLASS = "ricos-spotlight-last";
const SPOTLIGHT_CURSOR_CLASS = "ricos-cursor-spotlight";
const spotlight = (0, import_tiptap_extensions.createRicosFunctionalExtension)({
  type: "extension",
  groups: [],
  name: "spotlight",
  createExtensionConfig({ services }) {
    const pmPlugin = new import_state.Plugin({
      key: new import_state.PluginKey("spotlight"),
      state: {
        init() {
          return {
            spotlightList: [],
            decorations: import_view.DecorationSet.empty
          };
        },
        apply(tr, state) {
          const meta = tr.getMeta(pmPlugin);
          if (!meta) {
            return { ...state, decorations: state.decorations.map(tr.mapping, tr.doc) };
          }
          if (meta.spotlightList.length === 0) {
            return {
              ...state,
              decorations: import_view.DecorationSet.empty
            };
          }
          const nodeWithPosListRange = meta.spotlightList.filter((s) => s.type === "range").flatMap((s) => {
            const { from, to, excluded, highlightType } = s;
            const fromNode = from ? excluded ? findNodeSiblingAfterNodeId(tr, from) : findNodeById(tr, from) : getFirstNode(tr);
            const toNode = to ? excluded ? findNodeSiblingBeforeNodeId(tr, to) : findNodeById(tr, to) : getLastNode(tr);
            if (!fromNode) {
              console.error(`Spotlight: Node with id ${from} not found`);
              return void 0;
            }
            if (!toNode) {
              console.error(`Spotlight: Node with id ${to} not found`);
              return void 0;
            }
            const parentFromNode = tr.doc.resolve(fromNode.pos).parent;
            const parentToNode = tr.doc.resolve(toNode.pos).parent;
            if (parentFromNode !== parentToNode) {
              console.error(`Spotlight: Nodes with ids ${from} and ${to} are not siblings`);
              return void 0;
            }
            const allNodesInSpotlightRange = [];
            tr.doc.nodesBetween(
              fromNode.pos,
              toNode.pos + toNode.node.nodeSize,
              (node, pos, parent) => {
                if (parent === parentFromNode) {
                  allNodesInSpotlightRange.push({ node, pos, highlightType });
                  return false;
                }
              }
            );
            return allNodesInSpotlightRange;
          }).filter(import_wix_rich_content_common.isDefined);
          const posListWithAfter = meta.spotlightList.filter((s) => s.type === "afterNode").map((s) => {
            if (!s.id) {
              return 0;
            }
            const node = findNodeById(tr, s.id);
            if (!node) {
              console.error(`Spotlight: Node with id ${s.id} not found`);
              return void 0;
            }
            return node.pos + node.node.nodeSize;
          }).filter(import_wix_rich_content_common.isDefined);
          let decorations = import_view.DecorationSet.empty;
          for (const nodeWithPos of nodeWithPosListRange) {
            const { node, pos } = nodeWithPos;
            decorations = decorations.add(tr.doc, [
              import_view.Decoration.node(pos, pos + node.nodeSize, {
                class: (0, import_classnames.default)(
                  nodeWithPos.highlightType === "line" ? SPOTLIGHT_RANGE_CLASS : SPOTLIGHT_BACKGROUND_RANGE_CLASS,
                  node.attrs.id,
                  {
                    [SPOTLIGHT_RANGE_FIRST_CLASS]: nodeWithPosListRange.indexOf(nodeWithPos) === 0,
                    [SPOTLIGHT_RANGE_LAST_CLASS]: nodeWithPosListRange.indexOf(nodeWithPos) === nodeWithPosListRange.length - 1
                  }
                )
              })
            ]);
          }
          for (const pos of posListWithAfter) {
            decorations = decorations.add(tr.doc, [
              import_view.Decoration.widget(pos, (_view, _getPos) => {
                const div = document.createElement("div");
                div.classList.add(SPOTLIGHT_CURSOR_CLASS);
                return div;
              })
            ]);
          }
          return {
            spotlightList: meta.spotlightList,
            decorations
          };
        }
      },
      props: {
        decorations(state) {
          return this?.getState(state)?.decorations;
        }
      }
    });
    return {
      name: this.name,
      addCommands() {
        return {
          injectNodes: (nodesAndPositions, revert) => ({ tr, dispatch, editor }) => {
            nodesAndPositions.forEach(({ nodes, position }) => {
              const pmJsonNodes = nodes.map((node) => services.converters.toPmNode(node));
              const pmNodes = pmJsonNodes.map(editor.schema.nodeFromJSON);
              revert.changes = [];
              switch (position.type) {
                case "range": {
                  const firstNode = position.from ? position.excluded ? findNodeSiblingAfterNodeId(tr, position.from) : findNodeById(tr, position.from) : getFirstNode(tr);
                  const lastNode = position.to ? position.excluded ? findNodeSiblingBeforeNodeId(tr, position.to) : findNodeById(tr, position.to) : getLastNode(tr);
                  if (!firstNode) {
                    console.error(`Spotlight: Node with id ${position.from} not found`);
                    return;
                  }
                  if (!lastNode) {
                    console.error(`Spotlight: Node with id ${position.to} not found`);
                    return;
                  }
                  const replacedNodes = tr.doc.slice(
                    firstNode.pos,
                    lastNode.pos + lastNode.node.nodeSize
                  ).content;
                  const replacedRicosNodes = (replacedNodes.toJSON() ?? []).map(
                    (node) => services.converters.fromPmNode(node)
                  );
                  const nodeBefore = firstNode.pos > 0 ? tr.doc.nodeAt(firstNode.pos - 1) : void 0;
                  tr.replaceWith(firstNode.pos, lastNode.pos + lastNode.node.nodeSize, pmNodes);
                  tr.setMeta("allowTextReplace", true);
                  if (nodes.length === 0) {
                    revert.changes.push({
                      nodes: replacedRicosNodes,
                      position: {
                        type: "afterNode",
                        id: nodeBefore ? nodeBefore.attrs.id : "START"
                      }
                    });
                  } else {
                    revert.changes.push({
                      nodes: replacedRicosNodes,
                      position: {
                        type: "range",
                        from: nodes[0].id,
                        to: nodes[nodes.length - 1].id
                      }
                    });
                  }
                  return;
                }
                case "afterNode": {
                  if (!position.id) {
                    tr.insert(0, pmNodes);
                    revert.changes.push({
                      nodes: [],
                      position: {
                        type: "range",
                        from: nodes[0].id,
                        to: nodes[nodes.length - 1].id
                      }
                    });
                    return;
                  }
                  const nodeWithPos = findNodeById(tr, position.id);
                  if (!nodeWithPos) {
                    console.error(`Spotlight: Node with id ${position.id} not found`);
                    return;
                  }
                  tr.insert(nodeWithPos.pos + nodeWithPos.node.nodeSize, pmNodes);
                  tr.setMeta("allowTextReplace", true);
                  revert.changes.push({
                    nodes: [],
                    position: {
                      type: "range",
                      from: nodes[0].id,
                      to: nodes[nodes.length - 1].id
                    }
                  });
                  return;
                }
                default:
                  (0, import_log_invariant.logInvariant)(new Error("Invalid position type when injecting"));
              }
            });
            if (dispatch) {
            }
            return true;
          },
          setSpotlightList: (spotlightList, skipScroll) => ({ tr, dispatch, view }) => {
            const firstNodeId = spotlightList[0]?.type === "range" ? spotlightList[0].from : spotlightList[0]?.id;
            if (dispatch) {
              tr.setMeta(pmPlugin, {
                spotlightList
              });
              if (firstNodeId && !skipScroll) {
                if (firstNodeId === "START") {
                  view.dom.scrollIntoView({ behavior: "smooth", block: "center" });
                }
                const nodeWithPos = findNodeById(tr, firstNodeId);
                if (nodeWithPos) {
                  queueMicrotask(() => {
                    const { pos } = nodeWithPos;
                    const dom = view.nodeDOM(pos);
                    if (dom) {
                      dom.scrollIntoView({ behavior: "smooth", block: "center" });
                    }
                  });
                }
              }
            }
            return true;
          }
        };
      },
      addProseMirrorPlugins() {
        return [pmPlugin];
      }
    };
  }
});
const findNodeSiblingAfterNodeId = (tr, id) => {
  const nodesWithPos = [];
  tr.doc.descendants((child, pos, parent) => {
    if (child.attrs.id === id) {
      const afterChild = parent?.childAfter(pos + child.nodeSize);
      if (afterChild?.node) {
        const afterNode = findNodeById(tr, afterChild.node.attrs.id);
        if (afterNode) {
          nodesWithPos.push(afterNode);
        }
        return false;
      }
    }
  });
  const nodeWithPos = nodesWithPos[0];
  if (!nodeWithPos) {
    return void 0;
  }
  return nodeWithPos;
};
const findNodeSiblingBeforeNodeId = (tr, id) => {
  const nodesWithPos = [];
  tr.doc.descendants((child, pos, parent, index) => {
    if (child.attrs.id === id) {
      const beforeSiblingIndex = Math.max(index - 1, 0);
      const beforeChild = parent?.maybeChild(beforeSiblingIndex);
      if (beforeChild) {
        const beforeNode = findNodeById(tr, beforeChild.attrs.id);
        if (beforeNode) {
          nodesWithPos.push(beforeNode);
        }
        return false;
      }
    }
  });
  const nodeWithPos = nodesWithPos[0];
  if (!nodeWithPos) {
    return void 0;
  }
  return nodeWithPos;
};
const findNodeById = (tr, id) => {
  const nodesWithPos = [];
  tr.doc.descendants((child, pos) => {
    if (child.attrs.id === id) {
      nodesWithPos.push({
        node: child,
        pos
      });
      return false;
    }
  });
  const nodeWithPos = nodesWithPos[0];
  if (!nodeWithPos) {
    return void 0;
  }
  const parent = tr.doc.resolve(nodeWithPos.pos).parent;
  if (parent.type.name === "FIGURE" && nodeWithPos.node.type.name !== "CAPTION") {
    return { node: parent, pos: nodeWithPos.pos - 1 };
  }
  return nodeWithPos;
};
const getFirstNode = (tr) => {
  const firstNode = tr.doc.content.firstChild;
  if (!firstNode) {
    return void 0;
  }
  return { node: firstNode, pos: 0 };
};
const getLastNode = (tr) => {
  const lastNode = tr.doc.content.lastChild;
  if (!lastNode) {
    return void 0;
  }
  return { node: lastNode, pos: tr.doc.content.size - lastNode.nodeSize };
};
//# sourceMappingURL=extension.js.map
