<template>
    <div class="ps-tree component">
        <template v-for="(item, index) in list" :key="item.key">
            <node @onDragstart="onDragstart" @onDragEnd="onDragEnd" @onDrop="onDrop" :data-source-key="dataSourceKey"
                :data="item" :list="list" :level="level" @click="(item) => clickNode(item)">
                <template
                    #default="{ data, deep, dataSourceKey, status }: { data: INiuTreeData, deep: number, dataSourceKey: INiuTreeKey, status: ENiuTreeStatus }">
                    <slot :data="data" :deep="deep" :dataSourceKey="dataSourceKey" :status="status"></slot>
                </template>
            </node>
        </template>
    </div>
</template>
<script lang="ts" setup>
import { INiuTreeData, INiuTreeKey, ENiuTreeStatus } from './type'
import {
    findByKey,
    forEachTree,
    insertAfterByKey,
    insertBeforeByKey,
    isChildOf,
    removeByKey,
} from './util'

const props = withDefaults(
    defineProps<{
        list: INiuTreeData[]
        justOpen?: boolean
        autoExpand?: boolean
        justOpenOne?: boolean
        level?: number
    }>(),
    {
        justOpenOne: false,
        justOpen: false,
        autoExpand: false,
        level: 0,
    }
)

provide("tree:opts", props)

function clickNode(item: INiuTreeData) {
    if (props.justOpenOne) {
        forEachTree(props.list, (node: INiuTreeData) => {
            node.isExpand = false
        })
    }
    if (item.isFolder) {
        item.isExpand = !item.isExpand
        emit("change")
    }

}

const emit = defineEmits<{
    (e: 'change'): void
}>()

const dataSourceKey = ref()
function onDragstart(key: INiuTreeKey) {
    dataSourceKey.value = key
}
function onDragEnd(key: INiuTreeKey) {
    dataSourceKey.value = undefined
}
function onDrop(key: INiuTreeKey, status?: ENiuTreeStatus) {
    if (!dataSourceKey.value) return
    if (!key) return
    let data = findByKey(dataSourceKey.value, props.list)
    let targetData = findByKey(key, props.list)
    switch (status) {
        case ENiuTreeStatus.DragIn:
            if (
                data &&
                targetData &&
                dataSourceKey.value != key &&
                !isChildOf(key, dataSourceKey.value, props.list) &&
                targetData.children
            ) {
                removeByKey(dataSourceKey.value, props.list)
                targetData.children.push(data)
                if (props.autoExpand) {
                    targetData.isExpand = true
                }
                emit("change")
            }
            break
        case ENiuTreeStatus.DragDown:
            // 按索引往列表添加节点
            if (
                data &&
                targetData &&
                dataSourceKey.value != key &&
                !isChildOf(key, dataSourceKey.value, props.list)
            ) {
                removeByKey(dataSourceKey.value, props.list)
                insertAfterByKey(key, data, props.list)
                emit("change")
            }
            break
        case ENiuTreeStatus.DragUp:
            // 按索引往列表添加节点
            if (
                data &&
                targetData &&
                dataSourceKey.value != key &&
                !isChildOf(key, dataSourceKey.value, props.list)
            ) {
                removeByKey(dataSourceKey.value, props.list)
                insertBeforeByKey(key, data, props.list)
                emit("change")
            }
            break
    }
    dataSourceKey.value = undefined
}
</script>
<script lang="ts">
import { defineComponent, provide, ref } from "vue"
import node from './node.vue'

export default defineComponent({
    name: 'ps-tree',
})
</script>

