<template>
    <Tree
        ref="tree"
        :data="innerData"
        v-bind="$attrs"
    >
        <template #title="slotProps">
            <component :is="{ render: () => renderWrapper(slotProps) }" />
        </template>
    </Tree>
</template>

<script>
import { h } from "vue"
import { Tree } from "view-ui-plus"

export default {

    name: "CompatTree",

    components: { Tree },

    props: {

        data: {
            type: Array,
            default: () => []
        },

        render: {
            type: Function,
            default: null
        }

    },


    data() {

        return {

            innerData: []

        }

    },

    watch: {

        // ⚠️ 不使用 deep watch，否则树结构会卡死
        data: {

            immediate: true,

            handler(val) {

                if (Array.isArray(val)) {
                    console.log("watch data triggered")
                    // 复制引用，避免父子互相影响
                    this.innerData = [...val]

                } else {

                    this.innerData = []

                }

            }

        }

    },

    computed: {

        /**
         * Vue2 Tree flatState 兼容
         */
        flatState() {

            const list = []
            console.log("flatState computing")
            const walk = (nodes) => {

                if (!Array.isArray(nodes)) return

                for (const n of nodes) {

                    list.push({ node: n })

                    if (Array.isArray(n.children)) {

                        walk(n.children)

                    }

                }

            }

            walk(this.innerData)

            return list

        }

    },

    methods: {

        /**
         * Vue2 render(h) 兼容
         */
        renderWrapper(slotProps) {

            const nodeRender =
                slotProps.data.render || this.render

            if (!nodeRender) {

                return slotProps.data.title

            }

            return nodeRender(h, {
                root: slotProps.root,
                node: slotProps.node,
                data: slotProps.data
            })

        },

        /**
         * 获取选中节点
         */
        getSelectedNodes() {

            return this.$refs.tree?.getSelectedNodes?.() || []

        },

        /**
         * 获取checkbox节点
         */
        getCheckedNodes() {

            return this.$refs.tree?.getCheckedNodes?.() || []

        },

        /**
         * 全部展开
         */
        expandAll() {

            this.$refs.tree?.expandAll?.()

        },

        /**
         * 全部收起
         */
        collapseAll() {

            this.$refs.tree?.collapseAll?.()

        },

        /**
         * 设置树数据
         */
        setData(data) {

            this.innerData =
                Array.isArray(data)
                    ? [...data]
                    : []


        },

        /**
         * 刷新树
         */
        refurbish() {

            const tmp = [...this.innerData]

            this.innerData = []

            this.$nextTick(() => {

                this.innerData = tmp

            })

        },

        /**
         * 获取root节点
         */
        getRootNodes() {

            return this.innerData

        },

        /**
         * 更新节点
         */
        updateNode(data, flag) {

            const idField = "id"
            console.log("updateNode called", data, flag)
            const findNode = (list, id) => {

                for (const node of list) {

                    if (node[idField] === id) {

                        return node

                    }

                    if (Array.isArray(node.children)) {

                        const res =
                            findNode(node.children, id)

                        if (res) return res

                    }

                }

                return null

            }

            if (flag === "U") {

                const node =
                    findNode(this.innerData, data[idField])

                if (node) {

                    Object.assign(node, data)

                }

            }

            if (flag === "D") {

                const removeNode = (list, id) => {

                    const index =
                        list.findIndex(
                            n => n[idField] === id
                        )

                    if (index > -1) {

                        list.splice(index, 1)

                        return true

                    }

                    for (const n of list) {

                        if (
                            Array.isArray(n.children) &&
                            removeNode(n.children, id)
                        ) {

                            return true

                        }

                    }

                    return false

                }

                removeNode(this.innerData, data[idField])

            }


        }

    }

}
</script>
