import { editor, languages } from 'monaco-editor/esm/vs/editor/editor.api';
import  { CSSProperties, MutableRefObject, RefObject, useEffect, useRef, useState } from 'react';
import './index.css'
import React from 'react';
export type EditorLanguages =
  | 'javascript'
  | 'typescript'
  | 'css'
  | 'json'
  | 'html'
  | 'markdown'
  | 'vue'
  | 'java'
  | 'tsx'
  | 'jsx';

export interface MonacoEditorProps {
  value?: string;
  onChange?: (v: string) => void;
  language: EditorLanguages;
  readonly?: boolean;
  editor?: RefObject<editor.IStandaloneCodeEditor>;
  /**
   * TypeScript类型定义文件，针对language='javascript' | 'typescript' 生效
   */
  definitions?: {
    [filePath: string]: string;
  };
  style?: CSSProperties;
}

export const MonacoEditor = (props: MonacoEditorProps) => {
  const instance = useRef<editor.IStandaloneCodeEditor>(null!);
  const root = useRef<HTMLDivElement>(null!);

  const [ready, setReady] = useState(false);

  function updateDefinition() {
    if (props.language === 'javascript' || props.language === 'typescript') {
      if (props.definitions) {
        languages.typescript[`${props.language}Defaults`].setExtraLibs(
          Object.entries(props.definitions).map(([filePath, content]) => ({
            filePath,
            content,
          })),
        );
      }
    }
  }
  useEffect(() => {
    updateDefinition();

    instance.current = editor.create(root.current, {
      value: props.value || '',
      language: props.language,
      automaticLayout: true,
      readOnly: props.readonly,
    });
    
    instance.current.onDidChangeModelContent(onCodeChange);
    if (props.editor) {
      (props.editor as MutableRefObject<editor.IStandaloneCodeEditor>).current =
        instance.current;
    }
    setReady(true);
    return () => {
      if (props.language === 'javascript' || props.language === 'typescript') {
        if (props.definitions) {
          languages.typescript[`${props.language}Defaults`].setExtraLibs([]);
        }
      }
      instance.current.dispose();
    };
  }, []);
  useEffect(() => {  
    if (ready && instance.current) {  
      const currentValue = instance.current.getValue();
      if (currentValue !== props.value) {  
        instance.current.setValue(props.value || '');  
      }  
    }  
  }, [props.value, ready]); 
  function onCodeChange() {
    const code = instance.current.getValue();
    props.onChange?.(code);
  }

  useEffect(() => {
    if (ready) {  
      editor.setModelLanguage(instance.current.getModel()!, props.language);  
    }  
  }, [props.language,ready]);

  useEffect(() => {
    if (ready) {  
      updateDefinition();  
    }
  }, [props.definitions,ready]);

  

  return (
    <div className="monaco-editor" style={props.style}>
      <div className="monaco-editor__root" key="editor-root" ref={root}></div>
    </div>
  );
};
