package com.fkzy.warn.common.util.treeUtil;

import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author zhangjing
 * @date 2024/04/25 17:14
 * @description
 */
public class  ForestNodeManager<T extends INode<T>> {
    /**
     * 使用 ImmutableMap 存储节点，其中键是节点的ID，值是节点本身。
     * 这个映射是不可变的，通过调用 Maps.uniqueIndex(nodes, INode::getId) 来创建，其中 INode::getId 是获取节点ID的方法。
     *
     * parentIdMap: 使用 HashMap 存储尚未创建的父节点的ID。键是父节点的ID，值是一个占位对象（在这里是空字符串）。
     */
    private final ImmutableMap<Integer, T> nodeMap;
    private final Map<Integer, Object> parentIdMap = Maps.newHashMap();

    /**
     * 接受一个 List<T> 类型的参数 nodes，并使用 Maps.uniqueIndex 方法将其转换为 ImmutableMap 存储在 nodeMap 中
     */
    public ForestNodeManager(List<T> nodes) {
        this.nodeMap = Maps.uniqueIndex(nodes, INode::getId);
    }

    /**
     * 接受一个 Long 类型的节点ID作为参数，然后尝试从 nodeMap 中获取对应ID的节点。
     * 如果存在该节点，则返回节点；否则返回 null。
     */
    public INode<T> getTreeNodeAt(Integer id) {
        return this.nodeMap.containsKey(id) ? (INode)this.nodeMap.get(id) : null;
    }

    /**
     * 接受一个 Long 类型的父节点ID作为参数，将其添加到 parentIdMap 中。
     * 这个方法用于标记尚未创建的父节点。
     */
    public void addParentId(Integer parentId) {
        this.parentIdMap.put(parentId, "");
    }

    /**
     * 创建一个空的 ArrayList 用于存储树的根节点。
     * 使用 forEach 遍历 nodeMap 中的每个节点。
     * 对于每个节点，如果其父节点ID为0（表示是根节点）或者父节点ID在 parentIdMap 中存在（即尚未创建的父节点），则将该节点添加到根节点列表中。
     * 最后返回根节点列表。
     */
    public List<T> getRoot() {
        List<T> roots = new ArrayList();
        this.nodeMap.forEach((key, node) -> {
            if (node.getParentId() == 0L || this.parentIdMap.containsKey(node.getId())) {
                roots.add(node);
            }

        });
        return roots;
    }
}

