import {
  Add,
  AddSmall,
  Catalog,
  CatalogSmall,
  LayoutThreeColumns,
  LayoutThreeColumnsSmall,
  LayoutTwoColumns,
  LayoutTwoColumnsSmall
} from "@wix/wix-ui-icons-common";
import lodash from "lodash";
import React, { useContext } from "react";
import { LAYOUT_DEFAULTS } from "./../../ricos-common-plugins/layout/shared-with-viewer.js";
import {
  RICOS_LAYOUT_TYPE,
  TIPTAP_CARD_FOOTER_TYPE,
  TIPTAP_CARD_HEADER_TYPE,
  TIPTAP_CARD_TYPE,
  TIPTAP_COLLAPSIBLE_LIST_TYPE,
  TIPTAP_LAYOUT_TYPE
} from "./../../ricos-content/index.js";
import { RicosContext } from "./../../ricos-context/index.js";
import { RicosPluginToolbarNames, quickActionsModalSections } from "./../../ricos-types/index.js";
import { createPluginToolbarButton } from "./../../_shared/create-plugin-toolbar-button.js";
import {
  PLUGIN_TOOLBAR_SET_AS_FOOTER_BUTTON,
  PLUGIN_TOOLBAR_SET_AS_HEADER_BUTTON
} from "./../../_shared/data-hooks.js";
import { BannerIcon } from "./../../_shared/icons/banner-icon.js";
import { FooterIcon } from "./../../_shared/icons/footer-icon.js";
import { createDeleteButton } from "./../../_shared/plugin-toolbar/create-delete-button.js";
import { createSettingsButton } from "./../../_shared/plugin-toolbar/create-settings-button.js";
import { createSeparator } from "./../../_shared/plugin-toolbar/separator/create-separator.js";
import { canSetAsBanner } from "./../../_shared/resolvers/can-set-as-banner.js";
import { canSetAsFooter } from "./../../_shared/resolvers/can-set-as-footer.js";
import { isAlwaysVisible } from "./../../_shared/resolvers/is-always-visible.js";
import { ToolbarButton } from "./../../_shared/toolbar-button/toolbar-button.js";
import { findParentNodeClosestToPos, posToDOMRect } from "./../../tiptap/index.js";
import { Fragment } from "./../../tiptap/pm/model.js";
import { NodeSelection, TextSelection } from "./../../tiptap/pm/state.js";
import { INSERT_PLUGIN_BUTTONS } from "./../../editor-common/index.js";
import { VERTICAL_ALIGNMENT_BUTTONS } from "./../../toolbars-v3/components/buttons/VerticalAlignmentButton/vertical-alignment-dropdown.js";
import {
  FLOATING_PLUGIN_TOOLBAR,
  VERTICAL_ALIGNMENT_MODAL_ID,
  VerticalAlignmentButton,
  VerticalAlignmentDropdown,
  verticalAlignmentIcons
} from "./../../toolbars-v3/index.js";
import { findNodeById } from "./../../tiptap-editor/helpers/index.js";
import {
  INSERT_LAYOUT_BUTTON,
  LAYOUT_PLUGIN_TOOLBAR_ADD_CELL_BUTTON,
  LAYOUT_SETTINGS_MODAL_ID,
  LAYOUT_TOOLBAR_VERTICAL_ALIGNMENT_BUTTON
} from "./data-hooks.js";
import { layoutConverter } from "./layout-converter.js";
import { layoutExtension } from "./layout-extension.js";
import { Settings } from "./layout-settings/settings.js";
import { LAYOUT_INSERT_MODAL_ID, LayoutInsertModal } from "./modals/layout-insert-modal.js";
import {
  createQuickActionBannerLayout,
  createBlankLayoutData,
  findParentCardId,
  getToolbarReferenceElement,
  toolbarsToAddIn
} from "./shared.js";
const isBannerLayoutNode = (node) => node?.type.name === TIPTAP_LAYOUT_TYPE && !!node.attrs?.banner;
const isEmptyTextBlock = (node) => node.isTextblock && node.content.size === 0;
const findEdgeBannerInDoc = (doc, isTop) => {
  const children = [];
  doc.forEach((node, pos) => children.push({ node, pos }));
  const ordered = isTop ? children : children.reverse();
  for (const { node, pos } of ordered) {
    if (isEmptyTextBlock(node)) {
      continue;
    }
    return isBannerLayoutNode(node) ? { node, pos } : null;
  }
  return null;
};
const findBottomInsertionPos = (doc) => {
  let pos = doc.content.size;
  const children = [];
  doc.forEach((node, p) => children.push({ node, pos: p }));
  for (let i = children.length - 1; i >= 0; i--) {
    if (isEmptyTextBlock(children[i].node)) {
      pos = children[i].pos;
    } else {
      break;
    }
  }
  return pos;
};
const createRegularLayoutNode = (node) => {
  const { banner: _banner, ...attrs } = node.attrs;
  return {
    type: TIPTAP_LAYOUT_TYPE,
    attrs,
    content: node.content.toJSON()
  };
};
const insertQuickActionBanner = (position) => (editor) => {
  const isTop = position === "TOP";
  const wrapperType = isTop ? TIPTAP_CARD_HEADER_TYPE : TIPTAP_CARD_FOOTER_TYPE;
  editor.chain().focus().command(({ tr, dispatch, state }) => {
    const { headingId, layoutNode } = createQuickActionBannerLayout(position);
    const cardId = findParentCardId(tr.doc, tr.selection.from);
    if (cardId) {
      const card = findNodeById(tr, cardId)[0];
      if (!card) {
        return false;
      }
      const newWrapper = state.schema.nodeFromJSON({
        type: wrapperType,
        content: [layoutNode]
      });
      let existingPos = -1;
      let existingSize = -1;
      card.node.forEach((child, offset) => {
        if (child.type.name === wrapperType && existingPos < 0) {
          existingPos = card.pos + 1 + offset;
          existingSize = child.nodeSize;
        }
      });
      if (existingPos >= 0) {
        tr.replaceWith(existingPos, existingPos + existingSize, newWrapper);
      } else {
        const insertPos = isTop ? card.pos + 1 : card.pos + card.node.nodeSize - 1;
        tr.insert(insertPos, newWrapper);
      }
    } else {
      const edge = findEdgeBannerInDoc(tr.doc, isTop);
      const demotedBanner = edge ? createRegularLayoutNode(edge.node) : void 0;
      const preDeleteInsertPos = isTop ? 0 : findBottomInsertionPos(tr.doc);
      if (edge && demotedBanner) {
        tr.deleteRange(edge.pos, edge.pos + edge.node.nodeSize);
      }
      const nodesToInsert = isTop ? [layoutNode, ...demotedBanner ? [demotedBanner] : []] : [...demotedBanner ? [demotedBanner] : [], layoutNode];
      const fragment = Fragment.fromArray(
        nodesToInsert.map((node) => state.schema.nodeFromJSON(node))
      );
      tr.insert(tr.mapping.map(preDeleteInsertPos), fragment);
    }
    const headingNode = findNodeById(tr, headingId)[0];
    if (headingNode) {
      tr.setSelection(TextSelection.create(tr.doc, headingNode.pos + 1));
    }
    if (dispatch) {
      dispatch(tr.scrollIntoView());
    }
    return true;
  }).run();
};
const pluginLayout = (config = {
  showInQuickActions: false,
  showInToolbars: false
}) => ({
  type: TIPTAP_LAYOUT_TYPE,
  config,
  pmMarkConverters: [],
  pmNodeConverters: [layoutConverter],
  tiptapExtensions: [layoutExtension],
  textButtons: [],
  toolbar: {
    names: [RicosPluginToolbarNames.LAYOUT],
    isVisible: isToolbarVisible,
    resolveReferenceElement: (tiptapEditor) => getToolbarReferenceElement(tiptapEditor),
    getButtons: (_, services) => [
      createSettingsButton({
        modalId: LAYOUT_SETTINGS_MODAL_ID,
        showLabel: true,
        attributes: {
          selectedNode: selectedNodeResolver
        },
        command: ({ isMobile, referenceElement, attributes: { selectedNode } }) => {
          services.modals?.togglePluginPanel({
            id: LAYOUT_SETTINGS_MODAL_ID,
            Component: Settings,
            componentProps: {
              referenceElement,
              nodeId: selectedNode.attrs.id,
              config
            },
            positioning: {
              referenceElement: referenceElement.closest(`[data-hook~=${FLOATING_PLUGIN_TOOLBAR}]`) ?? referenceElement,
              placement: "right-start"
            },
            onClickOutside: {
              on: "pointerup",
              handler: lodash.noop
            },
            focusReturnElement: referenceElement,
            isMobile
          });
        },
        buttonId: "layoutSettings"
      }),
      createSeparator(),
      {
        id: "layoutSetAsBanner",
        type: "toggle",
        tooltip: null,
        label: "Layouts_LayoutSetAsBanner_Tooltip",
        icon: BannerIcon,
        attributes: {
          selectedNode: selectedNodeResolver,
          visible: canSetAsBanner,
          active: isLayoutSetAsBannerActive
        },
        dataHook: PLUGIN_TOOLBAR_SET_AS_HEADER_BUTTON,
        renderer: (toolbarItem) => /* @__PURE__ */ React.createElement(LayoutSetAsHeaderButton, { toolbarItem }),
        command: ({ tiptapEditor, attributes: { selectedNode } }) => {
          const isTopBanner = selectedNode?.attrs?.banner?.position === "TOP";
          tiptapEditor.commands.setLayoutBanner(
            selectedNode.attrs.id,
            isTopBanner ? void 0 : { position: "TOP", origin: "LAYOUT" }
          );
        }
      },
      {
        id: "layoutSetAsFooter",
        type: "toggle",
        tooltip: null,
        label: "Layouts_LayoutSetAsFooter_Tooltip",
        icon: FooterIcon,
        attributes: {
          selectedNode: selectedNodeResolver,
          visible: canSetAsFooter,
          active: isLayoutSetAsFooterActive
        },
        dataHook: PLUGIN_TOOLBAR_SET_AS_FOOTER_BUTTON,
        renderer: (toolbarItem) => /* @__PURE__ */ React.createElement(LayoutSetAsFooterButton, { toolbarItem }),
        command: ({ tiptapEditor, attributes: { selectedNode } }) => {
          const isBottomBanner = selectedNode?.attrs?.banner?.position === "BOTTOM";
          tiptapEditor.commands.setLayoutBanner(
            selectedNode.attrs.id,
            isBottomBanner ? void 0 : { position: "BOTTOM", origin: "LAYOUT" }
          );
        }
      },
      createPluginToolbarButton({
        id: "layoutVerticalAlignment",
        type: "dropdown",
        tooltip: "Layouts_LayoutCellVerticalAlignment_Tooltip",
        dataHook: LAYOUT_TOOLBAR_VERTICAL_ALIGNMENT_BUTTON,
        Component: VerticalAlignmentDropdown,
        getComponentProps: ({ tiptapEditor, modals, attributes }) => {
          return {
            onSelect: (verticalAlignment) => {
              tiptapEditor.chain().focus().setLayoutCellsVerticalAlignment(
                attributes.selectedNode.attrs.id,
                verticalAlignment
              ).run();
            },
            dropdownOptions: Object.values(VERTICAL_ALIGNMENT_BUTTONS).map((item) => ({
              id: item.commandKey,
              dataHook: item.dataHook,
              label: services.t(item.tooltip),
              icon: item.iconSmall,
              iconMobile: item.icon
            })),
            closeModal: () => modals.closeModal(VERTICAL_ALIGNMENT_MODAL_ID),
            selectedId: attributes.selectedNode.attrs.cellVerticalAlignment || LAYOUT_DEFAULTS.cellVerticalAlignment
          };
        },
        command: ({
          tiptapEditor,
          modals,
          referenceElement,
          attributes,
          getComponentProps,
          publicCommands
        }) => {
          const closeModal = () => modals.closeModal(VERTICAL_ALIGNMENT_MODAL_ID);
          const isModalOpen = modals.isModalOpen(VERTICAL_ALIGNMENT_MODAL_ID);
          if (isModalOpen) {
            closeModal();
            return;
          }
          const componentProps = getComponentProps?.({
            tiptapEditor,
            attributes,
            publicCommands,
            t: services.t,
            modals,
            languageDir: services.context.languageDir
          });
          if (!componentProps) {
            return;
          }
          modals.openModal({
            id: VERTICAL_ALIGNMENT_MODAL_ID,
            Component: VerticalAlignmentDropdown,
            componentProps,
            layout: services.context.isMobile ? "drawer" : "floating",
            positioning: { referenceElement, placement: "bottom" }
          });
        },
        attributes: {
          selectedNode: selectedNodeResolver,
          verticalAlignment: getVerticalAlignmentResolver
        },
        renderer: (toolbarItem) => /* @__PURE__ */ React.createElement(VerticalAlignmentButton, { toolbarItem }),
        getIcon: ({ attributes }) => {
          const verticalAlignment = attributes.selectedNode.attrs?.cellVerticalAlignment || LAYOUT_DEFAULTS.cellVerticalAlignment;
          return verticalAlignmentIcons[verticalAlignment];
        }
      }),
      {
        id: "addCellToTheEnd",
        type: "toggle",
        dataHook: LAYOUT_PLUGIN_TOOLBAR_ADD_CELL_BUTTON,
        tooltip: "Layouts_LayoutAddCell_Tooltip",
        icon: Add,
        attributes: {
          selectedNode: selectedNodeResolver,
          alwaysVisible: isAlwaysVisible,
          disabled: (_2, __, editor) => {
            const selection = editor?.state?.selection;
            if (!selection) {
              return true;
            }
            const closest = selection instanceof NodeSelection && selection.node?.type.name === TIPTAP_LAYOUT_TYPE ? selection : findParentNodeClosestToPos(
              selection.$from,
              (node) => node.type.name === TIPTAP_LAYOUT_TYPE
            );
            return closest?.node.lastChild && editor ? !editor.can().addCellRight(closest.node.lastChild.attrs.id) : true;
          }
        },
        command: ({ tiptapEditor, attributes: { selectedNode } }) => {
          tiptapEditor.commands.addCellRight(selectedNode.lastChild.attrs.id);
        },
        renderer: (toolbarItem) => /* @__PURE__ */ React.createElement(AddCellButton, { toolbarItem })
      },
      createSeparator(),
      createDeleteButton({
        tooltip: "Layouts_LayoutDelete_Tooltip",
        attributes: {
          selectedNode: selectedNodeResolver
        },
        command: ({ tiptapEditor, attributes }) => {
          const layoutId = attributes.selectedNode.attrs.id;
          const layoutWithPos = findNodeById(tiptapEditor.state.tr, layoutId)[0];
          if (!layoutWithPos) {
            return;
          }
          const $layoutPos = tiptapEditor.state.doc.resolve(layoutWithPos.pos);
          const parentTypeName = $layoutPos.parent.type.name;
          const isInCardWrapper = parentTypeName === TIPTAP_CARD_HEADER_TYPE || parentTypeName === TIPTAP_CARD_FOOTER_TYPE;
          if (isInCardWrapper) {
            const wrapperFrom = $layoutPos.before($layoutPos.depth);
            const wrapperTo = $layoutPos.after($layoutPos.depth);
            tiptapEditor.chain().focus().command(({ tr }) => {
              tr.delete(wrapperFrom, wrapperTo);
              return true;
            }).run();
            return;
          }
          tiptapEditor.commands.deleteNode(layoutId);
        }
      })
    ]
  },
  getAddButtons: (_config, services) => config.showInToolbars ? [
    {
      id: `${TIPTAP_LAYOUT_TYPE}.insert`,
      label: INSERT_PLUGIN_BUTTONS.LAYOUT,
      dataHook: INSERT_LAYOUT_BUTTON,
      icon: LayoutThreeColumns,
      tooltip: "Layout_InsertButton_Tooltip",
      toolbars: toolbarsToAddIn,
      command: ({ referenceElement }) => {
        services.modals?.togglePluginPanel({
          id: LAYOUT_INSERT_MODAL_ID,
          Component: LayoutInsertModal,
          componentProps: {},
          isMobile: services.context.isMobile,
          positioning: {
            referenceElement,
            placement: "bottom"
          },
          mobileLayout: "drawer"
        });
        return true;
      },
      menuConfig: {
        tags: "Layout_InsertButton",
        group: "basic"
      }
    }
  ] : [],
  getQuickActions: ({ pluginServices }) => config.showInQuickActions ? [
    {
      id: "banner",
      title: "QuickActionsPlugin_ActionTitle_Banner",
      tags: ["header", "banner", "cover", "layout"],
      icon: BannerIcon,
      section: quickActionsModalSections.FormatLayout,
      command: ({ editor }) => {
        insertQuickActionBanner("TOP")(editor);
      }
    },
    {
      id: "footer",
      title: "QuickActionsPlugin_ActionTitle_Footer",
      tags: ["footer", "banner", "layout"],
      icon: FooterIcon,
      section: quickActionsModalSections.FormatLayout,
      isVisible: (editor) => !!editor.state.schema.nodes[TIPTAP_CARD_TYPE],
      command: ({ editor }) => {
        insertQuickActionBanner("BOTTOM")(editor);
      }
    },
    {
      id: "twoColumns",
      title: "QuickActionsPlugin_ActionTitle_TwoColumns",
      tags: ["layout", "grid", "cell"],
      icon: pluginServices?.context.isMobile ? LayoutTwoColumns : LayoutTwoColumnsSmall,
      section: quickActionsModalSections.FormatLayout,
      command: ({ publicCommands }) => {
        publicCommands.insertBlockWithBlankLines(
          RICOS_LAYOUT_TYPE,
          createBlankLayoutData(2),
          {
            updateSelection: "text",
            skipBlankLineBefore: false,
            skipBlankLineAfter: false
          }
        );
      }
    },
    {
      id: "threeColumns",
      title: "QuickActionsPlugin_ActionTitle_ThreeColumns",
      tags: ["layout", "grid", "cell"],
      icon: pluginServices?.context.isMobile ? LayoutThreeColumns : LayoutThreeColumnsSmall,
      section: quickActionsModalSections.FormatLayout,
      command: ({ publicCommands }) => {
        publicCommands.insertBlockWithBlankLines(
          RICOS_LAYOUT_TYPE,
          createBlankLayoutData(3),
          {
            updateSelection: "text",
            skipBlankLineBefore: false,
            skipBlankLineAfter: false
          }
        );
      }
    },
    {
      id: "layoutPresets",
      title: "QuickActionsPlugin_ActionTitle_Presets",
      tags: ["layout", "grid", "cell", "presets"],
      icon: pluginServices?.context.isMobile ? Catalog : CatalogSmall,
      section: quickActionsModalSections.FormatLayout,
      command: ({ editor, referenceElement }) => {
        const isMobile = pluginServices.context.isMobile;
        pluginServices.modals?.togglePluginPanel({
          id: LAYOUT_INSERT_MODAL_ID,
          Component: LayoutInsertModal,
          componentProps: {},
          isMobile,
          positioning: {
            referenceElement: referenceElement ?? {
              getBoundingClientRect: () => posToDOMRect(
                editor.view,
                editor.view.state.selection.from,
                editor.view.state.selection.to
              )
            },
            placement: isMobile ? "bottom" : "bottom-start"
          },
          mobileLayout: "drawer"
        });
      }
    }
  ] : []
});
const getVerticalAlignmentResolver = (content) => {
  if (Array.isArray(content) && content.length > 0) {
    const cellNode = content.find((node) => node.type.name === TIPTAP_LAYOUT_TYPE);
    return cellNode?.attrs?.cellVerticalAlignment;
  }
  return void 0;
};
const selectedNodeResolver = (_, __, editor) => {
  if (!editor) {
    return void 0;
  }
  const { selection } = editor.state;
  const node = selection instanceof NodeSelection ? selection.node : void 0;
  const closest = findParentNodeClosestToPos(
    selection.$from,
    (node2) => node2.type.name === TIPTAP_LAYOUT_TYPE
  );
  if (closest || node) {
    return closest?.node ?? node;
  }
  return void 0;
};
const isLayoutSetAsBannerActive = (content, services, editor) => {
  const node = selectedNodeResolver(content, services, editor);
  return node?.attrs?.banner?.position === "TOP";
};
const isLayoutSetAsFooterActive = (content, services, editor) => {
  const node = selectedNodeResolver(content, services, editor);
  return node?.attrs?.banner?.position === "BOTTOM";
};
const AddCellButton = ({ toolbarItem }) => {
  const { t } = useContext(RicosContext) || {};
  return /* @__PURE__ */ React.createElement(
    ToolbarButton,
    {
      disabled: toolbarItem.attributes.disabled,
      prefix: AddSmall,
      onClick: () => {
        toolbarItem.tiptapEditor.commands.addCellRight(
          toolbarItem.attributes.selectedNode.lastChild.attrs.id
        );
      },
      dataHook: LAYOUT_PLUGIN_TOOLBAR_ADD_CELL_BUTTON,
      tooltip: t("Layouts_LayoutAddCell_Tooltip"),
      tabIndex: toolbarItem.presentation.tabIndex
    }
  );
};
const LayoutSetAsHeaderButton = ({ toolbarItem }) => {
  const { t } = useContext(RicosContext) || {};
  const onClick = toolbarItem.commands.click;
  const isActive = !!toolbarItem.attributes.active;
  return /* @__PURE__ */ React.createElement(
    ToolbarButton,
    {
      prefix: BannerIcon,
      onClick: () => onClick?.(),
      dataHook: PLUGIN_TOOLBAR_SET_AS_HEADER_BUTTON,
      label: t(toolbarItem.presentation.label),
      tabIndex: toolbarItem.presentation.tabIndex,
      active: isActive
    }
  );
};
const LayoutSetAsFooterButton = ({ toolbarItem }) => {
  const { t } = useContext(RicosContext) || {};
  const onClick = toolbarItem.commands.click;
  const isActive = !!toolbarItem.attributes.active;
  return /* @__PURE__ */ React.createElement(
    ToolbarButton,
    {
      prefix: FooterIcon,
      onClick: () => onClick?.(),
      dataHook: PLUGIN_TOOLBAR_SET_AS_FOOTER_BUTTON,
      label: t(toolbarItem.presentation.label),
      tabIndex: toolbarItem.presentation.tabIndex,
      active: isActive
    }
  );
};
const isToolbarVisible = (selection) => {
  const isVisibleInSelection = "node" in selection && selection.node?.type.name === TIPTAP_LAYOUT_TYPE;
  if (isVisibleInSelection) {
    return true;
  }
  if ("node" in selection) {
    return false;
  }
  const closestContainer = findParentNodeClosestToPos(
    selection.$from,
    (node) => node.type.name === TIPTAP_LAYOUT_TYPE || node.type.name === TIPTAP_COLLAPSIBLE_LIST_TYPE
  );
  return closestContainer?.node.type.name === TIPTAP_LAYOUT_TYPE;
};
export {
  pluginLayout
};
//# sourceMappingURL=plugin-layout.js.map
