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

<script>
import { ref, onMounted, onBeforeUnmount, defineProps, defineEmits } from "vue";
import { EditorView, keymap, gutter, GutterMarker, lineNumbers } from "@codemirror/view";
import { EditorState, StateField, StateEffect } from "@codemirror/state";
import { defaultKeymap, indentWithTab } from "@codemirror/commands";
import { RangeSet } from "@codemirror/rangeset";
import { javascript } from "@codemirror/lang-javascript";
import { oneDark } from "@codemirror/theme-one-dark";
import { indentUnit } from "@codemirror/language";

class BreakpointMarker extends GutterMarker {
  toDOM() {
    const marker = document.createElement("div");
    marker.className = "breakpoint-marker";
    marker.textContent = "●";
    return marker;
  }
}

export default {
  name: "CodeEditor",
  props: {
    modelValue: String, // 双向绑定代码内容
    language: String, // 代码语言，默认 JS
    height: {
      type: String,
      default: '600px'
    }
  },
  emits: ["update:modelValue"], // 监听代码变更
  setup(props, { emit }) {
    const editor = ref(null);
    let editorView = null;

    const setBreakpoint = StateEffect.define();
    const breakpointsField = StateField.define({
      create: () => new Set(),
      update(breakpoints, tr) {
        const newBreakpoints = new Set(breakpoints);
        for (let effect of tr.effects) {
          if (effect.is(setBreakpoint)) {
            const line = effect.value;
            if (newBreakpoints.has(line)) {
              newBreakpoints.delete(line);
            } else {
              newBreakpoints.add(line);
            }
          }
        }
        return newBreakpoints;
      },
    });

    const breakpointGutter = gutter({
      class: "cm-breakpoint-gutter",
      markers: (view) => {
        const breakpoints = view.state.field(breakpointsField);
        const markers = [];
        for (const line of breakpoints) {
          try {
            const lineInfo = view.state.doc.line(line);
            markers.push(new BreakpointMarker().range(lineInfo.from));
          } catch (e) {
            console.warn("Invalid line number skipped:", line);
          }
        }
        return RangeSet.of(markers, true);
      },
      domEventHandlers: {
        click: (view, block) => {
          const lineNumber = view.state.doc.lineAt(block.from).number;
          view.dispatch({
            effects: [setBreakpoint.of(lineNumber)],
          });
          return true;
        },
      },
    });

    onMounted(() => {
      if (!editor.value) return;

      editorView = new EditorView({
        state: EditorState.create({
          doc: props.modelValue || "",
          extensions: [
            lineNumbers(),
            breakpointGutter,
            breakpointsField,
            javascript(),
            oneDark,
            indentUnit.of("    "), // 使用4个空格作为缩进
            keymap.of([
              ...defaultKeymap,
              indentWithTab
            ]),
            EditorView.updateListener.of((update) => {
              if (update.docChanged) {
                emit("update:modelValue", update.state.doc.toString());
              }
            }),
            EditorView.theme({
              "&": {
                fontSize: "14px",
                height: "100%"
              },
              ".cm-content": {
                fontFamily: "'Fira Code', monospace",
                padding: "12px 0",
              },
              ".cm-line": {
                padding: "0 12px",
                lineHeight: "1.6"
              },
              ".cm-gutters": {
                backgroundColor: "#1e1e1e",
                color: "#666",
                border: "none"
              },
              ".cm-activeLineGutter": {
                backgroundColor: "#333"
              },
              ".cm-activeLine": {
                backgroundColor: "rgba(255,255,255,0.03)"
              }
            }),
            EditorView.baseTheme({
              ".cm-breakpoint-gutter": { 
                width: "30px", 
                backgroundColor: "#1e1e1e",
                borderRight: "1px solid #333" 
              },
              ".breakpoint-marker": { 
                color: "#ff5555", 
                fontSize: "14px", 
                cursor: "pointer", 
                textAlign: "center" 
              },
            }),
          ],
        }),
        parent: editor.value,
      });
    });

    onBeforeUnmount(() => {
      editorView?.destroy();
    });

    return { editor };
  },
};
</script>

<style>
.editor-container {
  width: 100%;
  height: 100%;
  background: #282c34;
}

.code-editor {
  height: 100%;
  overflow: auto;
}

/* 自定义滚动条样式 */
.code-editor ::-webkit-scrollbar {
  width: 12px;
  height: 12px;
}

.code-editor ::-webkit-scrollbar-track {
  background: #21252b;
}

.code-editor ::-webkit-scrollbar-thumb {
  background: #454c59;
  border-radius: 6px;
  border: 3px solid #21252b;
}

.code-editor ::-webkit-scrollbar-thumb:hover {
  background: #535b6a;
}
</style>
