import * as A from "fp-ts-esm/Array";
import * as E from "fp-ts-esm/Either";
import { flow, pipe } from "fp-ts-esm/function";
import * as M from "fp-ts-esm/Monoid";
import * as O from "fp-ts-esm/Option";
import * as S from "fp-ts-esm/string";
import { encode } from "html-entities";
import lodash from "lodash";
import { Decoration_Type, Link_Target, Node_Type, TextStyle_TextAlignment } from "./../../../../ricos-schema/legacy/wix/rich_content/v1/index.js";
import { CHECKBOX_LIST_STYLE_ATTRIBUTE_VALUE } from "./../../../../_shared/list-checkbox/checkbox-list-style.js";
import { resolveDocumentColorToCss, resolveDocumentColorToHex } from "./../../../../_shared/theme-color-token.js";
import { unreachable } from "./../../../../_shared/uncreachable.js";
import { firstRight } from "../../../fp-utils.js";
const toHtml = (content, interceptorFn = ({ result }) => result, separator = "\n", palette) => {
  const nodes = Array.isArray(content) ? content : content.nodes ?? [];
  return `${nodeArrayToHtml(nodes, interceptorFn, separator, palette)}`;
};
const ensureNodeType = (nodes) => nodes.map((node) => {
  node.type = node.type || Node_Type.PARAGRAPH;
  ensureNodeType(node.nodes || []);
  return node;
});
const nodeArrayToHtml = (nodes, interceptorFn, separator = "", palette) => {
  const nodesWithTypes = ensureNodeType(nodes);
  return nodesWithTypes.flatMap((node) => {
    const result = nodeToHtml(node, interceptorFn, palette);
    return interceptorFn({ node, result });
  }).join(separator);
};
const nodeToHtml = (node, interceptorFn, palette) => {
  if (node.type === Node_Type.TEXT && node.textData) {
    return decorateTextElement({ ...node.textData, text: encode(node.textData.text) }, palette);
  }
  if (node.type === Node_Type.PARAGRAPH && node.nodes?.length === 0) {
    return EMPTY_PARAGRAPH;
  }
  let tag = NODE_TO_HTML_TAG[node.type];
  if (node.type === Node_Type.HEADING && node.headingData) {
    const { level } = node.headingData;
    tag = `h${level}`;
  }
  if (node.type === Node_Type.PARAGRAPH && node.paragraphData) {
    const children = nodeArrayToHtml(node.nodes ?? [], interceptorFn, void 0, palette);
    const attrs = createTextStyleAttrs(node.paragraphData.textStyle);
    return createHtmlTag(tag, children, attrs);
  }
  if (node.type === Node_Type.LAYOUT) {
    return nodeArrayToHtml(
      node.nodes?.map((cell) => cell.nodes)?.flat() ?? [],
      interceptorFn,
      void 0,
      palette
    );
  }
  if (tag) {
    const children = nodeArrayToHtml(node.nodes ?? [], interceptorFn, void 0, palette);
    return createHtmlTag(tag, children, createNodeAttrs(node));
  }
  return [];
};
const createLinkAttrs = (decoration) => {
  const rel = Object.entries(decoration.linkData?.link?.rel || {}).filter(([_, value]) => !!value).map(([key]) => key).join(" ");
  const targetRaw = decoration.linkData?.link?.target;
  const ignoreTarget = [void 0, Link_Target.UNRECOGNIZED, Link_Target.SELF].includes(targetRaw);
  const target = ignoreTarget ? "" : `_${targetRaw?.toLowerCase()}`;
  const anchor = decoration.linkData?.link?.anchor || "";
  const href = decoration.linkData?.link?.url || "";
  return lodash.pickBy({ href, rel, anchor, target }, lodash.identity);
};
const createAnchorAttrs = (decoration) => {
  const anchor = decoration.anchorData?.anchor || "";
  return { href: `#${anchor}`, rel: "noopener noreferrer" };
};
const createMentionAttrs = (decoration) => {
  const { name = "", slug = "", id = "" } = decoration.mentionData || {};
  if (!name && !slug && !id) {
    return {};
  }
  return lodash.pickBy(
    { role: "link", "data-mention-name": name, "data-mention-slug": slug, "data-mention-id": id },
    lodash.identity
  );
};
const createSpoilerAttrs = () => ({ "data-spoiler": "true" });
const createColorAttrs = (decoration, palette) => {
  const { foreground, background } = decoration.colorData || {};
  const resolveColor = (color) => palette ? resolveDocumentColorToHex(color, palette) : resolveDocumentColorToCss(color);
  const fg = resolveColor(foreground);
  const bg = resolveColor(background);
  const style = pipe(
    [fg && `color: ${fg};`, bg && `background-color: ${bg};`],
    lodash.compact,
    M.concatAll(S.Monoid)
  );
  return lodash.pickBy({ style }, lodash.identity);
};
const createTextStyleAttrs = (textStyle) => {
  const { textAlignment } = textStyle || {};
  const textAlign = normalizeTextAlignment(textAlignment);
  const style = pipe(
    [textAlign && `text-align: ${textAlign};`],
    lodash.compact,
    M.concatAll(S.Monoid)
  );
  return lodash.pickBy({ style }, lodash.identity);
};
const createNodeAttrs = (node) => {
  if (node.type === Node_Type.CHECKBOX_LIST) {
    return { "data-list-style": CHECKBOX_LIST_STYLE_ATTRIBUTE_VALUE };
  }
  if (node.type === Node_Type.LIST_ITEM && node.listItemData?.checked !== void 0) {
    return { role: "checkbox", "aria-checked": node.listItemData.checked ? "true" : "false" };
  }
  return {};
};
const isType = (type) => (decoration) => decoration.type === type;
const createHtmlAttrs = (decoration, palette) => firstRight(decoration, {}, [
  [isType(Decoration_Type.LINK), createLinkAttrs],
  [isType(Decoration_Type.ANCHOR), createAnchorAttrs],
  [isType(Decoration_Type.MENTION), createMentionAttrs],
  [isType(Decoration_Type.SPOILER), createSpoilerAttrs],
  [isType(Decoration_Type.COLOR), (decoration2) => createColorAttrs(decoration2, palette)]
]);
const createHtmlTag = (tag, child, attrs = {}) => {
  const isFragment = tag === "fragment";
  const prefix = tag === "li" ? "\n  " : "";
  const suffix = ["ul", "ol"].includes(tag) ? "\n" : "";
  return isFragment ? `${child}${suffix}` : `${prefix}<${tag}${attrsToString(attrs)}>${child}${suffix}</${tag}>`;
};
const attrsToString = (attrs) => Object.entries(attrs).map(([key, value]) => ` ${key}="${value}"`).join("");
const toForegroundDecoration = (d) => d.colorData?.foreground ? O.some({ type: Decoration_Type.COLOR, colorData: { foreground: d.colorData.foreground } }) : O.none;
const toBackgroundDecoration = (d) => d.colorData?.background ? O.some({ type: Decoration_Type.COLOR, colorData: { background: d.colorData.background } }) : O.none;
const expandColorDecoration = (decoration) => pipe([toBackgroundDecoration, toForegroundDecoration], A.ap(A.of(decoration)), A.compact);
const eitherColorDecoration = (d) => d.type === Decoration_Type.COLOR ? E.right(d) : E.left(d);
const ensureDecorations = (decorations) => decorations || [];
const normalizeDecorations = flow(
  ensureDecorations,
  A.map(flow(eitherColorDecoration, E.fold(A.of, expandColorDecoration))),
  A.flatten
);
const normalizeTextAlignment = (textAlignment) => {
  switch (textAlignment) {
    case TextStyle_TextAlignment.CENTER:
    case TextStyle_TextAlignment.JUSTIFY:
    case TextStyle_TextAlignment.LEFT:
    case TextStyle_TextAlignment.RIGHT:
      return textAlignment.toLowerCase();
    case TextStyle_TextAlignment.AUTO:
    case TextStyle_TextAlignment.UNRECOGNIZED:
    case void 0:
      return void 0;
    default:
      throw unreachable(textAlignment);
  }
};
const decorateTextElement = ({ text, decorations }, palette) => {
  const normalizedDecorations = normalizeDecorations(decorations);
  return normalizedDecorations.reduce((child, decoration) => {
    const tag = DECORATION_TO_HTML_TAG[decoration.type];
    return tag ? createHtmlTag(tag, child, createHtmlAttrs(decoration, palette)) : child;
  }, text);
};
const DECORATION_TO_HTML_TAG = {
  [Decoration_Type.COLOR]: "span",
  [Decoration_Type.MENTION]: "span",
  [Decoration_Type.SPOILER]: "span",
  [Decoration_Type.BOLD]: "strong",
  [Decoration_Type.ITALIC]: "em",
  [Decoration_Type.UNDERLINE]: "u",
  [Decoration_Type.LINK]: "a",
  [Decoration_Type.ANCHOR]: "a",
  [Decoration_Type.STRIKETHROUGH]: "s"
};
const NODE_TO_HTML_TAG = {
  [Node_Type.BULLETED_LIST]: "ul",
  [Node_Type.CHECKBOX_LIST]: "ul",
  [Node_Type.COLLAPSIBLE_LIST]: "ul",
  [Node_Type.ORDERED_LIST]: "ol",
  [Node_Type.LIST_ITEM]: "li",
  [Node_Type.COLLAPSIBLE_ITEM]: "li",
  [Node_Type.COLLAPSIBLE_ITEM_TITLE]: "fragment",
  [Node_Type.COLLAPSIBLE_ITEM_BODY]: "fragment",
  [Node_Type.PARAGRAPH]: "p"
};
const EMPTY_PARAGRAPH = "<p><br /></p>";
export {
  ensureNodeType,
  toHtml
};
//# sourceMappingURL=to-html.js.map
