import lodash from "lodash";
import {
  BLOCKQUOTE,
  BULLET_LIST_TYPE,
  CHECKBOX_LIST_TYPE,
  CODE_BLOCK_TYPE,
  GIPHY_TYPE,
  HEADER_BLOCK,
  IMAGE_TYPE,
  NUMBERED_LIST_TYPE,
  RICOS_ANCHOR_TYPE,
  RICOS_FONT_SIZE_TYPE,
  RICOS_GIPHY_TYPE,
  RICOS_IMAGE_TYPE,
  RICOS_INDENT_TYPE,
  RICOS_LAYOUT_TYPE,
  RICOS_LINE_SPACING_TYPE,
  RICOS_LINK_TYPE,
  RICOS_MENTION_TYPE,
  RICOS_TEXT_COLOR_TYPE,
  RICOS_TEXT_HIGHLIGHT_TYPE,
  TIPTAP_CAPTION_TYPE,
  TIPTAP_FIGURE_TYPE,
  TIPTAP_LAYOUT_TYPE,
  TIPTAP_GIF_TYPE,
  TIPTAP_IMAGE_TYPE,
  TIPTAP_VIDEO_TYPE,
  UNSTYLED,
  generateId
} from "./../../ricos-content/index.js";
import { fromEntries } from "./../../ricos-content/lib/utils.js";
import {
  SHORTCUT_SHEET_MODAL_ID,
  ShortcutsDialog
} from "./../../ricos-editor/shortcuts/shortcuts-dialog.js";
import {
  desktopTextButtonList,
  mobileTextButtonList
} from "./../../ricos-plugins/toolbar-utils/default-text-formatting-buttons.js";
import { getButtonsListFromConfig } from "./../../ricos-plugins/toolbar-utils/get-buttons-list-from-config.js";
import { mergeToolbarSettings } from "./../../ricos-plugins/toolbar-utils/merge-toolbar-settings.js";
import { Decoration_Type, Node_Type } from "./../../ricos-schema/legacy/wix/rich_content/v1/index.js";
import { legacyPluginToNextMap } from "./../../ricos-schema/next-schema/index.js";
import { DOC_STYLE_TYPES, Mark_Type, ToolbarType } from "./../../ricos-types/index.js";
import { getAlignmentInSelection } from "./../../_shared/resolvers/get-alignment-in-selection.js";
import { getFontFamilyInSelection } from "./../../_shared/resolvers/get-font-family-in-selection.js";
import { getFontSizeInSelection } from "./../../_shared/resolvers/get-font-size-in-selection.js";
import { getHeadingInSelection } from "./../../_shared/resolvers/get-heading-in-selection.js";
import { getHighlightColorInSelection } from "./../../_shared/resolvers/get-highligh-color-in-selection.js";
import { getLineSpacingAfterSelection } from "./../../_shared/resolvers/get-line-spacing-after-selection.js";
import { getLineSpacingBeforeSelection } from "./../../_shared/resolvers/get-line-spacing-before-selection.js";
import { getLineSpacingInSelection } from "./../../_shared/resolvers/get-line-spacing-in-selection.js";
import { getTextColorInSelection } from "./../../_shared/resolvers/get-text-color-in-selection.js";
import { isBoldInText } from "./../../_shared/resolvers/is-bold-in-text.js";
import { isItalicInText } from "./../../_shared/resolvers/is-italic-in-text.js";
import { isRedoStackEmpty } from "./../../_shared/resolvers/is-redo-stack-empty.js";
import { isSpoilerInText } from "./../../_shared/resolvers/is-spoiler-in-text.js";
import { isStrikethroughInText } from "./../../_shared/resolvers/is-striketrough-in-text.js";
import { isSuperscriptInText } from "./../../_shared/resolvers/is-superscript-in-text.js";
import { isUnderlineInText } from "./../../_shared/resolvers/is-underline-in-text.js";
import { isUndoStackEmpty } from "./../../_shared/resolvers/is-undo-stack-empty.js";
import { unreachable } from "./../../_shared/uncreachable.js";
import {
  useContextSelectorWithValue
} from "./../../_shared/use-context-selector.js";
import { findChildrenInRange, findParentNodeClosestToPos } from "./../../tiptap/index.js";
import { NodeSelection, TextSelection } from "./../../tiptap/pm/state.js";
import {
  FORMATTING_BUTTONS,
  INSERT_PLUGIN_BUTTONS,
  TOOLBARS,
  isTextSelection
} from "./../../editor-common/index.js";
import { useInlineAiStateWithSelectorContextValue } from "./../../plugin-inline-ai/inline-ai-context-provider.js";
import { getDefaultToolbarSettings } from "./../../toolbars-v3/default-toolbar-settings.js";
import { mapButtonsFromConfig } from "./../../toolbars-v3/map-buttons-from-config.js";
import { toResolvedAttributes } from "./../../toolbars-v3/to-resolved-attributes.js";
import { toSchemaBasedId } from "./../../toolbars-v3/to-schema-base-id.js";
import { TO_TIPTAP_TYPE } from "../consts.js";
import { convertInlineStylesToCSS } from "../helpers/convert-inline-styles-to-css.js";
import { findNodeById } from "../helpers/index.js";
class RichContentAdapter {
  constructor(tiptapEditor, services, toolbarSettings, getToolbarStateSelectorContextValue, getSelectionSelectorContextValue, getModalStateSelectorContextValue, pmContentSelectorContextValue, getInlineAiStateSelectorContextValue) {
    this.tiptapEditor = tiptapEditor;
    this.useWixelToolbarProps = ({
      selection,
      resolvedToolbarSettings
    }) => {
      const pluginToolbar = this.services.plugins.getVisibleToolbar(
        this.tiptapEditor.state.selection,
        {
          adapter: { tiptapEditor: this.tiptapEditor },
          getPublicCommands: this.getEditorCommands
        }
      );
      if (pluginToolbar && (selection?.to === selection?.from || selection instanceof NodeSelection || selection?.toJSON()?.type === "cell")) {
        return {
          toolbarType: ToolbarType.PLUGIN,
          buttons: toExternalPluginToolbarButtons({
            buttons: pluginToolbar.getButtons(),
            editor: this.tiptapEditor,
            publicCommands: this.getEditorCommands(),
            modals: this.services.modals
          })
        };
      }
      const toolbarType = ToolbarType.FORMATTING;
      const toolbarSettingsFunctions = resolvedToolbarSettings.find(
        (toolbar) => toolbar?.name === toolbarType
      );
      const textButtons = this.services.plugins.getTextButtons();
      return {
        toolbarType,
        buttons: toExternalTextButtonsToolbarConfigs({
          textButtons,
          services: this.services,
          toolbarSettingsFunctions,
          toolbarType,
          publicCommands: this.getEditorCommands(),
          editor: this.tiptapEditor,
          isMobile: this.services.context.isMobile,
          editorQuery: this.services.getEditorQuery()
        })
      };
    };
    this.openModal = (options) => {
      if (options.type === "SHORTCUTS_SHEET") {
        this.services.modals.openModal({
          id: SHORTCUT_SHEET_MODAL_ID,
          Component: ShortcutsDialog,
          componentProps: {},
          dragHandleSelector: "[data-drag-handler]",
          enableDrag: true,
          layout: "floating",
          positioning: {
            referenceElement: this.tiptapEditor.view.dom,
            placement: "right-start"
          }
        });
        return;
      }
      const openFn = this.services.plugins.getExports().modals?.[options.type];
      if (!openFn) {
        console.error(
          `No such modal type ${options.type}, are you sure you added appropriate plugin?`
        );
        return;
      }
      openFn(this.tiptapEditor, { ...this.services, publicCommands: this.getEditorCommands() });
    };
    this.getContainer = () => {
      return this.tiptapEditor?.options?.element;
    };
    this.getDocumentStyle = () => this.tiptapEditor?.getJSON()?.attrs?.documentStyle || {};
    this.editorMocks = {
      getAnchorableBlocks: () => ({
        anchorableBlocks: [],
        pluginsIncluded: []
      }),
      getTextAlignment: () => this.services.content.resolve(getAlignmentInSelection),
      isBlockTypeSelected: () => false,
      isUndoStackEmpty: () => this.services.content.resolve(isUndoStackEmpty),
      isRedoStackEmpty: () => this.services.content.resolve(isRedoStackEmpty),
      getSelectedData: () => "blah",
      getPluginsList: () => {
        return this.services.editorProps.plugins?.map(
          (p) => legacyPluginToNextMap[p.type] ?? legacyPluginToNextMap[lodash.camelCase(p.type)]
        ) ?? [];
      },
      scrollToBlock: (_nodeId) => {
      },
      isBlockInContent: (_nodeId) => false,
      toggleBlockOverlay: (_nodeId) => false,
      getBlockSpacing: () => {
        const lineHeight = this.services.content.resolve(getLineSpacingInSelection);
        const paddingTop = this.services.content.resolve(getLineSpacingBeforeSelection);
        const paddingBottom = this.services.content.resolve(getLineSpacingAfterSelection);
        return {
          "line-height": lineHeight,
          "padding-top": paddingTop,
          "padding-bottom": paddingBottom
        };
      },
      saveEditorState: () => {
      },
      loadEditorState: () => {
      },
      saveSelectionState: () => {
      },
      loadSelectionState: () => {
      },
      setBlockType: () => {
      },
      _setSelection: () => {
      },
      getAnchorBlockInlineStyles: () => {
        return {};
      },
      getInlineStylesInSelection: () => {
        const {
          state: {
            doc,
            selection: { from, to }
          }
        } = this.tiptapEditor;
        let node;
        doc.nodesBetween(from, to, (currNode) => {
          if ([Node_Type.PARAGRAPH, Node_Type.HEADING].includes(
            currNode?.type?.name
          )) {
            node = this.services.converters.fromPmNode({
              ...currNode.toJSON(),
              type: currNode?.type?.name
            });
            return false;
          }
        });
        return node ? convertInlineStylesToCSS(node) : {};
      },
      getWiredFontStyles: () => {
        const container = this.getContainer();
        const styles = window.getComputedStyle(container);
        return Object.entries(DOC_STYLE_TYPES).reduce((acc, [key, docType]) => {
          const toPropertyValue = (property) => ({
            [property]: styles.getPropertyValue(`--ricos-custom-${key.toLowerCase()}-${property}`)
          });
          return {
            ...acc,
            [docType]: {
              ...toPropertyValue("font-size"),
              ...toPropertyValue("font-family"),
              ...toPropertyValue("color"),
              ...toPropertyValue("background-color")
            }
          };
        }, {});
      },
      isAtomicBlockInSelection: () => false,
      isTextBlockInSelection: () => true,
      getAnchorBlockType: () => "paragraph",
      focus: (focusPosition) => this.focus(focusPosition)
    };
    this.tiptapEditor = tiptapEditor;
    this.getEditorCommands = this.getEditorCommands.bind(this);
    this.getToolbarProps = (type) => {
      if (type === ToolbarType.INSERT_PLUGIN) {
        const addButtons = services.plugins.getAddButtons();
        const toolbarSettingsFunctions2 = getToolbarConfig(toolbarSettings, type);
        return {
          buttons: toExternalAddButtonsToolbarConfigs(
            addButtons,
            toolbarSettingsFunctions2,
            type,
            services.t,
            services.pluginsEvents,
            this.getEditorCommands(),
            services.context.isMobile
          )
        };
      }
      const toolbarType = TOOLBARS.FORMATTING;
      const textButtons = services.plugins.getTextButtons();
      const toolbarSettingsFunctions = getToolbarConfig(toolbarSettings, toolbarType);
      return {
        buttons: toExternalTextButtonsToolbarConfigs({
          textButtons,
          services: this.services,
          toolbarSettingsFunctions,
          toolbarType,
          publicCommands: this.getEditorCommands(),
          editor: this.tiptapEditor,
          isMobile: services.context.isMobile,
          editorQuery: services.getEditorQuery()
        })
      };
    };
    this.services = services;
    this.useUndoState = () => {
      useContextSelectorWithValue(pmContentSelectorContextValue(), (v) => v, Object.is);
      return {
        isUndoStackEmpty: !this.tiptapEditor.can().undo(),
        isRedoStackEmpty: !this.tiptapEditor.can().redo()
      };
    };
    this.useInlineAiState = (invocationId) => {
      return useInlineAiStateWithSelectorContextValue(
        getInlineAiStateSelectorContextValue(),
        invocationId,
        void 0
      );
    };
    this.useToolbarProps = (type) => {
      const resolvedToolbarSettings = useContextSelectorWithValue(
        getToolbarStateSelectorContextValue(),
        (v) => v.resolvedToolbarSettings,
        Object.is
      );
      useContextSelectorWithValue(getModalStateSelectorContextValue(), (v) => v, Object.is);
      useContextSelectorWithValue(pmContentSelectorContextValue(), (v) => v, Object.is);
      const selection = useContextSelectorWithValue(
        getSelectionSelectorContextValue(),
        (v) => v.selection,
        Object.is
      );
      const toolbarSettingsFunctions = resolvedToolbarSettings.find(
        (toolbar) => toolbar?.name === type
      );
      if (type === "WIXEL") {
        return this.useWixelToolbarProps({ selection, resolvedToolbarSettings });
      }
      if (type === TOOLBARS.INSERT_PLUGIN) {
        const addButtons = services.plugins.getAddButtons();
        return {
          buttons: toExternalAddButtonsToolbarConfigs(
            addButtons,
            toolbarSettingsFunctions,
            type,
            services.t,
            services.pluginsEvents,
            this.getEditorCommands(),
            services.context.isMobile
          )
        };
      }
      if (type === TOOLBARS.QUICK_ACTIONS) {
        return {
          buttons: Object.fromEntries(
            services.plugins.getQuickActions().map((quickAction) => [
              quickAction.id,
              {
                name: quickAction.id,
                getIcon: () => quickAction.icon,
                getLabel: () => quickAction.title,
                onClick: ({ referenceElement }) => quickAction.command({
                  editor: this.tiptapEditor,
                  publicCommands: this.getEditorCommands(),
                  modalService: this.services.modals,
                  referenceElement
                }),
                tags: quickAction.tags,
                dataHook: quickAction.id
              }
            ])
          )
        };
      }
      if (type === TOOLBARS.PLUGIN) {
        const pluginToolbar = services.plugins.getVisibleToolbar(
          this.tiptapEditor.state.selection,
          {
            adapter: { tiptapEditor: this.tiptapEditor },
            getPublicCommands: this.getEditorCommands
          }
        );
        const isVisible = isPluginToolbarVisible(selection, this.tiptapEditor.state.doc);
        if (!pluginToolbar || isVisible) {
          return { buttons: {} };
        }
        return {
          buttons: toExternalPluginToolbarButtons({
            buttons: pluginToolbar.getButtons(),
            editor: this.tiptapEditor,
            publicCommands: this.getEditorCommands(),
            modals: this.services.modals
          })
        };
      }
      const textButtons = this.services.plugins.getTextButtons();
      return {
        buttons: toExternalTextButtonsToolbarConfigs({
          textButtons,
          services: this.services,
          toolbarSettingsFunctions,
          toolbarType: type,
          publicCommands: this.getEditorCommands(),
          editor: this.tiptapEditor,
          isMobile: services.context.isMobile,
          editorQuery: services.getEditorQuery()
        })
      };
    };
    this.useToolbarWixelProps = () => {
      const resolvedToolbarSettings = useContextSelectorWithValue(
        getToolbarStateSelectorContextValue(),
        (v) => v.resolvedToolbarSettings,
        Object.is
      );
      useContextSelectorWithValue(getModalStateSelectorContextValue(), (v) => v, Object.is);
      useContextSelectorWithValue(pmContentSelectorContextValue(), (v) => v, Object.is);
      const selection = useContextSelectorWithValue(
        getSelectionSelectorContextValue(),
        (v) => v.selection,
        Object.is
      );
      const { buttons, toolbarType } = this.useWixelToolbarProps({
        selection,
        resolvedToolbarSettings
      });
      return {
        buttons,
        toolbarType,
        isEditorOrPortalFocused: () => {
          if (this.tiptapEditor.isFocused) {
            return true;
          }
          const activeElement = document.activeElement;
          const ricosPortal = this.services.context.portal;
          if (!activeElement || !ricosPortal) {
            return false;
          }
          return ricosPortal.contains(activeElement);
        }
      };
    };
  }
  focus(focusPosition) {
    this.tiptapEditor.commands.focus(focusPosition);
  }
  blur() {
    this.tiptapEditor.commands.blur();
  }
  setTiptapContent(content) {
    this.tiptapEditor.commands.setContent(content);
  }
  getEditorCommands() {
    const hasInlineStyle = (style) => {
      const resolvedStyles = {
        bold: this.services.content.resolve(isBoldInText),
        italic: this.services.content.resolve(isItalicInText),
        underline: this.services.content.resolve(isUnderlineInText),
        spoiler: this.services.content.resolve(isSpoilerInText),
        strikethrough: this.services.content.resolve(isStrikethroughInText),
        superscript: this.services.content.resolve(isSuperscriptInText)
      };
      return resolvedStyles[style];
    };
    return {
      ...this.editorMocks,
      getContent: this.services.schema.getContent,
      getDocumentStyle: this.getDocumentStyle,
      toggleInlineStyle: (inlineStyle) => {
        const editorCommand = this.tiptapEditor.chain();
        switch (inlineStyle) {
          case "bold":
            editorCommand.toggleBold().run();
            return;
          case "underline":
            editorCommand.toggleUnderline().run();
            return;
          case "italic":
            editorCommand.toggleItalic().run();
            return;
          case "spoiler":
            editorCommand.toggleSpoiler().run();
            return;
          case "strikethrough":
            editorCommand.toggleStrikethrough().run();
            return;
          case "superscript":
            editorCommand.toggleSuperscript().run();
            return;
          case "subscript":
            editorCommand.toggleSubscript().run();
            return;
          case "not_superscript":
          case "not_bold":
          case "not_italic":
          case "not_underline":
          case "not_strikethrough":
          case "not_subscript":
            return;
          default:
            console.error(unreachable(inlineStyle));
            return;
        }
      },
      hasInlineStyle,
      insertBlock: (pluginType, data = {}) => {
        const type = TO_TIPTAP_TYPE[pluginType];
        let id = "";
        if (!type) {
          console.error(`No such plugin type ${pluginType}`);
          return id;
        }
        let { content, ..._attrs } = data;
        id = data.id || generateId();
        let attrs = { id, ...flatComponentState(_attrs) };
        if (type === TIPTAP_FIGURE_TYPE && !content) {
          const normalizedData = normalizeFigureData(pluginType, data, id);
          content = normalizedData.content;
          attrs = normalizedData.attrs;
        }
        this.tiptapEditor.chain().focus().command(adjustSelectionForValidInsertion).insertContent([{ type, attrs, content }]).run();
        return id;
      },
      insertBlockWithBlankLines: (pluginType, data = {}, settings = {}) => {
        const defaultSettings = {
          updateSelection: true,
          skipBlankLineBefore: true,
          skipBlankLineAfter: true
        };
        const mergedSettings = { ...defaultSettings, ...settings };
        const type = TO_TIPTAP_TYPE[pluginType];
        let id = "";
        if (!type) {
          console.error(`No such plugin type ${pluginType}`);
          return id;
        }
        id = data.id || generateId();
        let { content, ..._attrs } = data;
        let attrs = { id, ...flatComponentState(_attrs) };
        if (type === TIPTAP_FIGURE_TYPE && !content) {
          const normalizedData = normalizeFigureData(pluginType, data, id);
          content = normalizedData.content;
          attrs = normalizedData.attrs;
        }
        const { updateSelection } = mergedSettings;
        this.tiptapEditor.chain().focus().command(adjustSelectionForValidInsertion).command(({ commands, dispatch, tr }) => {
          if (!dispatch) {
            return true;
          }
          const selectionRange = { from: tr.selection.from, to: tr.selection.to };
          const insertPos = mergedSettings.pos ?? getLayoutInsertPos(tr, pluginType) ?? selectionRange;
          const cmd = commands.insertContentAt(insertPos, [
            ...mergedSettings.skipBlankLineBefore ? [] : [{ type: Node_Type.PARAGRAPH, attrs: { id: generateId() } }],
            { type, attrs, content },
            ...mergedSettings.skipBlankLineAfter ? [] : [{ type: Node_Type.PARAGRAPH, attrs: { id: generateId() } }]
          ]);
          return dispatch(cmd);
        }).command(({ commands, dispatch, tr }) => {
          if (!updateSelection || !dispatch) {
            return false;
          }
          const nodeWithPos = findNodeById(tr, id)[0];
          if (!nodeWithPos) {
            return false;
          }
          const selectCommand = updateSelection === "text" ? commands.setTextSelection(nodeWithPos.pos) : commands.setNodeSelection(nodeWithPos.pos);
          return dispatch(selectCommand);
        }).run();
        return id;
      },
      deleteBlock: (nodeId) => {
        const nodesWithPos = findNodeById(this.tiptapEditor.state.tr, nodeId);
        if (nodesWithPos[0].node.type.name === TIPTAP_IMAGE_TYPE) {
          const figures = this.tiptapEditor.$nodes(TIPTAP_FIGURE_TYPE);
          const selectedFigure = figures?.find((f) => {
            return f.firstChild?.node.attrs.id === nodeId;
          });
          if (selectedFigure) {
            return this.tiptapEditor.commands.deleteNode(selectedFigure.attributes.id);
          }
          return this.tiptapEditor.commands.deleteNode(nodeId);
        }
        return this.tiptapEditor.commands.deleteNode(nodeId);
      },
      setBlock: (nodeId, _, data) => {
        return this.tiptapEditor.commands.setNodeAttrsById(nodeId, flatComponentState(data));
      },
      updateBlock: (nodeId, _, data) => {
        return this.tiptapEditor.commands.updateNodeAttrsById(nodeId, flatComponentState(data));
      },
      getColor: (colorType) => this.services.content.resolve(
        colorType === "ricos-text-color" ? getTextColorInSelection : getHighlightColorInSelection
      ),
      getSelection: () => {
        const {
          state: {
            doc,
            selection: { from, to }
          }
        } = this.tiptapEditor;
        const selectedNodes = [];
        doc.nodesBetween(from, to, (node) => {
          selectedNodes.push(node);
        });
        const hasSelectionNodes = selectedNodes.length > 0;
        return {
          isFocused: this.tiptapEditor.isFocused,
          isCollapsed: this.tiptapEditor.state.selection.empty,
          startKey: hasSelectionNodes ? selectedNodes[0].attrs.id : "",
          endKey: hasSelectionNodes ? selectedNodes[selectedNodes.length - 1].attrs.id : "",
          textContent: doc.cut(from, to).textContent,
          selectedNodes,
          isEditorOrPortalFocused: () => {
            if (this.tiptapEditor.isFocused) {
              return true;
            }
            const activeElement = document.activeElement;
            const ricosPortal = this.services.context.portal;
            if (!activeElement || !ricosPortal) {
              return false;
            }
            return ricosPortal.contains(activeElement);
          }
        };
      },
      getSelectionSlice: () => {
        const state = this.tiptapEditor.state;
        if (this.tiptapEditor.state.selection.empty) {
          return void 0;
        }
        const content = state.selection.content();
        if ([TIPTAP_IMAGE_TYPE, TIPTAP_GIF_TYPE, TIPTAP_VIDEO_TYPE].includes(
          content.content.firstChild?.type.name
        )) {
          const figureContent = NodeSelection.create(state.doc, state.selection.from - 1).content().toJSON();
          return this.services.converters.fromPmNodeChildren(figureContent);
        }
        return this.services.converters.fromPmNodeChildren(content.toJSON());
      },
      insertDecoration: (type, data, settings) => {
        const decorationCommandMap = {
          [RICOS_LINK_TYPE]: (data2) => ({
            command: "setLink",
            args: { link: data2 }
          }),
          [RICOS_ANCHOR_TYPE]: (data2) => ({
            command: "setAnchor",
            args: data2
          }),
          [RICOS_TEXT_COLOR_TYPE]: (data2) => ({
            command: "setColor",
            args: data2.color
          }),
          [RICOS_TEXT_HIGHLIGHT_TYPE]: (data2) => ({
            command: "setHighlight",
            args: data2.color
          }),
          [RICOS_MENTION_TYPE]: (data2) => ({
            command: "insertMention",
            args: data2.mention
          }),
          [RICOS_INDENT_TYPE]: () => ({ command: "indent", args: void 0 }),
          [RICOS_FONT_SIZE_TYPE]: (data2) => ({
            command: "setFontSize",
            args: parseInt(data2.fontSize, 10)
          }),
          FONT_FAMILY: (data2) => {
            return {
              command: "setFontFamily",
              args: data2.value
            };
          },
          [RICOS_LINE_SPACING_TYPE]: (data2) => ({
            command: "setLineSpacings",
            args: data2.data
          })
        };
        const decorationCommand = decorationCommandMap[type];
        if (decorationCommand) {
          const { command, args } = decorationCommand(data);
          const editorCommand = settings?.shouldFocus ? this.tiptapEditor.chain().focus() : this.tiptapEditor.chain();
          editorCommand[command](args).run();
        } else {
          console.error(`${type} decoration not supported`);
        }
      },
      insertMultipleAnchors: (anchors) => {
        const content = anchors.map((anchor) => {
          return this.tiptapEditor.schema.nodes.PARAGRAPH.create(
            null,
            this.tiptapEditor.schema.text(anchor.defaultName || "", [
              this.tiptapEditor.schema.marks.ANCHOR.create(anchor),
              this.tiptapEditor.schema.mark(Mark_Type.UNDERLINE)
            ])
          ).toJSON();
        });
        return this.tiptapEditor.commands.insertContent(content);
      },
      getFontSize: () => {
        return this.services.content.resolve(getFontSizeInSelection);
      },
      getFontFamily: () => {
        return this.services.content.resolve(getFontFamilyInSelection);
      },
      hasLinkInSelection: (options) => {
        const {
          state: {
            doc,
            selection: { from, to }
          }
        } = this.tiptapEditor;
        const selectionFrom = options?.inclusive ? from - 1 : from;
        const marks = {};
        doc.nodesBetween(selectionFrom, to, (node) => {
          node.marks.forEach(({ type: { name } }) => {
            marks[name] = true;
          });
        });
        return !!(marks[Decoration_Type.LINK] || marks[Decoration_Type.ANCHOR]);
      },
      selectLinkDecoration: (decoration, options) => {
        const decorationTypeMap = {
          [RICOS_LINK_TYPE]: Decoration_Type.LINK,
          [RICOS_ANCHOR_TYPE]: Decoration_Type.ANCHOR
        };
        const decorationMarkType = decorationTypeMap[decoration];
        if (!decorationMarkType) {
          console.error(`${decoration} decoration not supported`);
        }
        const {
          state: {
            doc,
            selection: { from, to }
          }
        } = this.tiptapEditor;
        const selectionFrom = options?.inclusive ? from - 1 : from;
        const decoratedNodes = findChildrenInRange(doc, { from: selectionFrom, to }, (child) => {
          return !!child.marks?.find((mark) => mark.type.name === decorationMarkType);
        });
        const nodeWithPos = decoratedNodes[0];
        if (nodeWithPos) {
          nodeWithPos && this.tiptapEditor.commands.setNodeSelection(nodeWithPos.pos);
        } else {
          console.error(`${decoration} node with decoration not found`);
        }
      },
      getLinkDataInSelection: (options) => {
        const {
          state: {
            doc,
            selection: { from, to }
          }
        } = this.tiptapEditor;
        const selectionFrom = options?.inclusive ? from - 1 : from;
        let link;
        doc.nodesBetween(selectionFrom, to, (node) => {
          node.marks.forEach((mark) => {
            const {
              type: { name }
            } = mark;
            if (name === Decoration_Type.LINK) {
              link = mark.attrs.link;
            } else if (name === Decoration_Type.ANCHOR) {
              link = { anchor: mark.attrs.anchor };
            }
          });
        });
        return link;
      },
      setBlockType: (type) => {
        const blockTypeCommandMap = {
          // oxlint-disable-next-line @typescript-oxlint/ban-ts-comment
          // @ts-ignore
          [UNSTYLED]: () => this.tiptapEditor.chain().focus().setParagraph().run(),
          [HEADER_BLOCK.ONE]: () => (
            // oxlint-disable-next-line @typescript-oxlint/ban-ts-comment
            // @ts-ignore
            this.tiptapEditor.chain().focus().toggleHeading({ level: 1 }).run()
          ),
          [HEADER_BLOCK.TWO]: () => (
            // oxlint-disable-next-line @typescript-oxlint/ban-ts-comment
            // @ts-ignore
            this.tiptapEditor.chain().focus().toggleHeading({ level: 2 }).run()
          ),
          [HEADER_BLOCK.THREE]: () => (
            // oxlint-disable-next-line @typescript-oxlint/ban-ts-comment
            // @ts-ignore
            this.tiptapEditor.chain().focus().toggleHeading({ level: 3 }).run()
          ),
          [HEADER_BLOCK.FOUR]: () => (
            // oxlint-disable-next-line @typescript-oxlint/ban-ts-comment
            // @ts-ignore
            this.tiptapEditor.chain().focus().toggleHeading({ level: 4 }).run()
          ),
          [HEADER_BLOCK.FIVE]: () => (
            // oxlint-disable-next-line @typescript-oxlint/ban-ts-comment
            // @ts-ignore
            this.tiptapEditor.chain().focus().toggleHeading({ level: 5 }).run()
          ),
          [HEADER_BLOCK.SIX]: () => (
            // oxlint-disable-next-line @typescript-oxlint/ban-ts-comment
            // @ts-ignore
            this.tiptapEditor.chain().focus().toggleHeading({ level: 6 }).run()
          ),
          // oxlint-disable-next-line @typescript-oxlint/ban-ts-comment
          // @ts-ignore
          [BLOCKQUOTE]: () => this.tiptapEditor.commands.toggleBlockquote(),
          // oxlint-disable-next-line @typescript-oxlint/ban-ts-comment
          // @ts-ignore
          [CODE_BLOCK_TYPE]: () => this.tiptapEditor.commands.toggleCodeBlock(),
          // oxlint-disable-next-line @typescript-oxlint/ban-ts-comment
          // @ts-ignore
          [BULLET_LIST_TYPE]: () => this.tiptapEditor.commands.toggleBulletList(),
          [CHECKBOX_LIST_TYPE]: () => this.tiptapEditor.commands.toggleCheckboxList(),
          // oxlint-disable-next-line @typescript-oxlint/ban-ts-comment
          // @ts-ignore
          [NUMBERED_LIST_TYPE]: () => this.tiptapEditor.commands.toggleOrderedList()
        };
        const currentSetBlockTypeCommand = blockTypeCommandMap[type];
        if (currentSetBlockTypeCommand) {
          currentSetBlockTypeCommand();
        } else {
          throw new Error(`${type} block type not supported`);
        }
      },
      // What the hell is block type lol. Is like, collapsible list not a block type?
      isBlockTypeSelected: (type) => {
        const blockTypeActiveCommandMap = {
          [UNSTYLED]: () => this.tiptapEditor.isActive("unstyled"),
          // This is the ONLY correct way to check if a node/mark is active
          // Node_Type shouldn't be used BUT its better than nothing
          [HEADER_BLOCK.ONE]: () => this.tiptapEditor.isActive(Node_Type.HEADING, { level: 1 }),
          [HEADER_BLOCK.TWO]: () => this.tiptapEditor.isActive(Node_Type.HEADING, { level: 2 }),
          [HEADER_BLOCK.THREE]: () => this.tiptapEditor.isActive(Node_Type.HEADING, { level: 3 }),
          [HEADER_BLOCK.FOUR]: () => this.tiptapEditor.isActive(Node_Type.HEADING, { level: 4 }),
          [HEADER_BLOCK.FIVE]: () => this.tiptapEditor.isActive(Node_Type.HEADING, { level: 5 }),
          [HEADER_BLOCK.SIX]: () => this.tiptapEditor.isActive(Node_Type.HEADING, { level: 6 }),
          [CODE_BLOCK_TYPE]: () => this.tiptapEditor.isActive(Node_Type.CODE_BLOCK),
          [BLOCKQUOTE]: () => this.tiptapEditor.isActive(Node_Type.BLOCKQUOTE),
          [NUMBERED_LIST_TYPE]: () => this.tiptapEditor.isActive(Node_Type.ORDERED_LIST),
          [BULLET_LIST_TYPE]: () => this.tiptapEditor.isActive(Node_Type.BULLETED_LIST),
          [CHECKBOX_LIST_TYPE]: () => this.tiptapEditor.isActive(Node_Type.CHECKBOX_LIST)
        };
        const currentBlockTypeActiveCommand = blockTypeActiveCommandMap[type];
        if (currentBlockTypeActiveCommand) {
          return currentBlockTypeActiveCommand();
        } else {
          throw new Error(`${type} block type not supported`);
        }
      },
      deleteDecoration: (type) => {
        switch (type) {
          case RICOS_LINK_TYPE:
            this.tiptapEditor.commands.unsetLink();
            return;
          case RICOS_ANCHOR_TYPE:
            this.tiptapEditor.commands.unsetAnchor();
            return;
          case RICOS_INDENT_TYPE:
            this.tiptapEditor.commands.outdent();
            return;
          case RICOS_TEXT_COLOR_TYPE:
            this.tiptapEditor.commands.unsetColor();
            return;
          case RICOS_TEXT_HIGHLIGHT_TYPE:
            this.tiptapEditor.commands.unsetHighlight();
            return;
          default:
            console.error(`delete ${type} decoration type not supported`);
        }
      },
      setTextAlignment: (alignment) => {
        this.tiptapEditor.chain().focus().setTextAlign(alignment).run();
      },
      undo: () => this.tiptapEditor.chain().focus().undo().run(),
      redo: () => this.tiptapEditor.chain().focus().redo().run(),
      insertText: (text, options = { preventAutolink: false }) => this.tiptapEditor.chain().focus().command(({ tr }) => {
        tr.insertText(text).setMeta("preventAutolink", options.preventAutolink);
        return true;
      }).run(),
      getAllBlocksKeys: () => {
        const keys = [];
        this.tiptapEditor.state.doc.descendants((node) => {
          keys.push(node.attrs.id);
        });
        return keys;
      },
      getBlockComponentData: (id) => {
        const nodesWithPos = findNodeById(this.tiptapEditor.state.tr, id);
        if (nodesWithPos[0]) {
          const { node } = nodesWithPos[0];
          return node.attrs;
        } else {
          console.error("Failed to find node and return its data");
        }
      },
      resetDocumentStyleByNodeType: (nodeType) => {
        this.tiptapEditor.chain().focus().unsetAllMarks().resetDocumentStyleByNodeType(nodeType).run();
      },
      updateDocumentStyle: (_documentStyles) => {
        this.tiptapEditor.commands.updateDocumentStyleBySelectedNode();
      },
      clearSelectedBlocksInlineStyles: () => {
        this.tiptapEditor.commands.unsetAllMarks();
      },
      getCurrentHeading: () => {
        return this.services.content.resolve(getHeadingInSelection);
      },
      triggerDecoration: (type) => {
        const triggerDecorationsMap = {
          [RICOS_MENTION_TYPE]: () => this.tiptapEditor.chain().focus().command(({ tr }) => {
            tr.insertText(" @");
            return true;
          }).run()
        };
        triggerDecorationsMap[type]?.();
      },
      softNewLine: () => {
        this.tiptapEditor.commands.setHardBreak();
      },
      clearEditorContent: (triggerUpdate = false) => {
        this.tiptapEditor.commands.clearContent(triggerUpdate);
      },
      setSpotlight: (list) => {
        this.tiptapEditor.commands.setSpotlightList(list);
      },
      // applies changes and returns reverse changes
      injectNodes: (args) => {
        const reverts = {};
        this.tiptapEditor.commands.injectNodes(args, reverts);
        return reverts.changes || [];
      },
      triggerInlineAi: (args) => {
        this.tiptapEditor.commands.triggerInlineAi({
          ...args,
          selection: this.getEditorCommands().getSelectionSlice() ?? []
        });
      },
      toggleAiSuggestions: (visible) => {
        this.tiptapEditor.commands.toggleSuggestions(visible);
      },
      setContent: (content, options) => {
        const nodes = [
          { nodes: content.nodes, position: { type: "range" } }
        ];
        if (options?.skipHistory) {
          return this.tiptapEditor.chain().command(({ tr }) => {
            tr.setMeta("addToHistory", false);
            return true;
          }).injectNodes(nodes, {}).run();
        }
        return this.tiptapEditor.commands.injectNodes(nodes, {});
      }
    };
  }
}
const flatComponentState = (data) => {
  const { componentState, ...rest } = data;
  return { ...rest || {}, ...componentState || {} };
};
const normalizeFigureData = (pluginType, data, mediaId) => {
  const isImage = [RICOS_IMAGE_TYPE, IMAGE_TYPE].includes(pluginType);
  const isGif = [RICOS_GIPHY_TYPE, GIPHY_TYPE].includes(pluginType);
  return {
    content: [
      {
        type: isImage ? TIPTAP_IMAGE_TYPE : isGif ? TIPTAP_GIF_TYPE : TIPTAP_VIDEO_TYPE,
        attrs: {
          id: mediaId,
          ...data
        }
      },
      {
        type: TIPTAP_CAPTION_TYPE
      }
    ],
    attrs: {
      id: generateId()
    }
  };
};
const getLayoutInsertPos = (tr, pluginType) => {
  if (pluginType !== RICOS_LAYOUT_TYPE) {
    return void 0;
  }
  const $from = tr.doc.resolve(tr.selection.from);
  const parentLayout = findParentNodeClosestToPos(
    $from,
    (node) => node.type.name === TIPTAP_LAYOUT_TYPE
  );
  return parentLayout ? parentLayout.pos + parentLayout.node.nodeSize : void 0;
};
const adjustSelectionForValidInsertion = ({ dispatch, tr }) => {
  if (dispatch === void 0) {
    return true;
  }
  const { selection } = tr;
  const { from, to } = selection;
  const resolvedFrom = tr.doc.resolve(from);
  const resolvedTo = tr.doc.resolve(to);
  const isFigureChildSelected = resolvedFrom.nodeAfter?.type.spec.group?.includes("figureFirstChildContent");
  if (isFigureChildSelected && from === to - 1) {
    tr.setSelection(NodeSelection.create(tr.doc, from - 1));
    dispatch(tr);
    return true;
  }
  const isFromCaption = resolvedFrom.parent.type.name === TIPTAP_CAPTION_TYPE;
  const isToCaption = resolvedTo.parent.type.name === TIPTAP_CAPTION_TYPE;
  if (!isFromCaption && !isToCaption) {
    return true;
  }
  if (from === to || resolvedFrom.parent.attrs.id === resolvedTo.parent.attrs.id) {
    const nodeAfter = tr.doc.resolve(resolvedFrom.after());
    tr.setSelection(TextSelection.create(tr.doc, nodeAfter.pos, nodeAfter.pos));
    dispatch(tr);
    return true;
  }
  const posFrom = isFromCaption ? tr.doc.resolve(resolvedFrom.after()).pos : from;
  const posTo = isToCaption ? tr.doc.resolve(resolvedTo.before()).pos - 1 : to;
  tr.setSelection(TextSelection.create(tr.doc, posFrom, posTo));
  dispatch(tr);
  return true;
};
const toExternalAddButtonsToolbarConfigs = (addButtons, toolbarSettingsFunctions, toolbarType, t, pluginsEvents, publicCommands, isMobile) => {
  const buttonsType = isMobile ? "mobile" : "desktop";
  const externalAddPluginToolbarItemsConfig = toExternalAddPluginToolbarItemsConfig(
    toolbarSettingsFunctions,
    addButtons,
    toolbarType,
    buttonsType
  );
  return externalAddPluginToolbarItemsConfig.reduce((acc, b) => {
    const buttonConfig = toExternalToolbarAddButtonConfig(b, t, pluginsEvents, publicCommands);
    return {
      ...acc,
      [buttonConfig.name || ""]: buttonConfig
    };
  }, {});
};
const pluginButtonNames = Object.values(INSERT_PLUGIN_BUTTONS);
const initToolbarSettings = (toolbarSettings) => {
  const textButtons = {
    mobile: mobileTextButtonList,
    desktop: desktopTextButtonList
  };
  const defaultSettings = getDefaultToolbarSettings({ textButtons, pluginButtonNames });
  if (!toolbarSettings?.getToolbarSettings) {
    return defaultSettings;
  }
  const customSettings = toolbarSettings.getToolbarSettings({
    textButtons,
    pluginButtonNames
  });
  return mergeToolbarSettings({ defaultSettings, customSettings });
};
const toExternalAddPluginToolbarItemsConfig = (toolbarConfig, addButtons, toolbarType, buttonsType) => {
  if (!toolbarConfig) {
    console.error(`${toolbarType} doesn't exists`);
    return [];
  }
  const buttonsListFromConfig = getButtonsListFromConfig(toolbarConfig, buttonsType);
  const externalToolbarItemsConfig = [];
  buttonsListFromConfig.map(fromConfigToSchemaBasedId).forEach((button) => {
    const buttonConfig = addButtons.find((b) => b.id === button);
    if (buttonConfig) {
      externalToolbarItemsConfig.push(buttonConfig);
    }
  });
  return externalToolbarItemsConfig;
};
const fromConfigToSchemaBasedId = (insertButtonId) => {
  const specificMapping = {
    [INSERT_PLUGIN_BUTTONS.IMAGE]: Node_Type.IMAGE,
    [INSERT_PLUGIN_BUTTONS.SHAPE]: Node_Type.SHAPE,
    [INSERT_PLUGIN_BUTTONS.GALLERY]: Node_Type.GALLERY,
    [INSERT_PLUGIN_BUTTONS.POLLS]: Node_Type.POLL,
    [INSERT_PLUGIN_BUTTONS.DIVIDER]: Node_Type.DIVIDER,
    [INSERT_PLUGIN_BUTTONS.HTML]: `${Node_Type.HTML}.html`,
    [INSERT_PLUGIN_BUTTONS.VIDEO]: `${Node_Type.VIDEO}.video`,
    [INSERT_PLUGIN_BUTTONS.INSTAGRAM]: `${Node_Type.LINK_PREVIEW}.instagram`,
    [INSERT_PLUGIN_BUTTONS.YOUTUBE]: `${Node_Type.VIDEO}.youTube`,
    [INSERT_PLUGIN_BUTTONS.TIKTOK]: `${Node_Type.LINK_PREVIEW}.tiktok`,
    [INSERT_PLUGIN_BUTTONS.TWITTER]: `${Node_Type.LINK_PREVIEW}.twitter`,
    [INSERT_PLUGIN_BUTTONS.PINTEREST]: `${Node_Type.LINK_PREVIEW}.pinterest`,
    [INSERT_PLUGIN_BUTTONS.FACEBOOK]: `${Node_Type.LINK_PREVIEW}.facebook`,
    [INSERT_PLUGIN_BUTTONS.STORES]: `${Node_Type.APP_EMBED}.product`,
    [INSERT_PLUGIN_BUTTONS.EVENTS]: `${Node_Type.APP_EMBED}.event`,
    [INSERT_PLUGIN_BUTTONS.BOOKINGS]: `${Node_Type.APP_EMBED}.booking`,
    [INSERT_PLUGIN_BUTTONS.BUTTON]: Node_Type.BUTTON,
    [INSERT_PLUGIN_BUTTONS.CODE_BLOCK]: Node_Type.CODE_BLOCK,
    [INSERT_PLUGIN_BUTTONS.SOUND_CLOUD]: `${Node_Type.AUDIO}.soundCloud`,
    [INSERT_PLUGIN_BUTTONS.GIF]: Node_Type.GIF,
    [INSERT_PLUGIN_BUTTONS.FILE]: Node_Type.FILE,
    [INSERT_PLUGIN_BUTTONS.EMOJI]: "wix-draft-plugin-emoji",
    [INSERT_PLUGIN_BUTTONS.UNDO]: "UNDO",
    [INSERT_PLUGIN_BUTTONS.REDO]: "REDO",
    [INSERT_PLUGIN_BUTTONS.TABLE]: Node_Type.TABLE,
    [INSERT_PLUGIN_BUTTONS.COLLAPSIBLE_LIST]: Node_Type.COLLAPSIBLE_LIST,
    [INSERT_PLUGIN_BUTTONS.ADSENSE]: `${Node_Type.HTML}.adsense`,
    [INSERT_PLUGIN_BUTTONS.AUDIO]: `${Node_Type.AUDIO}.audio`,
    [INSERT_PLUGIN_BUTTONS.SPOTIFY]: `${Node_Type.AUDIO}.spotify`,
    [INSERT_PLUGIN_BUTTONS.LAYOUT]: `${Node_Type.LAYOUT}.insert`
  };
  const id = specificMapping[insertButtonId];
  if (!id) {
    console.error(`toSchemaBasedId: unknown insertButtonId: ${insertButtonId}`);
  }
  return id;
};
const toExternalToolbarAddButtonConfig = (button, t, pluginsEvents, publicCommands) => {
  return {
    type: "button",
    tooltip: t(button.tooltip),
    toolbars: button.toolbars,
    getIcon: () => button.icon,
    getLabel: () => t(button.label),
    onClick: (_e) => {
      pluginsEvents.publishers.byTopic("ricos.toolbars.functionality.buttonClick").publish({
        toolbarType: TOOLBARS.EXTERNAL,
        buttonId: button.id
      });
      pluginsEvents.publishPluginAdd({
        pluginId: button.id,
        entryPoint: TOOLBARS.EXTERNAL
      });
      return button.command({
        publicCommands,
        // @ts-ignore
        referenceElement: {
          getBoundingClientRect: () => {
            const x = window.innerWidth / 2;
            const y = window.innerHeight / 2;
            return new DOMRect(x, y, 0, 0);
          }
        }
      });
    },
    isActive: () => false,
    isDisabled: () => false,
    dataHook: button.dataHook,
    name: button.label
  };
};
const toExternalTextButtonsToolbarConfigs = ({
  textButtons,
  services,
  toolbarSettingsFunctions,
  toolbarType,
  publicCommands,
  editor,
  isMobile,
  editorQuery
}) => {
  const buttonsType = isMobile ? "mobile" : "desktop";
  const externalToolbarItemsConfig = toExternalTextButtonsToolbarItemsConfig(
    toolbarSettingsFunctions,
    textButtons,
    toolbarType,
    buttonsType
  );
  return externalToolbarItemsConfig.reduce((acc, b) => {
    const buttonConfig = toExternalToolbarTextButtonConfig(
      b,
      publicCommands,
      editor,
      editorQuery,
      services
    );
    return {
      ...acc,
      [buttonConfig.name || ""]: buttonConfig
    };
  }, {});
};
const toExternalPluginToolbarButtons = ({
  buttons,
  editor,
  publicCommands,
  modals
}) => {
  return buttons.reduce((acc, toolbarButton) => {
    const { button, services } = toolbarButton;
    const { content } = services;
    const attributes = fromEntries(
      Object.entries(button.attributes || {}).map(([key, value]) => {
        return value ? [key, content.resolve(value)] : [key, void 0];
      })
    );
    if (attributes.visible === false) {
      return acc;
    }
    return {
      ...acc,
      [button.id]: button.type === "separator" ? {
        type: "separator",
        getIcon: () => button.icon,
        getLabel: () => {
        },
        onClick: () => {
        },
        isActive: () => false,
        isDisabled: () => false
      } : {
        type: button.type,
        tooltip: services.t(
          (typeof button.tooltip === "function" ? button.tooltip({ isActive: !!attributes.active }) : button.tooltip) || ""
        ),
        toolbars: [],
        getIcon: () => "getIcon" in button ? button.getIcon?.({ services, attributes }) : "icon" in button ? button.icon : void 0,
        getLabel: () => "label" in button && button.label ? services.t(button.label) : void 0,
        onClick: (e) => {
          const returnValue = button?.command?.({
            referenceElement: e?.referenceElement ?? e?.target,
            tiptapEditor: editor,
            publicCommands,
            attributes,
            modals,
            isMobile: services.context.isMobile,
            getComponentProps: "getComponentProps" in button ? button.getComponentProps : void 0
          });
          const node = attributes.selectedNode;
          services.pluginsEvents.publishPluginToolbarClick({
            pluginId: node?.type?.name,
            nodeId: node?.attrs?.id,
            buttonName: button?.id,
            value: e?.value
          });
          return returnValue;
        },
        componentProps: "getComponentProps" in button ? button.getComponentProps?.({
          tiptapEditor: editor,
          attributes,
          publicCommands,
          t: services.t,
          modals,
          languageDir: services.context.languageDir
        }) : void 0,
        isActive: () => !!attributes.active,
        isDisabled: () => !!attributes.disabled,
        dataHook: button.dataHook,
        name: button.id
      }
    };
  }, {});
};
const getToolbarConfig = (toolbarSettings, toolbarType) => {
  const finalToolbarSettings = initToolbarSettings(toolbarSettings);
  const toolbarConfig = finalToolbarSettings.find((setting) => setting.name === toolbarType);
  return toolbarConfig;
};
const toExternalTextButtonsToolbarItemsConfig = (toolbarConfig, textButtons, toolbarType, buttonsType) => {
  if (!toolbarConfig) {
    console.error(`${toolbarType} doesn't exists`);
    return [];
  }
  const buttonsListFromConfig = getButtonsListFromConfig(toolbarConfig, buttonsType);
  const buttonsList = buttonsListFromConfig.map(handleDeprecatedButtons).map(mapButtonsFromConfig).map(toSchemaBasedId);
  const externalToolbarItemsConfig = buttonsList.flatMap((button) => {
    const buttonConfig = textButtons.find((b) => b.id === button);
    if (buttonConfig) {
      return [buttonConfig];
    }
    return [];
  });
  return externalToolbarItemsConfig;
};
const handleDeprecatedButtons = (configButtonId) => {
  if (typeof configButtonId === "string") {
    return configButtonId;
  }
  if (configButtonId.name === "Alignment") {
    return FORMATTING_BUTTONS.ALIGNMENT;
  }
};
const toExternalToolbarTextButtonConfig = (button, publicCommands, editor, editorQuery, services, tooltipHint) => {
  const attributes = toResolvedAttributes(button);
  const { modals, content, context, t, pluginsEvents, styles } = services;
  const name = button.id in toExternalType ? toExternalType[button.id] : button.id;
  if (button.type === "separator") {
    return {
      type: "separator",
      getIcon: () => button.presentation.icon
    };
  }
  return {
    type: button.type,
    tooltip: `${t(button.presentation.tooltip)} ${tooltipHint ? `(${tooltipHint})` : ""}`,
    toolbars: [],
    componentProps: button.type === "dropdown" ? button.presentation.getComponentProps?.({
      publicCommands,
      t,
      modals,
      styles,
      editor
    }) : void 0,
    getIcon: () => "getIcon" in button.presentation ? button.presentation.getIcon({ publicCommands, t }) : button.presentation.icon,
    getLabel: () => t(name),
    onClick: (e) => {
      pluginsEvents.publishers.byTopic("ricos.toolbars.functionality.buttonClick").publish({
        toolbarType: ToolbarType.EXTERNAL,
        buttonId: button.id
      });
      const referenceElement = e?.referenceElement ?? e?.target;
      return button.command?.({
        publicCommands,
        modalService: modals,
        editor,
        editorQuery,
        referenceElement,
        isMobile: context.isMobile,
        componentProps: "getComponentProps" in button.presentation ? button.presentation.getComponentProps({
          publicCommands,
          t,
          modals,
          editor,
          styles
        }) : void 0
      })({});
    },
    isActive: () => !!attributes.active && !!content.resolve(attributes.active),
    isDisabled: () => !!attributes.disabled && !!content.resolve(attributes.disabled),
    dataHook: button.presentation?.dataHook,
    name
  };
};
const toExternalType = {
  [Decoration_Type.BOLD]: FORMATTING_BUTTONS.BOLD,
  [Decoration_Type.ITALIC]: FORMATTING_BUTTONS.ITALIC,
  [Decoration_Type.UNDERLINE]: FORMATTING_BUTTONS.UNDERLINE,
  [Decoration_Type.STRIKETHROUGH]: FORMATTING_BUTTONS.STRIKETHROUGH,
  [`${Node_Type.HEADING}.title`]: FORMATTING_BUTTONS.TITLE,
  [Node_Type.BLOCKQUOTE]: FORMATTING_BUTTONS.BLOCKQUOTE,
  "TextAlignment.ALIGNMENT": FORMATTING_BUTTONS.ALIGNMENT,
  "TextAlignment.LEFT": FORMATTING_BUTTONS.ALIGN_LEFT,
  "TextAlignment.CENTER": FORMATTING_BUTTONS.ALIGN_CENTER,
  "TextAlignment.RIGHT": FORMATTING_BUTTONS.ALIGN_RIGHT,
  "TextAlignment.JUSTIFY": FORMATTING_BUTTONS.ALIGN_JUSTIFY,
  [Node_Type.ORDERED_LIST]: FORMATTING_BUTTONS.ORDERED_LIST,
  [Node_Type.BULLETED_LIST]: FORMATTING_BUTTONS.UNORDERED_LIST,
  [Node_Type.CHECKBOX_LIST]: FORMATTING_BUTTONS.CHECKBOX_LIST,
  [Decoration_Type.FONT_SIZE]: FORMATTING_BUTTONS.FONT_SIZE,
  [Decoration_Type.SPOILER]: FORMATTING_BUTTONS.SPOILER,
  [Decoration_Type.LINK]: FORMATTING_BUTTONS.LINK,
  [`${Node_Type.HEADING}.dropdown`]: FORMATTING_BUTTONS.HEADINGS,
  [`${Decoration_Type.COLOR}.foreground`]: FORMATTING_BUTTONS.TEXT_COLOR,
  [`${Decoration_Type.COLOR}.background`]: FORMATTING_BUTTONS.TEXT_HIGHLIGHT,
  [Node_Type.CODE_BLOCK]: FORMATTING_BUTTONS.CODE_BLOCK,
  LINE_SPACING: FORMATTING_BUTTONS.LINE_SPACING,
  [`INDENT.increase`]: FORMATTING_BUTTONS.INCREASE_INDENT,
  [`INDENT.decrease`]: FORMATTING_BUTTONS.DECREASE_INDENT
};
const isPluginToolbarVisible = (selection, doc) => {
  if (!selection || selection.empty || !(selection instanceof NodeSelection)) {
    return false;
  }
  try {
    let hasNonEmptyParagraph = false;
    doc.nodesBetween(selection.from, selection.to, (node) => {
      if (node.type.name === "text" && node.text !== "") {
        hasNonEmptyParagraph = true;
        return false;
      }
    });
    return hasNonEmptyParagraph && isTextSelection(selection);
  } catch (error) {
    console.error("Error checking if plugin toolbar is visible", error);
    return false;
  }
};
export {
  RichContentAdapter
};
//# sourceMappingURL=rich-content-adapter.js.map
