<template>
    <div :id="`table-form-item-${keyId}`" v-loading="loading" :style="tableFormItemStyle"
         class="hc-table-form-data-item">
        <el-scrollbar v-if="isScroll" class="table-form-item-scrollbar">
            <div :id="`table-form-${keyId}`" class="hc-excel-table-form"/>
        </el-scrollbar>
        <div v-else :id="`table-form-${keyId}`" class="hc-excel-table-form"/>
        <div v-if="isTableForm === false" class="hc-no-table-form">
            <div class="table-form-no">
                <img :src="notableform" alt=""/>
                <div class="desc">暂无表单数据</div>
            </div>
        </div>
    </div>
</template>

<script setup>
import {ref, watch, onMounted, nextTick, onUnmounted} from "vue"
import {useAppStore} from "~src/store";
import HTableForm from "~src/plugins/HTableForm"
import notableform from '~src/assets/view/notableform.svg'
import {getStoreData, setStoreData, delStoreData} from "~uti/storage";
import {getObjNullValue, isAsyncFunction, isString, getArrValue, deepClone, getIndex} from "vue-utils-plus"

const useAppState = useAppStore()

//初始
const props = defineProps({
    tid: { // 树节点
        type: [String, Number],
        default: ''
    },
    kid: { // pkeyId
        type: [String, Number],
        default: ''
    },
    classify: { // 类型
        type: [String, Number],
        default: ''
    },
    api: { //请求方法函数列表
        type: Object,
        default: () => ({
            dataInfo: null,
            bussCols: null,
            excelHtml: null
        })
    },
    height: { // 高度
        type: String,
        default: '100%'
    },
    width: { // 宽度
        type: String,
        default: 'auto'
    },
    scroll: { // 可否滚动
        type: Boolean,
        default: false
    },
    datas: { //变动的数据
        type: Object,
        default: () => ({})
    },
    nodeName: { // 表单名称
        type: String,
        default: ''
    },
})

//初始变量
const projectId = ref(useAppState.getProjectId)
const contractId = ref(useAppState.getContractId)
const keyId = ref(props.kid ? props.kid + '' : '')
const treeId = ref(props.tid)
const classify = ref(props.classify)
const apis = ref(props.api)
const tableFormItemStyle = ref('')
const loading = ref(false)
const isScroll = ref(props.scroll)
const changeData = ref(props.datas)
const nodeNames = ref(props.nodeName)

//监听
watch(() => [
    useAppState.getProjectId,
    useAppState.getContractId,
    props.tid,
    props.kid,
    props.classify,
    props.width,
    props.height,
    props.scroll,
    props.nodeName
], ([project_id, contract_id, tree_id, key_id, cid, width, height, scroll, nodeName]) => {
    projectId.value = project_id
    contractId.value = contract_id
    treeId.value = tree_id
    keyId.value = key_id ? key_id + '' : ''
    classify.value = cid
    isScroll.value = scroll
    nodeNames.value = nodeName
    setItemStyle(width, height)
})

//深度监听变动的对象数据
watch(() => [
    props.datas
], ([data]) => {
    changeData.value = data
    setFormChangeData(data)
}, {deep: true})

//渲染完成
onMounted(async () => {
    let keys = []
    loading.value = true
    const {dataInfo, bussCols, excelHtml} = apis.value
    setItemStyle(props.width, props.height)
    //获取已填写的数据
    if (isAsyncFunction(dataInfo)) {
        await getTableFormInfo(keyId.value, dataInfo)
    }
    //按键key列表
    if (isAsyncFunction(bussCols)) {
        keys = await getHtmlBussColsApi(keyId.value, bussCols)
    }
    //渲染表单
    if (isAsyncFunction(excelHtml)) {
        await getExcelHtml(keyId.value, excelHtml, keys)
    }
    loading.value = false
})

const setFormChangeData = (data) => {
    const form = tableFormInfo.value
    tableFormInfo.value = {
        ...form,
        ...data
    }
    tableFormInfo.value = form
}

//设置样式
const setItemStyle = (width, height) => {
    tableFormItemStyle.value = `width: ${width}; height: ${height};`
}

