<template>
    <Tree ref="tree" :data="treeRenderData" :render="renderContent" expand-node></Tree>
</template>

<script>
import { resolveComponent } from 'vue'

export default {
    props: {
        treeData: {
            type: Object,
            required: false,
            default: {
                path: "/Users/Frankie/rootFolder",
                name: "rootFolder",
                directory: true,
                nodes: [{
                    path: "/Users/Frankie/rootFolder/file.txt",
                    name: "file.txt",
                    suffix: "txt",
                    directory: false,
                }],
            },
        },
        selectedNode: {
            type: Array,
            required: false,
            default: [],
        },
        expandLevel: {
            type: Number,
            required: false,
            default: -1,
        },
        showHiddenFile: {
            type: Boolean,
            required: false,
            default: false,
        },
        specifyFileSuffix: {
            type: Array,
            required: false,
            default: [],
        },
    },
    data() {
        return {
            treeRenderData: [],
        }
    },
    mounted() {
        this.renderTreeByTreeData(this.treeData)
    },
    watch: {
        treeData(newTreeData) {
            this.renderTreeByTreeData(newTreeData)
        },
    },
    methods: {
        renderTreeByTreeData(currentTreeData) {
            const renderNode = this.renderNodeByNodeData(currentTreeData, 1)
            this.treeRenderData = renderNode == null ? [] : [renderNode]
        },
        renderNodeByNodeData(nodeData, level) {
            // 判断必须包含的字段，没有则返回 null
            if (nodeData == null || nodeData == undefined) {
                return null
            }
            if (nodeData.path == undefined ||
                nodeData.name == undefined ||
                nodeData.directory == undefined ||
                (nodeData.directory == true && nodeData.nodes == undefined)
            ) {
                return null
            }
            // 如果需要隐藏 . 开头的目录和文件
            if (!this.showHiddenFile && nodeData.name.startsWith(".")) {
                return null
            }
            // 如果要过滤文件后缀
            if (this.specifyFileSuffix.length > 0) {
                if (!nodeData.directory && nodeData.suffix != undefined &&
                    !this.specifyFileSuffix.includes(nodeData.suffix)) {
                    return null
                }
            }

            let allowExpand = this.expandLevel < 0 || level <= this.expandLevel
            let nodeRenderData = {
                title: nodeData.name,
                directory: nodeData.directory,
                expand: (allowExpand && nodeData.directory) ? true : false,
                // 附带数据，不直接参与渲染
                path: nodeData.path,
                selected: this.selectedNode.includes(nodeData.path),
            }
            if (nodeData.directory) {
                let childrenRenderData = []
                nodeData.nodes.forEach(node => {
                    const renderNode = this.renderNodeByNodeData(node, level + 1)
                    if (renderNode != null) {
                        if (renderNode.selected || renderNode.expand) {
                            nodeRenderData.expand = true
                        }
                        childrenRenderData.push(renderNode)
                    }
                });
                nodeRenderData.children = childrenRenderData
            }
            return nodeRenderData
        },
        renderContent(h, { root, node, data }) {
            return h('span', {
                style: {
                    display: 'inline-block',
                    width: '100%'
                },
                onClick: () => { this.selectNode(data) }
            }, [
                h('span', [
                    h(resolveComponent('Icon'), {
                        type: data.directory ? 'ios-folder-outline' : 'ios-paper-outline',
                        style: {
                            marginRight: '8px'
                        }
                    }),
                    h('span', data.title)
                ])
            ]);
        },
        selectNode(nodeData) {
            // 文件夹不做任何动作
            if (nodeData.directory) {
                return
            }

            // 清除其他选中状态，为当前节点增加选中状态
            let selectedNodes = this.$refs.tree.getSelectedNodes()
            selectedNodes.forEach(element => {
                element.selected = false
            });
            nodeData.selected = true

            // 向父组件暴露当前选中的文件
            this.$emit('file-selected', nodeData);
        }
    }
}
</script>
<style>
.hidden {
    display: none;
}
</style>
