<template>
  <div ref="dom" class="code-editor"></div>
</template>
<script lang="ts" setup>
import { onMounted, onUnmounted, ref, watch } from 'vue';

//按需引入
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import 'monaco-editor/esm/vs/editor/browser/widget/codeEditorWidget.js';
import 'monaco-editor/esm/vs/editor/contrib/bracketMatching/browser/bracketMatching.js';
import 'monaco-editor/esm/vs/editor/contrib/caretOperations/browser/caretOperations.js';
import 'monaco-editor/esm/vs/editor/contrib/caretOperations/browser/transpose.js';
import 'monaco-editor/esm/vs/editor/contrib/clipboard/browser/clipboard.js';
import 'monaco-editor/esm/vs/editor/contrib/codeAction/browser/codeActionContributions.js';
import 'monaco-editor/esm/vs/editor/contrib/copyPaste/browser/copyPasteContribution.js';
import 'monaco-editor/esm/vs/editor/contrib/comment/browser/comment.js';
import 'monaco-editor/esm/vs/editor/contrib/contextmenu/browser/contextmenu.js';
import 'monaco-editor/esm/vs/editor/contrib/cursorUndo/browser/cursorUndo.js';
import 'monaco-editor/esm/vs/editor/contrib/find/browser/findController.js';
import 'monaco-editor/esm/vs/editor/contrib/folding/browser/folding.js';
import 'monaco-editor/esm/vs/editor/contrib/format/browser/formatActions.js';
import 'monaco-editor/esm/vs/editor/contrib/documentSymbols/browser/documentSymbols.js';
import 'monaco-editor/esm/vs/editor/contrib/inlineCompletions/browser/inlineCompletions.contribution.js';
import 'monaco-editor/esm/vs/editor/contrib/hover/browser/hover.js';
import 'monaco-editor/esm/vs/editor/contrib/indentation/browser/indentation.js';
import 'monaco-editor/esm/vs/editor/contrib/inlayHints/browser/inlayHintsContribution.js';
import 'monaco-editor/esm/vs/editor/contrib/inPlaceReplace/browser/inPlaceReplace.js';
import 'monaco-editor/esm/vs/editor/contrib/lineSelection/browser/lineSelection.js';
import 'monaco-editor/esm/vs/editor/contrib/linesOperations/browser/linesOperations.js';
import 'monaco-editor/esm/vs/editor/contrib/linkedEditing/browser/linkedEditing.js';
import 'monaco-editor/esm/vs/editor/contrib/links/browser/links.js';
import 'monaco-editor/esm/vs/editor/contrib/longLinesHelper/browser/longLinesHelper.js';
import 'monaco-editor/esm/vs/editor/contrib/multicursor/browser/multicursor.js';
import 'monaco-editor/esm/vs/editor/contrib/parameterHints/browser/parameterHints.js';
import 'monaco-editor/esm/vs/editor/contrib/rename/browser/rename.js';
import 'monaco-editor/esm/vs/editor/contrib/semanticTokens/browser/documentSemanticTokens.js';
import 'monaco-editor/esm/vs/editor/contrib/semanticTokens/browser/viewportSemanticTokens.js';
import 'monaco-editor/esm/vs/editor/contrib/smartSelect/browser/smartSelect.js';
import 'monaco-editor/esm/vs/editor/contrib/snippet/browser/snippetController2.js';
import 'monaco-editor/esm/vs/editor/contrib/stickyScroll/browser/stickyScrollContribution.js';
import 'monaco-editor/esm/vs/editor/contrib/suggest/browser/suggestController.js';
import 'monaco-editor/esm/vs/editor/contrib/suggest/browser/suggestInlineCompletions.js';
import 'monaco-editor/esm/vs/editor/contrib/tokenization/browser/tokenization.js';
import 'monaco-editor/esm/vs/editor/contrib/toggleTabFocusMode/browser/toggleTabFocusMode.js';
import 'monaco-editor/esm/vs/editor/contrib/unicodeHighlighter/browser/unicodeHighlighter.js';
import 'monaco-editor/esm/vs/editor/contrib/unusualLineTerminators/browser/unusualLineTerminators.js';
import 'monaco-editor/esm/vs/editor/contrib/wordHighlighter/browser/wordHighlighter.js';
import 'monaco-editor/esm/vs/editor/contrib/wordOperations/browser/wordOperations.js';
import 'monaco-editor/esm/vs/editor/contrib/wordPartOperations/browser/wordPartOperations.js';

// import editorWorker from 'monaco-editor/esm/vs/editor/editor.worker?worker';
// import jsonWorker from 'monaco-editor/esm/vs/language/json/json.worker?worker';
// import tsWorker from 'monaco-editor/esm/vs/language/typescript/ts.worker?worker';

import 'monaco-editor/esm/vs/language/json/monaco.contribution';
import 'monaco-editor/esm/vs/basic-languages/javascript/javascript.contribution';
import 'monaco-editor/esm/vs/basic-languages/markdown/markdown.contribution';
import 'monaco-editor/esm/vs/basic-languages/sql/sql.contribution';

const dom = ref<any>();

const { modelValue, json, language, options } = defineProps<{
  modelValue: any;
  json?: boolean;
  language?: string;
  options?: any;
}>();

const emit = defineEmits(['update:modelValue', 'change']);

// self.MonacoEnvironment = {
//   getWorker(_: any, label: string) {
//     if (label === 'json') {
//       return new jsonWorker();
//     }
//     if (label === 'typescript' || label === 'javascript') {
//       return new tsWorker();
//     }
//     return new editorWorker();
//   },
// };

let editor: monaco.editor.IStandaloneCodeEditor;

onMounted(() => {
  let text = '';
  if (json) {
    if (modelValue) {
      text = JSON.stringify(modelValue);
    }
  } else {
    text = modelValue;
  }
  let theme = localStorage.getItem('le-theme')==='light'?'vs':'vs-dark';
  editor = monaco.editor.create(dom.value, {
    value: text,
    automaticLayout: true,
    minimap: { enabled: false },
    language: language || 'javascript',
    theme,
    lineNumbersMinChars:1,
    lineDecorationsWidth:0,
    ...options,
  });
  editor.onDidChangeModelContent(() => {
    const currenValue = editor.getValue();
    if (json) {
      let obj: any;
      try {
        obj = JSON.parse(currenValue);
      } catch {}
      emit('update:modelValue', obj);
      emit('change', obj);
    } else {
      emit('update:modelValue', currenValue);
      emit('change', currenValue);
    }
  });

  setTimeout(() => {
    editor.getAction('editor.action.formatDocument').run();
  }, 300);
});

// watch(
//   () => modelValue,
//   (newValue) => {
//     if (editor) {
//       const value = editor.getValue();
//       newValue = json ? JSON.stringify(newValue) : newValue;
//       if (newValue !== value) {
//         editor.setValue(newValue);
//       }
//     }
//   }
// );

watch(
  () => options,
  (newValue) => {
    editor.updateOptions(newValue);
  },
  { deep: true }
);

watch(
  () => language,
  (newValue) => {
    monaco.editor.setModelLanguage(editor.getModel()!, newValue);
  }
);

onUnmounted(() => {
  editor?.dispose();
});
</script>
<style lang="postcss" scoped>
.code-editor {
  border: 1px solid var(--color-sub-border);
  width: 100%;
  min-height: 160px;

  :deep(.monaco-editor) {
    --vscode-editorGutter-background: var(--color-background-editor);
    --vscode-editor-background: var(--color-background-editor);

    .view-overlays .current-line {
      border: 1px solid var(--color-border-editor);
    }
  }
}
</style>