//事件
const emit = defineEmits(['rightTap', 'render'])

//渲染状态变量
const isTableForm = ref(false)
const tableFormInfo = ref({})

//获取表单初始数据
const getFormDataInit = () => {
    return {
        projectId: projectId.value,
        contractId: contractId.value,
        classify: classify.value,
        pkeyId: keyId.value,
        nodeId: treeId.value,
        isRenderForm: false,
    }
}

//获取已填写的数据
const getTableFormInfo = async (pkeyId, func) => {
    if (pkeyId) {
        const {error, code, data} = await func({
            pkeyId: pkeyId
        }, false)
        const resData = getObjNullValue(data)
        if (!error && code === 200 && resData) {
            HTableForm.setPickerKey(resData)
            tableFormInfo.value = {
                ...resData,
                ...getFormDataInit(),
                ...changeData.value
            }
        } else {
            tableFormInfo.value = {
                ...getFormDataInit(),
                ...changeData.value
            }
        }
    } else {
        tableFormInfo.value = {}
        window?.$message?.warning('pkeyId为空')
    }
}

//获取按键切换输入框的key列表
const getHtmlBussColsApi = async (pkeyId, func) => {
    if (pkeyId) {
        const {error, code, data} = await func({
            pkeyId: pkeyId
        }, false)
        if (!error && code === 200) {
            let keys = getArrValue(data);
            for (let i = 0; i < keys.length; i++) {
                if (keys[i].length <= 0) {
                    keys.splice(i, 1)
                }
            }
            return keys;
        } else {
            return [];
        }
    } else {
        return [];
    }
}

//获取模板标签数据
const getExcelHtml = async (pkeyId, func, keys) => {
    if (pkeyId) {
        const {error, code, data} = await func({
            pkeyId: pkeyId
        }, false)
        const resData = isString(data) ? data || '' : ''
        if (!error && code === 200 && resData) {
            isTableForm.value = true
            //渲染表单
            HTableForm.createForm({
                template: resData,
                tableForm: tableFormInfo.value,
                keys: keys,
                appId: `#table-form-${pkeyId}`,
                onRight: (event, KeyName) => {
                    onRightClick(pkeyId, event, KeyName)
                },
                //表单正则效验
                onBlur: (event, key, reg, val, msg) => {
                    setTableFormBlurReg(pkeyId, event, key, reg, val, msg)
                },
                onLeftClick: (key) => {
                    setShiftTableForm(key)
                },
            })
            tableFormInfo.value.isRenderForm = true
            await nextTick(() => {
                HTableForm.setByClassKeyup(keys)
            })
        } else {
            isTableForm.value = false
            tableFormInfo.value.isRenderForm = false
            window?.$message?.warning('暂无表单')
        }
    } else {
        isTableForm.value = false
        tableFormInfo.value.isRenderForm = false
        window?.$message?.warning('pkeyId为空')
    }
    emit('render', tableFormInfo.value)
}

//正则效验
const formRegExpJson = ref({})
const setTableFormBlurReg = (pkeyId, event, key, reg, val, msg) => {
    const dom = document.getElementById(key)?.parentElement ?? ''
    if (dom) {
        if (val && reg) {
            let regx = new RegExp(reg);
            let state = regx.test(val);
            if (state) {
                delete formRegExpJson.value[key]
                HTableForm.setFormStyle(key, 'hc-red-border')
            } else {
                formRegExpJson.value[key] = {key, reg, val, msg, state}
                HTableForm.setFormStyle(key, 'hc-red-border', true)
                window?.$message?.warning(msg)
            }
        } else {
            delete formRegExpJson.value[key]
            HTableForm.setFormStyle(key, 'hc-red-border')
        }
    } else {
        delete formRegExpJson.value[key]
    }
}


//鼠标右键事件
const onRightClick = (pkeyId, event, KeyName) => {
    //取光标位置
    const specialDom = document.getElementById(KeyName + "")
    const startPos = specialDom?.selectionStart || 0
    const endPos = specialDom?.selectionEnd || 0
    emit('rightTap', {event, KeyName, startPos, endPos, pkeyId})
}

