<template>
    <div v-loading="treeNodeLoading" class="cu-tree-node-container" @mousewheel.prevent="treeNodeMousewheel">
        <div v-if="!!nodes.label" :id="'tree-node-' + uuid" :style="{zoom: zoomRef + '%'}"
             class="cu-tree-node-box horizontal collapsable" @mousedown="treeNodeMouseDown">
            <div class="cu-tree-node-view">
                <div class="cu-tree-node-label">
                    <div class="cu-tree-node-label-text">
                        <div :id="`node-tree-${nodes.key}`" class="cu-tree-node-label-name">
                            <el-button :loading="nodes.loading" hc-btn type="primary">{{ nodes.label }}</el-button>
                        </div>
                    </div>
                </div>
                <TreeNodeChildren :data="nodes.childNodes" :parentNodes="nodes" @expandClick="expandClick"
                                  @menuClick="poverMenuClick" @nodeClick="nodeLabelClick"
                                  @nodeDblClick="nodeLabelDblClick"/>
            </div>
        </div>
        <!--右键菜单-->
        <HcContextMenu v-if="menusData.length > 0" ref="contextMenuRef" :datas="menusData"
                       @item-click="handleMenuSelect">
            <template #mark="{item}">
                <HcIcon :fill="treeRefData?.isFirst" :name="item.icon" class="menu-item-icon"/>
                <span class="menu-item-name">{{ treeRefData?.isFirst ? '取消标记为首件' : '标记为首件' }}</span>
            </template>
            <template #sort="{item}">
                <HcIcon :line="false" :name="item.icon" class="menu-item-icon"/>
                <span class="menu-item-name">{{ item.label }}</span>
            </template>
        </HcContextMenu>
    </div>
</template>

<script setup>
import {watch, ref, onMounted, nextTick} from "vue";
import TreeNodeChildren from "./children.vue";
import wbsApi from "~api/data-fill/wbs"
import {getObjValue, getArrValue, getRandom, isArrItem} from "js-fast-way"

//参数
const props = defineProps({
    autoExpandKeys: {
        type: Array,
        default: () => ([])
    },
    menus: {
        type: Array,
        default: () => ([])
    },
    isMark: {
        type: Boolean,
        default: false
    },
    accordion: {
        type: Boolean,
        default: false
    },
    projectId: {
        type: [String, Number],
        default: ''
    },
    contractId: {
        type: [String, Number],
        default: ''
    },
})

//初始数据
const uuid = getRandom()
const datas = ref({})
const nodes = ref({})
const menusData = ref(props.menus)
const menuMark = ref(props.isMark)
const projectId = ref(props.projectId);
const contractId = ref(props.contractId);
const TreeExpandKey = ref(props.autoExpandKeys)
const treeRefNode = ref(null)
const treeRefData = ref(null)

//监听
watch(() => [
    props.autoExpandKeys,
    props.menus,
    props.isMark,
    props.projectId,
    props.contractId,
], ([expandKeys, menus, isMark, UserProjectId, UserContractId]) => {
    TreeExpandKey.value = expandKeys
    menusData.value = menus
    menuMark.value = isMark
    projectId.value = UserProjectId
    contractId.value = UserContractId
})

//渲染完成
onMounted(() => {
    getTreeOneLevel()
})

//导图结构树节点查询
const treeNodeLoading = ref(false)
const getTreeOneLevel = async () => {
    treeNodeLoading.value = true
    const data = await queryMappingStructureTree({
        contractId: contractId.value,
        contractIdRelation: '',
        primaryKeyId: '',
        parentId: '',
    })
    //处理数据
    const res = getObjValue(data[0])
    //自动展开第二级
    const keys = TreeExpandKey.value || []
    if (keys.length > 0 && res?.id) {
        const children = await queryMappingStructureTree({
            contractId: contractId.value,
            contractIdRelation: res?.contractIdRelation,
            primaryKeyId: res?.primaryKeyId,
            parentId: res?.id,
        })
        if (children.length > 0) {
            await setTreeExpandKey(children, res)
        }
    }
    datas.value = res
    setDatasToNodes()
    treeNodeLoading.value = false
}

//设置自动展开
const setTreeExpandKey = async (arr, res) => {
    const keys = TreeExpandKey.value || []
    res.children = []
    for (const item of arr) {
        if (isArrItem(keys, item?.primaryKeyId)) {
            const children = await queryMappingStructureTree({
                contractId: contractId.value,
                contractIdRelation: item?.contractIdRelation,
                primaryKeyId: item?.primaryKeyId,
                parentId: item?.id,
            })
            if (children.length > 0) {
                await setTreeExpandKey(children, item)
            }
        }
        res.children.push(item)
    }
}

//获取数据
const queryMappingStructureTree = async (form) => {
    const {error, code, data} = await wbsApi.queryMappingStructureTree({
        ...form,
        wbsType: 1
    })
    //处理数据
    if (!error && code === 200) {
        return getArrValue(data)
    } else {
        return []
    }
}

