import { EditorState } from "../_vendor/@codemirror/state/dist-index.js";
import { EditorView } from "../_vendor/@codemirror/view/dist-index.js";
import { useId, useRef, useCallback, useLayoutEffect, useEffect } from "react";
import { useExtensions } from "./use-extensions.js";
import { useEvent } from "./use-event.js";
import { useLanguageExtensions } from "./use-language-extensions.js";
function useCodeEditor(props) {
  const {
    value,
    customExtensions,
    autoFocus,
    onChange,
    readonly,
    lineWrapping,
    onEditorUpdate,
    onFormat,
    onCursorChange,
    onSelectionChange
  } = props;
  const id = useId();
  const containerRef = useRef(null);
  const editorViewRef = useRef(null);
  const isInternalChangeRef = useRef(false);
  const getCursorPosition = useCallback(() => {
    const editor = editorViewRef.current;
    if (!editor) return null;
    const { state } = editor;
    const pos = state.selection.main.head;
    const lineInfo = state.doc.lineAt(pos);
    return {
      column: pos - lineInfo.from + 1,
      line: lineInfo.number
    };
  }, []);
  const getSelectedCharacterCount = useCallback(() => {
    const editor = editorViewRef.current;
    if (!editor) return 0;
    const { state } = editor;
    const { from, to } = state.selection.main;
    return to - from;
  }, []);
  const extensions = useExtensions({
    readonly,
    lineWrapping,
    customExtensions,
    onChange: (newValue, update) => {
      isInternalChangeRef.current = true;
      onChange == null ? void 0 : onChange(newValue, update);
    },
    onCursorChange,
    onEditorUpdate: onEditorUpdate ?? (() => {
    }),
    onFormat,
    onSelectionChange
  });
  const { getLanguageExtensions } = useLanguageExtensions({
    id
  });
  const { blurOnClickOutside } = useEvent(editorViewRef);
  const createEditor = useCallback(async () => {
    if (!containerRef.current) return;
    const languageExtensions = await getLanguageExtensions(value ?? "");
    const config = {
      doc: value ?? "",
      extensions: [...extensions, ...languageExtensions]
    };
    const parent = containerRef.current;
    const state = EditorState.create(config);
    const editorView = new EditorView({
      parent,
      state
    });
    editorViewRef.current = editorView;
  }, [extensions, getLanguageExtensions, value]);
  useLayoutEffect(() => {
    createEditor();
    return () => {
      if (editorViewRef.current) {
        editorViewRef.current.destroy();
        editorViewRef.current = null;
      }
    };
  }, []);
  useEffect(() => {
    const editor = editorViewRef.current;
    if (!editor) return;
    if (isInternalChangeRef.current) {
      isInternalChangeRef.current = false;
      return;
    }
    const currentValue = editor.state.doc.toString();
    const newValue = value ?? "";
    if (currentValue !== newValue) {
      editor.dispatch({
        changes: {
          from: 0,
          to: currentValue.length,
          insert: newValue
        }
      });
    }
  }, [value]);
  useEffect(() => {
    if (autoFocus && editorViewRef.current) {
      editorViewRef.current.focus();
    }
  }, [autoFocus]);
  useEffect(() => {
    document.addEventListener("click", blurOnClickOutside);
    return () => {
      document.removeEventListener("click", blurOnClickOutside);
    };
  }, [blurOnClickOutside]);
  return {
    containerRef,
    editorViewRef,
    getCursorPosition,
    getSelectedCharacterCount
  };
}
export {
  useCodeEditor
};
//# sourceMappingURL=use-code-editor.js.map
