<template>
    <div :style="{ position: 'relative', height: row.height }" @click="closeContextmenu">
        <v-ace-editor
            ref="myEditorRef"
            v-model:value="(model as string)"
            class="editor"
            :readonly="row.disabled?.()"
            :lang="row.lang || 'sql'"
            theme="chrome"
            width="100%"
            :style="{ height: '100%', width: '100%' }"
            :options="options"
            :autoComplete="true"
            :placeholder="$t(row.placeholder?.() || 'pleaseInput')"
            @init="editorInit"
        />
        <!-- 右键自定义菜单，仅在 row.contextmenu 有值时挂载 -->
        <ul
            v-if="row.contextmenu?.length && contextmenuState.visible"
            class="ace-contextmenu"
            :style="{ left: contextmenuState.x + 'px', top: contextmenuState.y + 'px' }"
        >
            <li
                v-for="(item, index) in row.contextmenu"
                :key="index"
                class="ace-contextmenu__item"
                :class="{ 'is-disabled': item.disabled?.() }"
                @click.stop="handleContextmenuClick(item)"
            >{{ item.label }}</li>
        </ul>
    </div>
</template>
<script lang="ts">
import { reactive, defineComponent, ref, onMounted, PropType } from 'vue'
import { AceEditorInterface, AceOptionsInterface } from './index'
import { ObjectInterface } from '../../../script/index'
import { VAceEditor } from 'vue3-ace-editor'
import 'ace-builds/src-noconflict/mode-sql'
import 'ace-builds/src-noconflict/mode-xml'
import 'ace-builds/src-noconflict/theme-chrome'
import 'ace-builds/src-noconflict/ext-language_tools'
import 'ace-builds/src-noconflict/mode-javascript'
import 'ace-builds/src-noconflict/mode-html'
import 'ace-builds/src-noconflict/mode-json'
// 格式化sql
import { format } from 'sql-formatter'
// 格式化xml
import xmlFormat from 'xml-formatter'
import useModel from '../../../script/help/useModel'
import { ElMessage } from 'element-plus'
export default defineComponent({
    components: { VAceEditor },
    props: {
        row: {
            type: Object as PropType<AceEditorInterface>,
            default: () => {}
        },
        modelData: {
            type: Object,
            default: () => {}
        }
    },
    setup (props) {
        const { row, modelData } = props
        // let editor = reactive<ObjectInterface>({
        //     text: {}
        // })
        const myEditorRef = ref()
        const options = reactive<AceOptionsInterface>({
            useSoftTabs: true,
            tabSize: 2,
            showLineNumbers: true,
            showPrintMargin: false,
            fontSize: 14,
            enableLiveAutocompletion: true,
            wrap: true
        })
        let model = useModel(modelData, row.model, row.deepData)
        const sqlFormatter = (): void => {
            if (!model.value) {
                ElMessage.error(window.$t?.('pleaseInputSql') || 'pleaseInputSql')
                return
            }
            model.value = format(model.value as string)
        }

        const xmlFormatter = ():void => {
            if (!model.value) return
            model.value = xmlFormat(model.value as string, {indentation: '  '})
        }
        const editorInit = (paramsEditor: ObjectInterface): void => {
            // editor.text = paramsEditor
            if (row.sqlFormatter && row.lang === 'sql') {
                sqlFormatter()
            } else if (row.lang === 'xml') {
                xmlFormatter()
            }
            // 绑定右键菜单
            // contextmenu 格式:
            // [
            //   { label: '菜单文字', method: (editor) => void, disabled?: () => boolean }
            // ]
            if (row.contextmenu?.length) {
                paramsEditor.container.addEventListener('contextmenu', (e: MouseEvent) => {
                    e.preventDefault()
                    contextmenuState.visible = true
                    contextmenuState.x = e.clientX
                    contextmenuState.y = e.clientY
                })
            }
        }
        // 右键菜单显示状态
        const contextmenuState = reactive({
            visible: false,
            x: 0,
            y: 0
        })
        const handleContextmenuClick = (item: any): void => {
            const editor = myEditorRef.value?._editor
            if (!editor) return
            item.method(editor)
            contextmenuState.visible = false
        }
        const closeContextmenu = (): void => {
            contextmenuState.visible = false
        }
        // 格式化xml方法
        const formatXml = (xml) => {
            let reg
            reg = /(>)(<)(\/*)/g // 添加换行符号
            const xmlString = xml.replace(reg, '$1\r\n$2$3')
            return xmlString
        }
        // 在光标处插入文本
        const insert = (val: string) => {
            const editor = myEditorRef.value?._editor
            if (!editor) return
            editor.session.insert(editor.getCursorPosition(), val)
            editor.focus()
        }
        onMounted(() => {
            //
        })
        return {
            options,
            model,
            myEditorRef,
            editorInit,
            sqlFormatter,
            xmlFormatter,
            insert,
            contextmenuState,
            handleContextmenuClick,
            closeContextmenu
        }
    }
})
</script>
<style lang="scss" scoped>
.editor {
    border: 1px solid #E4E7ED;
    border-radius: 5px;
}
.ace-contextmenu {
    position: fixed;
    z-index: 9999;
    margin: 0;
    padding: 4px 0;
    list-style: none;
    background: #fff;
    border: 1px solid #E4E7ED;
    border-radius: 4px;
    box-shadow: 0 2px 12px rgba(0, 0, 0, 0.12);
    min-width: 120px;
    &__item {
        padding: 6px 16px;
        font-size: 13px;
        color: #303133;
        cursor: pointer;
        white-space: nowrap;
        &:hover {
            background: #F5F7FA;
        }
        &.is-disabled {
            color: #C0C4CC;
            cursor: not-allowed;
            pointer-events: none;
        }
    }
}
</style>