const isCtrlKey = ref(false)
const checkKeyList = ref([])
const copyKeyList = ref(getStoreData('TableFormCopyKeyList') || [])

//设置选择数据
const setShiftTableForm = (key) => {
    if (isCtrlKey.value) {
        const form = tableFormInfo.value
        const keys = checkKeyList.value
        const index = getIndex(keys, 'key', key)
        if (index === -1) {
            keys.push({key: key, val: form[key]})
        } else {
            keys.splice(index, 1)
        }
        checkKeyList.value = keys
        HTableForm.setCheckKeyStyle(key, index !== -1)
    }
}

//全局按键按下监听
document.onkeydown = async (event) => {
    const {key, ctrlKey} = event
    //按下ctrl键
    if (ctrlKey && key === 'Control') {
        isCtrlKey.value = true
    }
    //按下复制快捷键
    if (ctrlKey && key === 'c') {
        const keysList = deepClone(checkKeyList.value)
        if (keysList.length > 0) {
            event.preventDefault()
            setStoreData('TableFormCopyKeyList', keysList)
            copyKeyList.value = keysList
            keysList.forEach(item => {
                HTableForm.setCheckKeyStyle(item['key'], true)
            })
            checkKeyList.value = []
        }
    }
    //按下粘贴快捷键
    if (ctrlKey && key === 'v') {
        const keysList = deepClone(copyKeyList.value)
        const checkList = checkKeyList.value
        if (checkList.length > 0) {
            event.preventDefault()
            //粘贴多个
            if (checkList.length > 1 && keysList.length > 1) {
                await setMultipleCheckValue(checkList, keysList)
            }
            //粘贴单个复制
            if (checkList.length > 1 && keysList.length === 1) {
                await setSingleCopyValue(checkList, keysList)
            }
            //复制单个粘贴
            if (checkList.length === 1 && keysList.length > 1) {
                await setCopySingleValue(checkList, keysList)
            }
            //清除缓存
            checkKeyList.value = []
            copyKeyList.value = []
            delStoreData('TableFormCopyKeyList')
        }
    }
}

//复制单个粘贴
const setCopySingleValue = async (checkList, keysList) => {
    let form_val = '', key = checkList[0]['key']
    const form = tableFormInfo.value
    for (let i = 0; i < keysList.length; i++) {
        const val = form[keysList[i]['key']]
        form_val = form_val ? form_val + '、' + val : val
        keysList.splice(0, 1) //删除第一个元素
    }
    await setTableFormInfoValue(key, form_val)
    HTableForm.setCheckKeyStyle(key, true)
}

//粘贴单个复制
const setSingleCopyValue = async (checkList, keysList) => {
    const form = tableFormInfo.value
    const form_val = form[keysList[0]['key']]
    for (let i = 0; i < checkList.length; i++) {
        const {key} = checkList[i]
        await setTableFormInfoValue(key, form_val)
        HTableForm.setCheckKeyStyle(key, true)
    }
    keysList.splice(0, 1) //删除第一个元素
}


//粘贴多个
const setMultipleCheckValue = async (checkList, keysList) => {
    const form = tableFormInfo.value
    for (let i = 0; i < checkList.length; i++) {
        const {key, val} = checkList[i]
        if (keysList.length > 0) {
            const form_val = form[keysList[0]['key']]
            await setTableFormInfoValue(key, form_val ? form_val : val)
            keysList.splice(0, 1) //删除第一个元素
        } else {
            await setTableFormInfoValue(key, val)
        }
        HTableForm.setCheckKeyStyle(key, true)
    }
}

//设置表单数据
const setTableFormInfoValue = async (key, value) => {
    return new Promise((resolve) => {
        setTimeout(() => {
            tableFormInfo.value[key] = value
            resolve(true)
        }, 100)
    })
}


//全局键盘放开监听
document.onkeyup = (event) => {
    const {key, ctrlKey} = event
    if (!ctrlKey && key === 'Control') {
        isCtrlKey.value = false
    }
}

//卸载页面
onUnmounted(() => {
    document.onkeydown = null
    document.onkeyup = null
})

