package com.sybotan.android.demo.tree

object TreeHelper {

    @Throws(IllegalArgumentException::class, IllegalAccessException::class)
    fun <T : Any> getTreeNodes(list: List<T>): List<Node<T>> {

        val nodes = nodes(list)
        val rootNodes = rootNodes(nodes)

        val result = mutableListOf<Node<T>>()
        for (node in rootNodes) {
            addNode(result, node)
        }

        return result
    }


    /**
     * 过滤出可见节点
     *
     * @options nodes
     * @return
     */
    fun <T : Any> filterVisibleNodes(nodes: List<Node<T>>): List<Node<T>> {
        val result = mutableListOf<Node<T>>()

        for (node in nodes) {
            if (node.isRoot || node.isParentExpand) {
                result.add(node)
            }
        }
        return result
    }


    /**
     * 将用户的数据转化为树形数据
     *
     * @options datas
     * @return
     * @throws IllegalAccessException
     * @throws IllegalArgumentException
     */
    @Throws(IllegalArgumentException::class, IllegalAccessException::class)
    private fun <T : Any> nodes(list: List<T>): List<Node<T>> {
        val nodes = ArrayList<Node<T>>()
        var node: Node<T>

        for (t in list) {
            var id = ""
            var pid = ""
            var label = ""
            val clazz = t::class.java
            val fields = clazz.declaredFields
            for (field in fields) {
                if (field.getAnnotation(TreeNodeId::class.java) != null) {
                    field.isAccessible = true
                    id = field.get(t) as String
                }
                if (field.getAnnotation(TreeNodePid::class.java) != null) {
                    field.isAccessible = true
                    pid = field.get(t) as String
                }
                if (field.getAnnotation(TreeNodeLabel::class.java) != null) {
                    field.isAccessible = true
                    label = field.get(t) as String
                }

                if (id != "" && label != "") {  // 需要的属性都已经设置完毕
                    break
                }
            }
            node = Node(id, pid, label, t)
            nodes.add(node)
        }


        // 关联节点
        for (i in nodes.indices) {
            val n = nodes[i]

            for (j in i + 1 until nodes.size) {
                val m = nodes[j]

                if (m.pid == n.id) {
                    n.children.add(m)
                    m.parent = n
                } else if (m.id == n.pid) {
                    m.children.add(n)
                    n.parent = m
                }
            }
        }

        return nodes
    }

    /**
     * 把一个节点的所有孩子节点都放入result
     *
     * @options result
     * @options node
     */
    private fun <T : Any> addNode(
        result: MutableList<Node<T>>,
        node: Node<T>
    ) {
        result.add(node)
        if (node.isLeaf)
            return

        for (i in 0 until node.children.size) {
            addNode(result, node.children[i])
        }

    }

    /**
     * 获取根节点
     *
     * @options nodes
     * @return
     */
    private fun <T> rootNodes(nodes: List<Node<T>>): List<Node<T>> {
        val root = mutableListOf<Node<T>>()
        for (node in nodes) {
            if (node.isRoot) {
                root.add(node)
            }
        }
        return root
    }

}