<template>
    <div ref="editorContainer" class="code-editor"
        :style="{ height: height, minHeight: minHeight, maxHeight: maxHeight }"></div>
</template>

<script setup lang="ts">
import { defaultKeymap, history, historyKeymap } from '@codemirror/commands';
import { css } from '@codemirror/lang-css';
import { html } from '@codemirror/lang-html';
import { javascript } from '@codemirror/lang-javascript';
import { json } from '@codemirror/lang-json';
import { EditorState } from '@codemirror/state';
import { EditorView, keymap, placeholder } from '@codemirror/view';
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';

// 可选主题
import { oneDark } from '@codemirror/theme-one-dark';

defineOptions({
    name: 'PaasCodeEditor'
})
// Props
const props = withDefaults(
    defineProps<{
        modelValue: string
        language?: 'javascript' | 'html' | 'css' | 'json' | 'plaintext'
        readonly?: boolean
        theme?: 'light' | 'dark'
        height?: string
        minHeight?: string
        maxHeight?: string
        placeholder?: string
        disabled?: boolean
    }>(),
    {
        modelValue: '',
        language: 'json', // 修改默认语言为json，更适合表单配置
        readonly: false,
        theme: 'light',
        height: '300px', // 设置默认高度
        minHeight: '100px',
        maxHeight: 'none',
        placeholder: '',
        disabled: false
    }
)

// Emit
const emit = defineEmits<{
    (e: 'update:modelValue', value: string): void
}>()

// Refs
const editorContainer = ref<HTMLDivElement | null>(null)
let view: EditorView | null = null

// Get see from store
const see = () => {
    const store = (window as any).store;
    return store?.forms?.see || false;
}

// 创建基础设置扩展
const createBasicSetup = () => [
    // 基础编辑功能
    EditorView.lineWrapping,
    // 历史记录
    history(),
    // 键盘映射
    keymap.of([...defaultKeymap, ...historyKeymap])
]

// 语言映射
const languageExtensions = {
    javascript: [javascript()],
    html: [html()],
    css: [css()],
    json: [json()],
    plaintext: []
}

// 获取当前语言扩展
const getLanguageExtension = () => {
    return languageExtensions[props.language] || languageExtensions.json // 默认使用json
}

// 创建编辑器
const createEditor = () => {
    if (!editorContainer.value) return

    const extensions = [
        ...createBasicSetup(),
        ...getLanguageExtension(),
        EditorView.updateListener.of((update) => {
            if (update.docChanged) {
                const newValue = update.state.doc.toString()
                emit('update:modelValue', newValue)
            }
        }),
        EditorView.editable.of(!see() && !props.readonly && !props.disabled),
        props.placeholder ? placeholder(props.placeholder) : [],
        props.theme === 'dark' ? oneDark : []
    ]

    const state = EditorState.create({
        doc: props.modelValue,
        extensions
    })

    view = new EditorView({
        state,
        parent: editorContainer.value
    })
}

// 销毁编辑器
const destroyEditor = () => {
    if (view) {
        view.destroy()
        view = null
    }
}

// 监听 modelValue 外部变化（如重置内容）
watch(
    () => props.modelValue,
    (newVal) => {
        if (view && view.state.doc.toString() !== newVal) {
            view.dispatch({
                changes: { from: 0, to: view.state.doc.length, insert: newVal }
            })
        }
    }
)

// 监听语言或主题变化（简单处理：重建）
watch(
    () => [props.language, props.theme, props.readonly],
    () => {
        destroyEditor()
        nextTick(() => createEditor())
    }
)

// 初始化 & 清理
onMounted(() => {
    createEditor()
})

onUnmounted(() => {
    destroyEditor()
})
</script>

<style scoped>
.code-editor {
    border: 1px solid #ddd;
    border-radius: 4px;
    overflow: hidden;
    width: 100%;
    font-size: 14px;
}

.code-editor :deep(.cm-scroller) {
    overflow: auto;
    font-size: 13px;
}

.code-editor :deep(.cm-editor) {
    height: 100%;
}
</style>