//获取表单数据
const getFormData = () => {
    return tableFormInfo.value
}

//设置表单数据
const setFormData = (data) => {
    nextTick(() => {
        tableFormInfo.value = data
    })
}

//获取表单效验数据
const getRegExpJson = () => {
    return deepClone(formRegExpJson.value);
}

const getNodeName = () => {
    return nodeNames.value
}

//正则效验
const isFormRegExp = async () => {
    const isRegExp = !!getObjNullValue(formRegExpJson.value)
    if (!isRegExp) {
        return true
    } else {
        window?.$message?.warning('请先修改完红色输入框的数据')
        return false
    }
}

// 暴露出去
defineExpose({
    getFormData,
    setFormData,
    getRegExpJson,
    isFormRegExp,
    getNodeName
})
</script>

<style lang="scss">
//插入特殊字符弹窗的输入框
.hc-table-form-data-item .hc-excel-table-form td,
.hc-table-form-data-item .hc-excel-table-form td .el-input .el-input__wrapper .el-input__inner,
.el-form-item.special-form-item .el-form-item__content .el-input .el-input__wrapper .el-input__inner {
    font-family: "EUDC", 宋体, v-sans, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol" !important;
}
.hc-table-form-data-item {
    position: relative;
    padding: 12px;
    height: 100%;
    overflow: hidden;
    background-color: white;
    .hc-excel-table-form {
        position: relative;
        display: flex;
        padding: 10px;
        justify-content: center;
        td {
            padding: 6px;
            .el-input {
                background-color: #ffffff !important;
                border-radius: 3px;
                color: #606266;
                .el-input__wrapper {
                    background-color: inherit;
                    caret-color: var(--el-color-primary);
                }
                .el-input__suffix-inner {
                    width: 18px;
                }
            }
            .el-textarea {
                width: 100%;
                height: 100%;
                .el-textarea__inner {
                    min-height: initial !important;
                    background-color: #ffffff;
                    border-radius: 3px;
                    color: #606266;
                    height: 100%;
                    caret-color: var(--el-color-primary);
                }
            }
            //日期选择框
            .el-date-editor.el-input .el-input__wrapper,
            .el-date-editor.el-date-editor--datetimerange.el-input__wrapper {
                height: 100%;
                width: 100%;
            }
            //焦点
            .el-input .el-input__wrapper.is-focus, .el-input .el-input__wrapper:hover,
            .el-textarea .el-textarea__inner:hover {
                box-shadow: 0 0 0 1.5px var(--el-input-focus-border-color) inset;
                background-color: #eddac4;
            }
            //公式
            &[gscolor] {
                .el-input, .el-textarea .el-textarea__inner {
                    background-color: #dcdcdc !important;
                }
            }
            //文本选中颜色
            .el-input .el-input__wrapper input,
            .el-textarea textarea {
                &::selection {
                    background: var(--el-color-primary-light-9);
                    color: var(--el-color-primary);
                }
                &::-moz-selection {
                    background: var(--el-color-primary-light-9);
                    color: var(--el-color-primary);
                }
            }
            //下拉框
            .el-select {
                width: 100%;
                height: 100%;
            }
        }
        //非输入框颜色
        td:not([titlexx]), td[titlexx*=''],
        td:not([title]), td[title*=''] {
            background-color: white !important;
            user-select: none;
        }
    }
    .hc-no-table-form {
        position: relative;
        height: 100%;
        display: flex;
        justify-content: center;
        align-items: center;
        .table-form-no {
            position: relative;
            img {
                width: 350px;
            }
            .desc {
                text-align: center;
                font-size: 20px;
                color: #aaa;
            }
        }
    }
}

.hc-red-border {
    &.el-textarea__inner, &.el-input .el-input__wrapper {
        --el-input-border-color: #fe0000 !important;
        box-shadow: 0 0 0 2px #fe0000 inset !important;
    }
}

.hc-green-border {
    &.el-textarea__inner, &.el-input .el-input__wrapper {
        --el-input-border-color: #1ECC95 !important;
        box-shadow: 0 0 0 2px #1ECC95 inset !important;
    }
}

</style>
