import { TIPTAP_CARD_CONTENT_TYPE, TIPTAP_CARD_TYPE } from "./../ricos-content/index.js";
import { resolveBackwardCompatOverlay } from "./../_shared/resolve-backward-compat-overlay.js";
import { ReactRenderer } from "./../tiptap/react/index.js";
import { getImageSrc } from "./../wix-rich-content-common/lib/image-utils.js";
import { gradientToCss } from "../_shared/gradient-to-css.js";
import { hexToRgba } from "../theme-utils/color-utils.js";
import { BoundaryLine } from "./boundary-warning.js";
import styles from "./card-scss.js";
import { PageGap } from "./page-gap.js";
import {
  CARD_DEFAULTS,
  getCardBackgroundColorCssVar,
  isTransparentCardBackgroundColor
} from "./shared-with-viewer.js";
const isSelectionInCard = (editor, getPos, nodeSize) => {
  const pos = getPos();
  if (typeof pos !== "number") {
    return false;
  }
  const { from, to } = editor.state.selection;
  const cardStart = pos;
  const cardEnd = pos + nodeSize;
  return from < cardEnd && to > cardStart;
};
const isFluidPageFormat = (pageFormat) => pageFormat !== void 0 && pageFormat.height === void 0;
const getCardStorage = (editor) => editor.storage[TIPTAP_CARD_TYPE];
const getActivePageFormat = (editor) => getCardStorage(editor)?.activePageFormat;
const setOrRemove = (el, prop, value) => {
  if (value !== void 0) {
    el.style.setProperty(prop, value);
  } else {
    el.style.removeProperty(prop);
  }
};
const updateCardBackgroundStyles = (cardElement, node) => {
  const background = node.attrs.background;
  const backgroundImage = node.attrs.backgroundImage;
  const isTransparentColor = background?.type === "COLOR" && isTransparentCardBackgroundColor(background.color);
  const hasExplicitBackground = !!background && !isTransparentColor || !!backgroundImage;
  if (backgroundImage) {
    const imageUrl = backgroundImage.media?.src.url ?? (backgroundImage.media?.src.id && getImageSrc({ file_name: backgroundImage.media.src.id }, void 0, {
      requiredQuality: 100,
      requiredWidth: Math.min(backgroundImage.media?.width ?? 4e3, 4e3),
      requiredHeight: Math.min(backgroundImage.media?.height ?? 4e3, 4e3)
    }));
    setOrRemove(
      cardElement,
      "--ricos-internal-card-background-image",
      imageUrl ? `url(${imageUrl})` : void 0
    );
    setOrRemove(
      cardElement,
      "--ricos-internal-card-background-size",
      backgroundImage.scaling?.toLowerCase()
    );
    setOrRemove(
      cardElement,
      "--ricos-internal-card-background-position",
      backgroundImage.position?.toLowerCase().split("_").join(" ")
    );
    let overlay;
    if (background?.type === "GRADIENT") {
      overlay = gradientToCss(background.gradient) || void 0;
    } else if (background?.type === "COLOR" && !isTransparentColor) {
      const resolved = resolveBackwardCompatOverlay(
        background.color,
        backgroundImage.opacity ?? 100,
        100
      );
      overlay = hexToRgba(resolved);
    }
    setOrRemove(cardElement, "--ricos-internal-card-background-image-overlay", overlay);
    cardElement.style.removeProperty("--ricos-internal-card-background-color");
    cardElement.style.removeProperty("--ricos-internal-card-background-gradient");
    cardElement.style.removeProperty("--ricos-internal-card-background-image-opacity");
  } else {
    const gradientCss = background?.type === "GRADIENT" ? gradientToCss(background.gradient) : void 0;
    setOrRemove(
      cardElement,
      "--ricos-internal-card-background-color",
      getCardBackgroundColorCssVar(background, hasExplicitBackground)
    );
    setOrRemove(cardElement, "--ricos-internal-card-background-gradient", gradientCss || void 0);
    cardElement.style.removeProperty("--ricos-internal-card-background-image-overlay");
    if (hasExplicitBackground) {
      cardElement.style.setProperty("--ricos-internal-card-background-image", "none");
    } else {
      cardElement.style.removeProperty("--ricos-internal-card-background-image");
    }
    cardElement.style.removeProperty("--ricos-internal-card-background-size");
    cardElement.style.removeProperty("--ricos-internal-card-background-position");
    cardElement.style.removeProperty("--ricos-internal-card-background-image-opacity");
  }
};
const updateCardView = (cardElement, contentElement, boundaryLineWrapper, boundaryLineRenderer, pageFormat, hideBoundaryLine, onSplit) => {
  const width = pageFormat?.width ?? CARD_DEFAULTS.width;
  const isFluid = isFluidPageFormat(pageFormat);
  cardElement.style.setProperty("--ricos-internal-card-width", `${width}px`);
  if (isFluid) {
    cardElement.style.removeProperty("--ricos-internal-card-height");
    cardElement.classList.add(styles.fluid);
    contentElement.classList.add(styles.fluidContent);
    boundaryLineWrapper.classList.remove(styles.visible);
    boundaryLineRenderer.updateProps({ visible: false, onSplit });
  } else {
    const height = pageFormat?.height ?? CARD_DEFAULTS.height;
    cardElement.style.setProperty("--ricos-internal-card-height", `${height}px`);
    cardElement.classList.remove(styles.fluid);
    contentElement.classList.remove(styles.fluidContent);
    const isOverflowing = !hideBoundaryLine && contentElement.scrollHeight > height;
    boundaryLineWrapper.classList.toggle(styles.visible, isOverflowing);
    boundaryLineRenderer.updateProps({ visible: isOverflowing, onSplit });
  }
};
const createCardNodeView = (options) => {
  const { renderCardHeader, isMobile, getBoundaryWarningPortal } = options;
  return ({ node, editor, getPos }) => {
    let currentNode = node;
    const cardWrapper = document.createElement("div");
    cardWrapper.className = styles.cardWrapper;
    let headerContainer = null;
    let headerRenderer = null;
    const getCardIndex = () => {
      const doc = editor.state.doc;
      const cardPos = getPos();
      if (typeof cardPos !== "number") {
        return 0;
      }
      let currentIndex = 0;
      let found = false;
      doc.forEach((docNode, pos) => {
        if (found) {
          return;
        }
        if (docNode.type.name === "CARD") {
          currentIndex++;
          if (pos === cardPos) {
            found = true;
          }
        }
      });
      const pendingInsertions = getCardStorage(editor).pendingCardInsertions;
      for (const insertion of pendingInsertions) {
        if (insertion.afterCardIndex < currentIndex) {
          currentIndex += insertion.count;
        }
      }
      return currentIndex;
    };
    const getIsLastCard = () => {
      const doc = editor.state.doc;
      const cardPos = getPos();
      if (typeof cardPos !== "number") {
        return true;
      }
      let isLast = true;
      let foundCurrent = false;
      doc.forEach((docNode, pos) => {
        if (docNode.type.name === "CARD") {
          if (foundCurrent) {
            isLast = false;
            return;
          }
          if (pos === cardPos) {
            foundCurrent = true;
          }
        }
      });
      return isLast;
    };
    if (renderCardHeader) {
      headerContainer = document.createElement("div");
      headerContainer.setAttribute("contenteditable", "false");
      headerContainer.className = styles.cardHeaderContainer;
      headerRenderer = new ReactRenderer(renderCardHeader, {
        editor,
        props: {
          cardNode: currentNode,
          index: getCardIndex()
        }
      });
      headerContainer.appendChild(headerRenderer.element);
      cardWrapper.appendChild(headerContainer);
    }
    const cardElement = document.createElement("div");
    cardElement.setAttribute("data-card-container", "true");
    cardElement.setAttribute("data-card-id", currentNode.attrs.id);
    cardElement.className = styles.cardContainer;
    const contentElement = document.createElement("div");
    contentElement.className = styles.cardContent;
    const boundaryLineWrapper = document.createElement("div");
    boundaryLineWrapper.setAttribute("contenteditable", "false");
    boundaryLineWrapper.className = styles.cardBoundaryLineWrapper;
    const handleSplitAtBoundary = () => {
      const lineRect = boundaryLineWrapper.getBoundingClientRect();
      const posResult = editor.view.posAtCoords({
        left: lineRect.left + lineRect.width,
        top: lineRect.top - 30
      });
      if (posResult) {
        editor.commands.splitCardAtPos(posResult.pos);
      }
    };
    const boundaryLineRenderer = new ReactRenderer(BoundaryLine, {
      editor,
      props: { visible: false, onSplit: handleSplitAtBoundary, getBoundaryWarningPortal }
    });
    boundaryLineWrapper.appendChild(boundaryLineRenderer.element);
    const selectionSvg = document.createElementNS("http://www.w3.org/2000/svg", "svg");
    selectionSvg.setAttribute("width", "100%");
    selectionSvg.setAttribute("height", "100%");
    selectionSvg.setAttribute("class", styles.selectionSvg);
    const selectionRect = document.createElementNS("http://www.w3.org/2000/svg", "rect");
    selectionRect.setAttribute("width", "100%");
    selectionRect.setAttribute("height", "100%");
    selectionRect.setAttribute("class", styles.selectionRect);
    selectionSvg.appendChild(selectionRect);
    cardElement.append(contentElement, boundaryLineWrapper, selectionSvg);
    const cardGap = document.createElement("div");
    cardGap.className = styles.cardGap;
    cardGap.setAttribute("contenteditable", "false");
    const updateLastCardClass = () => {
      const isLast = getIsLastCard();
      cardElement.classList.toggle(styles.last, isLast);
      cardGap.classList.toggle(styles.last, isLast);
    };
    updateLastCardClass();
    const handleAddPage = () => {
      const pos = getPos();
      if (typeof pos === "number") {
        const insertPos = pos + currentNode.nodeSize;
        editor.chain().focus().insertContentAt(insertPos, {
          type: "CARD",
          content: [
            {
              type: TIPTAP_CARD_CONTENT_TYPE,
              content: [{ type: "PARAGRAPH" }]
            }
          ]
        }).run();
      }
    };
    const handleMergePages = () => {
      cardGap.classList.remove(styles.mergeHover);
      const cardPos = getPos();
      if (typeof cardPos === "number") {
        let cardIdx = -1;
        let current = 0;
        editor.state.doc.forEach((docNode, offset) => {
          if (docNode.type.name === "CARD") {
            if (offset === cardPos) {
              cardIdx = current;
            }
            current++;
          }
        });
        if (cardIdx >= 0) {
          editor.chain().focus().mergeCardWithNext(cardIdx).run();
        }
      }
    };
    const handleMergeHoverChange = (isHovered) => {
      cardGap.classList.toggle(styles.mergeHover, isHovered);
    };
    const pageGapRenderer = new ReactRenderer(PageGap, {
      editor,
      props: {
        onAddPage: handleAddPage,
        onMergePages: handleMergePages,
        onMergeHoverChange: handleMergeHoverChange,
        isLastCard: getIsLastCard()
      }
    });
    cardGap.appendChild(pageGapRenderer.element);
    cardWrapper.append(cardElement, cardGap);
    const resizeObserver = new ResizeObserver(() => {
      updateCardView(
        cardElement,
        contentElement,
        boundaryLineWrapper,
        boundaryLineRenderer,
        getActivePageFormat(editor),
        isMobile,
        handleSplitAtBoundary
      );
    });
    const updateSelectionState = () => {
      const isSelected = editor.isFocused && isSelectionInCard(editor, getPos, currentNode.nodeSize);
      const className = isSelected ? `${styles.selectionRect} ${styles.selectionRectActive}` : styles.selectionRect;
      selectionRect.setAttribute("class", className);
    };
    editor.on("selectionUpdate", updateSelectionState);
    editor.on("focus", updateSelectionState);
    editor.on("blur", updateSelectionState);
    const updateHeaderIndex = () => {
      if (headerRenderer) {
        headerRenderer.updateProps({
          cardNode: currentNode,
          index: getCardIndex()
        });
      }
      pageGapRenderer.updateProps({
        isLastCard: getIsLastCard()
      });
      updateLastCardClass();
    };
    editor.on("update", updateHeaderIndex);
    const handlePageFormatChange = () => {
      updateCardView(
        cardElement,
        contentElement,
        boundaryLineWrapper,
        boundaryLineRenderer,
        getActivePageFormat(editor),
        isMobile,
        handleSplitAtBoundary
      );
    };
    getCardStorage(editor).onPageFormatChange.add(handlePageFormatChange);
    getCardStorage(editor).onPendingCardInsertionsChange.add(updateHeaderIndex);
    updateCardView(
      cardElement,
      contentElement,
      boundaryLineWrapper,
      boundaryLineRenderer,
      getActivePageFormat(editor),
      void 0,
      handleSplitAtBoundary
    );
    updateCardBackgroundStyles(cardElement, currentNode);
    updateSelectionState();
    let destroyed = false;
    requestAnimationFrame(() => {
      if (!destroyed) {
        resizeObserver.observe(contentElement);
      }
    });
    return {
      dom: cardWrapper,
      contentDOM: contentElement,
      update: (newNode) => {
        if (newNode.type !== currentNode.type) {
          return false;
        }
        currentNode = newNode;
        cardElement.setAttribute("data-card-id", newNode.attrs.id);
        updateCardView(
          cardElement,
          contentElement,
          boundaryLineWrapper,
          boundaryLineRenderer,
          getActivePageFormat(editor),
          void 0,
          handleSplitAtBoundary
        );
        updateCardBackgroundStyles(cardElement, currentNode);
        if (headerRenderer) {
          headerRenderer.updateProps({
            cardNode: currentNode,
            index: getCardIndex()
          });
        }
        pageGapRenderer.updateProps({
          isLastCard: getIsLastCard()
        });
        updateLastCardClass();
        return true;
      },
      ignoreMutation: (mutation) => {
        const isMutatingWrapper = mutation.target === cardWrapper;
        const isMutatingHeader = headerContainer && (mutation.target === headerContainer || headerContainer.contains(mutation.target));
        const isMutatingCardAttributes = mutation.target === cardElement && mutation.type === "attributes";
        const isMutatingBoundaryLine = mutation.target === boundaryLineWrapper || boundaryLineWrapper.contains(mutation.target);
        const isMutatingGap = mutation.target === cardGap || cardGap.contains(mutation.target);
        const isMutatingSelectionSvg = mutation.target === selectionSvg || mutation.target === selectionRect;
        const isMutatingDataAttribute = mutation.type === "attributes" && mutation.attributeName?.startsWith("data-");
        const isMutatingStyle = mutation.type === "attributes" && mutation.attributeName === "style";
        const isMutatingClass = mutation.type === "attributes" && mutation.attributeName === "class";
        return isMutatingWrapper || isMutatingHeader || isMutatingCardAttributes || isMutatingBoundaryLine || isMutatingGap || isMutatingSelectionSvg || isMutatingDataAttribute || isMutatingStyle || isMutatingClass;
      },
      destroy: () => {
        destroyed = true;
        resizeObserver.disconnect();
        editor.off("selectionUpdate", updateSelectionState);
        editor.off("focus", updateSelectionState);
        editor.off("blur", updateSelectionState);
        editor.off("update", updateHeaderIndex);
        getCardStorage(editor).onPageFormatChange.delete(handlePageFormatChange);
        getCardStorage(editor).onPendingCardInsertionsChange.delete(updateHeaderIndex);
        boundaryLineRenderer.destroy();
        pageGapRenderer.destroy();
        if (headerRenderer) {
          headerRenderer.destroy();
        }
      }
    };
  };
};
export {
  createCardNodeView
};
//# sourceMappingURL=card-node-view.js.map
