import { json } from "@codemirror/lang-json";
import { closeLintPanel, diagnosticCount, linter, openLintPanel } from "@codemirror/lint";
import { EditorView } from "@codemirror/view";
import CodeMirror from "@uiw/react-codemirror";
import { Box, Button, Loader } from "@wix/design-system";
import { StatusAlertSmall } from "@wix/wix-ui-icons-common";
import lodash from "lodash";
import React from "react";
import { parseFromString } from "./../../../../ricos-schema/next-schema/index.js";
import { fixDocument } from "./autofix-api.js";
import { wixDocsCodeTheme } from "./code-mirror-theme.js";
const RicosContentEditorTab = ({
  editorPlugins,
  content,
  onChange,
  mode,
  selectedNodeId
}) => {
  const [hasErrors, setHasErrors] = React.useState(false);
  const [fixPending, setFixPending] = React.useState(false);
  const codemirrorRef = React.useRef(null);
  const stringContent = JSON.stringify(content, null, 2);
  const isValidJson = getIsValidJson(stringContent);
  React.useEffect(() => {
    if (!hasErrors && codemirrorRef.current?.view) {
      closeLintPanel(codemirrorRef.current?.view);
    }
  }, [hasErrors]);
  React.useEffect(() => {
    if (!selectedNodeId || !codemirrorRef.current?.view) {
      return;
    }
    const view = codemirrorRef.current.view;
    const contentAsString = view.state.doc.toString();
    const position = findNodeIdPosition(contentAsString, selectedNodeId);
    if (position === -1) {
      return;
    }
    const line = view.state.doc.lineAt(position);
    view.dispatch({
      selection: { anchor: line.from, head: line.to },
      effects: EditorView.scrollIntoView(line.from, { y: "start" })
    });
    view.focus();
  }, [selectedNodeId]);
  const handleOnChange = React.useCallback(
    (value) => {
      const parsedContent = typeof value === "string" ? parseWithFallback(value, content) : value;
      onChange(parsedContent);
    },
    [content]
  );
  const onChangeDebounced = React.useCallback(lodash.debounce(handleOnChange, 1e3), [
    handleOnChange
  ]);
  return /* @__PURE__ */ React.createElement(Box, { direction: "vertical", paddingInline: "8px", gap: "5px" }, codemirrorRef.current && hasErrors && /* @__PURE__ */ React.createElement(Box, { align: "right", gap: "8px" }, isValidJson && mode === "editor" && /* @__PURE__ */ React.createElement(
    Button,
    {
      size: "small",
      skin: "standard",
      priority: "secondary",
      onClick: () => {
        if (fixPending) {
          return;
        }
        const result = safeParse(stringContent);
        if (result.type === "ok") {
          setFixPending(true);
          fixDocument(result.value, editorPlugins).then((content2) => {
            handleOnChange(content2);
          }).catch((e) => {
            console.error(e);
          }).finally(() => {
            setFixPending(false);
          });
        }
      }
    },
    fixPending && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(Loader, { size: "tiny" }), /* @__PURE__ */ React.createElement("span", { className: "mr-2" })),
    " ",
    "Auto-Fix"
  ), /* @__PURE__ */ React.createElement(
    Button,
    {
      size: "small",
      prefixIcon: /* @__PURE__ */ React.createElement(StatusAlertSmall, null),
      skin: "destructive",
      priority: "primary",
      onClick: () => {
        codemirrorRef.current?.view && openLintPanel(codemirrorRef.current?.view);
      }
    },
    "Errors"
  )), /* @__PURE__ */ React.createElement(
    CodeMirror,
    {
      ref: codemirrorRef,
      theme: wixDocsCodeTheme,
      value: stringContent,
      minHeight: "200px",
      extensions: [json(), codemirrorValidationPlugin(editorPlugins)],
      onChange: onChangeDebounced,
      onUpdate: (updates) => {
        const hasErrorsLatest = diagnosticCount(updates.state) > 0;
        if (hasErrorsLatest !== hasErrors) {
          setHasErrors(hasErrorsLatest);
        }
      }
    }
  ));
};
const parseWithFallback = (json2, fallback) => {
  try {
    return JSON.parse(json2);
  } catch {
    return fallback;
  }
};
const getIsValidJson = (json2) => {
  try {
    JSON.parse(json2);
    return true;
  } catch {
    return false;
  }
};
const safeParse = (json2) => {
  try {
    return { type: "ok", value: JSON.parse(json2) };
  } catch (e) {
    return { type: "error", error: e };
  }
};
const findNodeIdPosition = (jsonString, nodeId) => {
  const escapedNodeId = nodeId.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
  const pattern = new RegExp(`"id"\\s*:\\s*"${escapedNodeId}"`);
  const match = pattern.exec(jsonString);
  return match ? match.index : -1;
};
const codemirrorValidationPlugin = (editorPlugins) => {
  return linter((view) => {
    const result = parseFromString(view.state.doc.toString(), { plugins: editorPlugins });
    if (result.type === "ok") {
      return [];
    }
    return result.messages.map((message) => ({
      ...message,
      severity: "error"
    }));
  });
};
export {
  RicosContentEditorTab
};
//# sourceMappingURL=ricos-content-editor.js.map
