<template>
  <div class="codemirror-editor">
    <div ref="editorContainer" class="editor-container"></div>
  </div>
</template>

<script>
import { EditorView, keymap, highlightActiveLine, highlightActiveLineGutter, lineNumbers, scrollPastEnd } from '@codemirror/view'
import { EditorState, Compartment } from '@codemirror/state'
import { defaultKeymap, history, historyKeymap } from '@codemirror/commands'
import { searchKeymap, highlightSelectionMatches } from '@codemirror/search'
import { autocompletion, completionKeymap, closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete'
import { foldGutter, indentOnInput, indentUnit, bracketMatching } from '@codemirror/language'
import { highlightSelectionMatches as highlightSelection } from '@codemirror/search'
import { javascript } from '@codemirror/lang-javascript'
import { php } from '@codemirror/lang-php'
import { oneDark } from '@codemirror/theme-one-dark'
import { env } from '../../lang-env.js'

export default {
  name: 'CodeEditor',
  props: {
    modelValue: {
      type: String,
      default: ''
    },
    language: {
      type: String,
      default: 'env' // 'env', 'javascript', 'php'
    },
    theme: {
      type: String,
      default: 'light' // 'light', 'dark'
    },
    readonly: {
      type: Boolean,
      default: false
    },
    placeholder: {
      type: String,
      default: ''
    }
  },
  emits: ['update:modelValue', 'change'],
  data() {
    return {
      editor: null,
      languageCompartment: new Compartment(),
      themeCompartment: new Compartment()
    }
  },
  mounted() {
    this.initEditor();
  },
  watch: {
    modelValue(newValue) {
      if (this.editor && newValue !== this.editor.state.doc.toString()) {
        this.editor.dispatch({
          changes: {
            from: 0,
            to: this.editor.state.doc.length,
            insert: newValue || ''
          }
        });
      }
    },
    language() {
      this.updateLanguage();
    },
    theme() {
      this.updateTheme();
    }
  },
  beforeUnmount() {
    if (this.editor) {
      this.editor.destroy();
    }
  },
  methods: {
    getLanguageExtension() {
      switch (this.language) {
        case 'javascript':
          return javascript();
        case 'php':
          return php();
        case 'env':
          return env();
        default:
          return [];
      }
    },

    getThemeExtension() {
      return this.theme === 'dark' ? oneDark : [];
    },

    initEditor() {
      const extensions = [
        lineNumbers(),
        highlightActiveLineGutter(),
        highlightActiveLine(),
        foldGutter(),
        indentOnInput(),
        indentUnit.of('  '),
        bracketMatching(),
        closeBrackets(),
        autocompletion(),
        highlightSelectionMatches(),
        history(),
        scrollPastEnd(),
        keymap.of([
          ...closeBracketsKeymap,
          ...defaultKeymap,
          ...searchKeymap,
          ...historyKeymap,
          ...completionKeymap,
        ]),
        this.languageCompartment.of(this.getLanguageExtension()),
        this.themeCompartment.of(this.getThemeExtension()),
        EditorView.updateListener.of((update) => {
          if (update.docChanged) {
            const content = update.state.doc.toString();
            this.$emit('update:modelValue', content);
            this.$emit('change', content);
          }
        }),
        // 确保编辑器可以滚动
        EditorView.theme({
          '&': {
            height: '100%'
          },
          '.cm-scroller': {
            fontFamily: 'inherit',
            overflow: 'auto'
          },
          '.cm-content': {
            padding: '12px',
            minHeight: '100%'
          },
          '.cm-editor': {
            height: '100%'
          },
          '.cm-focused': {
            outline: 'none'
          }
        })
      ];

      // 添加只读模式
      if (this.readonly) {
        extensions.push(EditorView.editable.of(false));
      }

      const state = EditorState.create({
        doc: this.modelValue || '',
        extensions
      });

      this.editor = new EditorView({
        state,
        parent: this.$refs.editorContainer
      });
    },

    updateLanguage() {
      if (!this.editor) return;

      this.editor.dispatch({
        effects: this.languageCompartment.reconfigure(this.getLanguageExtension())
      });
    },

    updateTheme() {
      if (!this.editor) return;

      this.editor.dispatch({
        effects: this.themeCompartment.reconfigure(this.getThemeExtension())
      });
    }
  }
}
</script>

<style scoped>
.codemirror-editor {
  width: 100%;
  height: 100%;
  border-radius: 8px;
  border: 1px solid #e5e7eb;
  background: #ffffff;
  display: flex;
  flex-direction: column;
}

.editor-container {
  width: 100%;
  height: 100%;
  flex: 1;
  min-height: 0;
}

/* CodeMirror 自定义样式 */
.codemirror-editor :deep(.cm-editor) {
  font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', 'Monaco', 'Inconsolata', 'Consolas', monospace;
  font-size: 14px;
  line-height: 1.6;
  height: 100%;
}

.codemirror-editor :deep(.cm-scroller) {
  overflow: auto !important;
  max-height: 100%;
}

/* 基本语法高亮样式 */
.codemirror-editor :deep(.cm-variableName) {
  color: #0969da;
  font-weight: 600;
}

.codemirror-editor :deep(.cm-string) {
  color: #0a3069;
}

.codemirror-editor :deep(.cm-number) {
  color: #0550ae;
}

.codemirror-editor :deep(.cm-keyword) {
  color: #8250df;
  font-weight: 500;
}

.codemirror-editor :deep(.cm-operator) {
  color: #cf222e;
}

.codemirror-editor :deep(.cm-comment) {
  color: #6a737d;
  font-style: italic;
}

.codemirror-editor :deep(.cm-content) {
  padding: 12px;
  min-height: 100%;
}

.codemirror-editor :deep(.cm-focused) {
  outline: none;
}

/* 自定义滚动条样式 */
.codemirror-editor :deep(.cm-scroller)::-webkit-scrollbar {
  width: 8px;
  height: 8px;
}

.codemirror-editor :deep(.cm-scroller)::-webkit-scrollbar-track {
  background: #f1f1f1;
  border-radius: 4px;
}

.codemirror-editor :deep(.cm-scroller)::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 4px;
}

.codemirror-editor :deep(.cm-scroller)::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}

/* 深色主题样式 */
.codemirror-editor.dark :deep(.cm-editor) {
  background: #1e1e1e;
  color: #d4d4d4;
}

.codemirror-editor.dark :deep(.cm-scroller)::-webkit-scrollbar-track {
  background: #2d2d2d;
}

.codemirror-editor.dark :deep(.cm-scroller)::-webkit-scrollbar-thumb {
  background: #555;
}

.codemirror-editor.dark :deep(.cm-scroller)::-webkit-scrollbar-thumb:hover {
  background: #777;
}
</style>