//处理为node节点类型的数据
const setDatasToNodes = () => {
    const deepData = datas.value
    let childNodes = getArrValue(deepData['children'])
    nodes.value = {
        childNodes: childNodes,
        childrenNodes: [],
        data: deepData,
        parentNodes: {},
        expanded: deepData['expanded'] || false,
        isExpand: deepData['isExpand'] || false,
        isLeaf: deepData['isLeaf'] || false,
        loading: deepData['loading'] || false,
        key: deepData['primaryKeyId'] || '',
        label: deepData['title'] || ''
    }
}

//放大缩小
const zoomRef = ref(100)
const treeNodeMousewheel = (event) => {
    /* 获取当前页面的缩放比 若未设置zoom缩放比，则为默认100%，即1，原图大小 */
    let zoom = parseInt(zoomRef.value + '') || 100
    /* event.wheelDelta 获取滚轮滚动值并将滚动值叠加给缩放比zoom wheelDelta统一为±120，其中正数表示为向上滚动，负数表示向下滚动 */
    zoom += event.wheelDelta / 12
    /* 最小范围 和 最大范围 的图片缩放尺度 */
    if (zoom >= 10 && zoom < 200) {
        zoomRef.value = zoom
    }
    return false
}

const isDown = ref(false)
const treeNodeMouseDown = (event) => {
    // 阻止默认事件和冒泡
    event.preventDefault()
    event.stopPropagation()
    //获取相关dom元素
    let dom = document.getElementById('tree-node-' + uuid)
    //获取x坐标和y坐标
    let clientX = event.clientX, clientY = event.clientY;

    //获取左部和顶部的偏移量
    let offsetLeft = dom.offsetLeft, offsetTop = dom.offsetTop;
    //开关打开
    isDown.value = true;

    //设置样式
    dom.style.cursor = 'move';

    document.onmousemove = (e) => {
        if (isDown.value === false) {
            return;
        }
        //获取x和y
        let nx = e.clientX;
        let ny = e.clientY;
        //计算移动后的左偏移量和顶部的偏移量
        let nl = nx - (clientX - offsetLeft);
        let nt = ny - (clientY - offsetTop);

        dom.style.left = nl + 'px';
        dom.style.top = nt + 'px';
    }
    document.onmouseup = () => {
        //开关关闭
        isDown.value = false;
        dom.style.cursor = 'default';
        document.onmousemove = null;
        document.onmouseup = null;
    }
}

//处理自动展开的节点KEY
const getNodeExpandKeys = async (node, newKeys) => {
    const parent = node?.parentNodes ?? []
    const primaryKeyId = node?.data?.primaryKeyId ?? ''
    if (primaryKeyId) {
        newKeys.push(primaryKeyId)
        await getNodeExpandKeys(parent, newKeys)
    }
}

const emit = defineEmits(['expand', 'nodeClick', 'nodeDblClick', 'menuClick']);

//导图结构展开和收缩被点击
const expandClick = ({node, data}) => {
    if (!node.children) {
        node.expanded = false;
    }
    node.isExpand = !node.isExpand;
    emit('expand', {node, data})
}

//鼠标左键单击事件
const nodeLabelClick = async ({node, data}) => {
    if (data?.notExsitChild) {
        await awaitNodeClick(node, data)
    } else {
        let ifChildren = !!(node.childNodes && node.childNodes.length > 0);
        if (ifChildren) {
            node.expanded = true;
            node.isExpand = true;
            node.loading = false
            await awaitNodeClick(node, data)
        } else {
            node.loading = true
            const children = await queryMappingStructureTree({
                contractId: contractId.value,
                contractIdRelation: data?.contractIdRelation,
                primaryKeyId: data?.primaryKeyId,
                parentId: data?.id,
            })
            node.childNodes = children
            await nextTick(async () => {
                if (children.length > 0) {
                    node.expanded = true;
                    node.isExpand = true;
                } else {
                    node.expanded = false;
                    node.expanded = false;
                }
                node.loading = false
                await awaitNodeClick(node, data)
            })
        }
    }
}

//处理数据
const awaitNodeClick = async (node, data) => {
    let autoKeysArr = []
    await getNodeExpandKeys(node, autoKeysArr)
    const autoKeys = autoKeysArr.reverse()
    emit('nodeClick', {node, data, keys: autoKeys})
}

//双击事件
const nodeLabelDblClick = (item) => {
    emit('nodeDblClick', item)
}

//菜单被点击
const contextMenuRef = ref(null)
const poverMenuClick = (event, node, data) => {
    const rows = menusData.value || [];
    if (rows.length > 0) {
        event.preventDefault();
        treeRefNode.value = node;
        treeRefData.value = data;
        contextMenuRef.value?.showMenu(event)
    }
}

//鼠标右键菜单被点击
const handleMenuSelect = ({key}) => {
    const node = treeRefNode.value;
    const data = treeRefData.value;
    //如果为标记菜单
    if (key === 'mark' && menuMark.value) {
        if (data.isFirst === true) {
            emit('menuClick', {key: 'cancel_mark', node, data})
        } else {
            emit('menuClick', {key: 'mark', node, data})
        }
    } else {
        emit('menuClick', {key, node, data})
    }
}
</script>

<style lang="scss">
@import "style";
</style>
