import {
  redo,
  undo,
  ySyncPlugin,
  yUndoPlugin,
  yUndoPluginKey,
  yXmlFragmentToProsemirrorJSON
} from "y-prosemirror";
import { Extension } from "./../core/index.js";
import { Plugin, PluginKey } from "./../pm/state.js";
const Collaboration = Extension.create({
  name: "collaboration",
  priority: 1e3,
  addOptions() {
    return {
      document: null,
      field: "default",
      fragment: null
    };
  },
  addStorage() {
    return {
      isDisabled: false
    };
  },
  onCreate() {
    if (this.editor.extensionManager.extensions.find((extension) => extension.name === "history")) {
      console.warn(
        '[tiptap warn]: "./" comes with its own history support and is not compatible with "@tiptap/extension-history".'
      );
    }
  },
  addCommands() {
    return {
      undo: () => ({ tr, state, dispatch }) => {
        tr.setMeta("preventDispatch", true);
        const undoManager = yUndoPluginKey.getState(state).undoManager;
        if (undoManager.undoStack.length === 0) {
          return false;
        }
        if (!dispatch) {
          return true;
        }
        return undo(state);
      },
      redo: () => ({ tr, state, dispatch }) => {
        tr.setMeta("preventDispatch", true);
        const undoManager = yUndoPluginKey.getState(state).undoManager;
        if (undoManager.redoStack.length === 0) {
          return false;
        }
        if (!dispatch) {
          return true;
        }
        return redo(state);
      }
    };
  },
  addKeyboardShortcuts() {
    return {
      "Mod-z": () => this.editor.commands.undo(),
      "Mod-y": () => this.editor.commands.redo(),
      "Shift-Mod-z": () => this.editor.commands.redo()
    };
  },
  addProseMirrorPlugins() {
    const fragment = this.options.fragment ? this.options.fragment : this.options.document.getXmlFragment(this.options.field);
    const yUndoPluginInstance = yUndoPlugin(this.options.yUndoOptions);
    const originalUndoPluginView = yUndoPluginInstance.spec.view;
    yUndoPluginInstance.spec.view = (view) => {
      const { undoManager } = yUndoPluginKey.getState(view.state);
      if (undoManager.restore) {
        undoManager.restore();
        undoManager.restore = () => {
        };
      }
      const viewRet = originalUndoPluginView ? originalUndoPluginView(view) : void 0;
      return {
        destroy: () => {
          const hasUndoManSelf = undoManager.trackedOrigins.has(undoManager);
          const observers = undoManager._observers;
          undoManager.restore = () => {
            if (hasUndoManSelf) {
              undoManager.trackedOrigins.add(undoManager);
            }
            undoManager.doc.on("afterTransaction", undoManager.afterTransactionHandler);
            undoManager._observers = observers;
          };
          if (viewRet?.destroy) {
            viewRet.destroy();
          }
        }
      };
    };
    const ySyncPluginOptions = {
      ...this.options.ySyncOptions,
      onFirstRender: this.options.onFirstRender
    };
    const ySyncPluginInstance = ySyncPlugin(fragment, ySyncPluginOptions);
    if (this.editor.options.enableContentCheck) {
      fragment.doc?.on("beforeTransaction", () => {
        try {
          const jsonContent = yXmlFragmentToProsemirrorJSON(fragment);
          if (jsonContent.content.length === 0) {
            return;
          }
          this.editor.schema.nodeFromJSON(jsonContent).check();
        } catch (error) {
          this.editor.emit("contentError", {
            error,
            editor: this.editor,
            disableCollaboration: () => {
              fragment.doc?.destroy();
              this.storage.isDisabled = true;
            }
          });
          return false;
        }
      });
    }
    return [
      ySyncPluginInstance,
      yUndoPluginInstance,
      // Only add the filterInvalidContent plugin if content checking is enabled
      this.editor.options.enableContentCheck && new Plugin({
        key: new PluginKey("filterInvalidContent"),
        filterTransaction: () => {
          if (this.storage.isDisabled) {
            fragment.doc?.destroy();
            return true;
          }
          return true;
        }
      })
    ].filter(Boolean);
  }
});
export {
  Collaboration
};
//# sourceMappingURL=collaboration.js.map
