"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
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 __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var ai_region_extension_exports = {};
__export(ai_region_extension_exports, {
  aiRegion: () => aiRegion
});
module.exports = __toCommonJS(ai_region_extension_exports);
var import_ai_region_plugin_key = require("./../_shared/ai-region-plugin-key.js");
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 AI_REGION_RANGE_CLASS = "ricos-ai-region";
const aiRegion = (0, import_tiptap_extensions.createRicosFunctionalExtension)({
  type: "extension",
  groups: [],
  name: "ai-region",
  createExtensionConfig({ services }) {
    const pmPlugin = new import_state.Plugin({
      key: import_ai_region_plugin_key.aiRegionPluginKey,
      state: {
        init() {
          return {
            regionList: [],
            decorations: import_view.DecorationSet.empty
          };
        },
        apply(tr, state) {
          const meta = tr.getMeta(pmPlugin);
          const regionList = meta?.addRegionList?.length ? [...state.regionList, ...meta.addRegionList] : meta?.syncRegionList?.length ? meta.syncRegionList : meta?.removeRegionList?.length ? state.regionList.filter((r) => !meta.removeRegionList.includes(r)) : meta?.removeAllRegions && state.regionList.length ? [] : state.regionList;
          if (state.regionList === regionList) {
            return { ...state, decorations: state.decorations.map(tr.mapping, tr.doc) };
          }
          const nodeWithPosListRange = regionList.filter((s) => s.type === "range").map((s) => {
            const { from, to, excluded } = 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(`Ai Region: Node with id ${from} not found`);
              return void 0;
            }
            if (!toNode) {
              console.error(`Ai Region: 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(`Ai Region: Nodes with ids ${from} and ${to} are not siblings`);
              return void 0;
            }
            const allNodesInRegionRange = [];
            tr.doc.nodesBetween(
              fromNode.pos,
              toNode.pos + toNode.node.nodeSize,
              (node, pos, parent) => {
                if (parent === parentFromNode) {
                  allNodesInRegionRange.push({ node, pos });
                  return false;
                }
              }
            );
            const posAfter = toNode.pos + toNode.node.nodeSize;
            const originalRicosNodes = allNodesInRegionRange.map(
              (nodeWithPos) => services.converters.fromPmNode(nodeWithPos.node.toJSON())
            );
            s.originalNodesRef.current = originalRicosNodes;
            return {
              nodesWithPos: allNodesInRegionRange,
              overlay: s.overlay,
              posAfter
            };
          }).filter(import_wix_rich_content_common.isDefined);
          const posListWithAfter = regionList.filter((s) => s.type === "afterNode").map((s) => {
            if (!s.id) {
              return { posAfter: 0, overlay: s.overlay };
            }
            const node = findNodeById(tr, s.id);
            if (!node) {
              console.error(`Ai Region: Node with id ${s.id} not found`);
              return void 0;
            }
            return { posAfter: node.pos + node.node.nodeSize, overlay: s.overlay };
          }).filter(import_wix_rich_content_common.isDefined);
          let decorations = import_view.DecorationSet.empty;
          nodeWithPosListRange.forEach(({ nodesWithPos: nodeWithPosListRange2 }) => {
            for (const nodeWithPos of nodeWithPosListRange2) {
              const { node, pos } = nodeWithPos;
              decorations = decorations.add(tr.doc, [
                import_view.Decoration.node(pos, pos + node.nodeSize, {
                  class: AI_REGION_RANGE_CLASS
                })
              ]);
            }
          });
          for (const pos of [...nodeWithPosListRange, ...posListWithAfter]) {
            if (!pos.overlay) {
              continue;
            }
            decorations = decorations.add(tr.doc, [
              import_view.Decoration.widget(pos.posAfter, (_view, _getPos) => {
                return pos.overlay;
              })
            ]);
          }
          return {
            regionList,
            decorations
          };
        }
      },
      props: {
        decorations(state) {
          return this?.getState(state)?.decorations;
        }
      }
    });
    return {
      name: this.name,
      addCommands() {
        return {
          acceptRegions: (nodesAndPositions) => ({ tr, editor }) => {
            nodesAndPositions.forEach(({ nodes, position }) => {
              const pmJsonNodes = nodes.map((node) => services.converters.toPmNode(node));
              const pmNodes = pmJsonNodes.map(editor.schema.nodeFromJSON);
              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(`Ai Region: Node with id ${position.from} not found`);
                    return;
                  }
                  if (!lastNode) {
                    console.error(`Ai Region: Node with id ${position.to} not found`);
                    return;
                  }
                  tr.replaceWith(firstNode.pos, lastNode.pos + lastNode.node.nodeSize, pmNodes);
                  tr.setMeta("allowTextReplace", true);
                  return;
                }
                case "afterNode": {
                  if (!position.id) {
                    tr.insert(0, pmNodes);
                    return;
                  }
                  const nodeWithPos = findNodeById(tr, position.id);
                  if (!nodeWithPos) {
                    console.error(`Ai Region: Node with id ${position.id} not found`);
                    return;
                  }
                  tr.insert(nodeWithPos.pos + nodeWithPos.node.nodeSize, pmNodes);
                  tr.setMeta("allowTextReplace", true);
                  return;
                }
                default:
                  (0, import_log_invariant.logInvariant)(new Error("Invalid position type when injecting"));
              }
            });
            tr.setMeta(pmPlugin, {
              removeRegionList: nodesAndPositions.map(({ position }) => position)
            });
            return true;
          },
          addAiRegions: (regionList) => ({ tr, dispatch, view }) => {
            const firstNodeId = regionList[0]?.type === "range" ? regionList[0].from : regionList[0]?.id;
            if (dispatch) {
              tr.setMeta(pmPlugin, {
                addRegionList: regionList
              });
              if (firstNodeId) {
                if (firstNodeId === "START") {
                  view.dom.scrollIntoView({ behavior: "smooth", block: "center" });
                }
                const nodeWithPos = findNodeById(tr, firstNodeId);
                if (nodeWithPos) {
                  queueMicrotask(() => {
                    const { pos: _pos } = nodeWithPos;
                    const dom = regionList[0]?.overlay;
                    if (dom) {
                      dom.scrollIntoView({ behavior: "smooth", block: "center" });
                    }
                  });
                }
              }
            }
            return true;
          },
          syncAiRegions: (regionList) => ({ tr, dispatch }) => {
            if (dispatch) {
              tr.setMeta(pmPlugin, {
                syncRegionList: regionList
              });
            }
            return true;
          },
          removeAllAiRegions: () => ({ tr, dispatch }) => {
            if (dispatch) {
              tr.setMeta(pmPlugin, {
                removeAllRegions: true
              });
            }
            return true;
          },
          removeAiRegions: (regionList) => ({ tr, dispatch }) => {
            if (dispatch) {
              tr.setMeta(pmPlugin, {
                removeRegionList: regionList
              });
            }
            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=ai-region-extension.js.map
