package com.ningdatech.carapi.sys.utils;

import cn.hutool.core.collection.CollUtil;
import com.google.common.collect.Maps;
import com.ningdatech.basic.util.StrPool;
import com.ningdatech.carapi.sys.entity.RoleMenu;
import com.ningdatech.carapi.sys.entity.TreeEntity;
import com.ningdatech.carapi.sys.entity.vo.MenuRoleVO;
import org.apache.commons.lang3.StringUtils;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * list列表 转换成tree列表
 *
 * @author PoffyZhang
 */
public final class TreeUtil {
    private TreeUtil() {
    }

    /**
     * 判断id是否为根节点
     *
     * @param id
     * @return
     */
    public static boolean isRoot(Long id) {
        return id == null || StrPool.DEF_PARENT_ID.equals(id);
    }


    public static String getTreePath(String parentTreePath, Long parentId) {
        return StrPool.COMMA + parentId + parentTreePath;
    }

    /**
     * 构建Tree结构
     *
     * @param treeList 待转换的集合
     * @return 树结构
     */
    public static <E extends TreeEntity<E, ? extends Serializable>> List<E> buildTree(List<E> treeList) {
        if (CollUtil.isEmpty(treeList)) {
            return treeList;
        }
        //记录自己是自己的父节点的id集合
        List<Serializable> selfIdEqSelfParent = new ArrayList<>();

        // 遍历两次
        foreachNodes(treeList, selfIdEqSelfParent);
        foreachNodesWithTopMenu(treeList);

        // 找出根节点集合
        List<E> trees = new ArrayList<>();

        List<? extends Serializable> allIds = treeList.stream().map(node -> node.getId()).collect(Collectors.toList());
        for (E baseNode : treeList) {
            if (!allIds.contains(baseNode.getPid()) || selfIdEqSelfParent.contains(baseNode.getPid())) {
                baseNode.setPid(null);
                baseNode.setTopMenu(baseNode.getName());
                trees.add(baseNode);
            }
        }
        return trees;
    }

    /**
     * 构建Tree结构
     *
     * @param treeList 待转换的集合
     * @param title    菜单名
     * @return 树结构
     */
    public static <E extends TreeEntity<E, ? extends Serializable>> List<E> buildTree(List<E> treeList, String title) {
        if (CollUtil.isEmpty(treeList)) {
            return treeList;
        }
        //记录自己是自己的父节点的id集合
        List<Serializable> selfIdEqSelfParent = new ArrayList<>();

        // 遍历两次
        foreachNodes(treeList, selfIdEqSelfParent);
        foreachNodesWithTopMenu(treeList);

        // 找出根节点集合
        List<E> trees = new ArrayList<>();

        List<? extends Serializable> allIds = treeList.stream().map(node -> node.getId()).collect(Collectors.toList());
        for (E baseNode : treeList) {
            if (!allIds.contains(baseNode.getPid()) || selfIdEqSelfParent.contains(baseNode.getPid())) {
                baseNode.setPid(null);
                baseNode.setTopMenu(baseNode.getName());
                trees.add(baseNode);
            }
        }
//        checkTitle(trees,title);
        return trees;
    }

    private static <E extends TreeEntity<E, ? extends Serializable>>
    void foreachNodes(List<E> treeList, List<Serializable> selfIdEqSelfParent) {
        for (E parent : treeList) {
            Serializable id = parent.getId();
            for (E children : treeList) {
                if (parent != children) {
                    //parent != children 这个来判断自己的孩子不允许是自己，因为有时候，根节点的parent会被设置成为自己
                    if (id.equals(children.getPid())) {
                        parent.initChildren();
                        if (0L == parent.getPid()) {
                            children.setTopMenu(parent.getName());
                            children.setLevel(2);
                        } else {
                            children.setTopMenu(parent.getTopMenu());
                            children.setLevel(parent.getLevel() + 1);
                        }
                        parent.getChildren().add(children);
                    }
                } else if (id.equals(parent.getPid())) {
                    selfIdEqSelfParent.add(id);
                }
            }
        }
    }

    private static <E extends TreeEntity<E, ? extends Serializable>> void foreachNodesWithTopMenu(List<E> treeList) {
        for (E parent : treeList) {
            Serializable id = parent.getId();
            for (E children : treeList) {
                if (parent != children) {
                    if (id.equals(children.getPid())) {
                        if (0L == parent.getPid()) {
                            children.setTopMenu(parent.getName());
                            children.setLevel(2);
                        } else {
                            children.setTopMenu(parent.getTopMenu());
                            children.setLevel(parent.getLevel() + 1);
                        }
                    }
                }
            }
        }
    }

    /**
     * 生成当前用户的菜单列表
     *
     * @param treeList
     * @param roleMenuMap
     * @return
     */
    public static List<MenuRoleVO> buildUserTree(List<MenuRoleVO> treeList, Map<Long, RoleMenu> roleMenuMap) {
        if (CollUtil.isEmpty(treeList)) {
            return Collections.emptyList();
        }
        //记录自己是自己的父节点的id集合
        List<Serializable> selfIdEqSelfParent = new ArrayList<>();

        // 遍历两次
        foreachNodesCheckRole(treeList, selfIdEqSelfParent, roleMenuMap);
        foreachNodesWithTopMenu(treeList);

        // 找出根节点集合
        List<MenuRoleVO> trees = new ArrayList<>();

        List<? extends Serializable> allIds = treeList.stream().map(TreeEntity::getId).collect(Collectors.toList());
        for (MenuRoleVO baseNode : treeList) {
            if (!allIds.contains(baseNode.getPid()) || selfIdEqSelfParent.contains(baseNode.getPid())) {
                baseNode.setPid(null);
                if (roleMenuMap.containsKey(baseNode.getId())) {
                    baseNode.setTopMenu(baseNode.getName());
                    checkRedirect(baseNode);
                    trees.add(baseNode);
                } else {
                    if (baseNode.getSize() > 0) {
                        baseNode.setTopMenu(baseNode.getName());
                        checkRedirect(baseNode);
                        trees.add(baseNode);
                    }
                }
            }
        }
        return trees;
    }

    //判断角色权限用 不用父级
    private static void foreachNodesCheckRoleWithoutParent(List<MenuRoleVO> treeList, List<Serializable> selfIdEqSelfParent, Map<Long, RoleMenu> roleMenuMap) {
        for (MenuRoleVO parent : treeList) {
            Serializable id = parent.getId();
            for (MenuRoleVO children : treeList) {
                if (parent != children) {
                    //parent != children 这个来判断自己的孩子不允许是自己，因为有时候，根节点的parent会被设置成为自己
                    if (id.equals(children.getPid())) {
                        parent.initChildren();

                        if (!roleMenuMap.containsKey(children.getId())) {
                            continue;
                        }

                        if (0L == parent.getPid()) {
                            children.setTopMenu(parent.getName());
                            children.setLevel(2);
                        } else {
                            children.setTopMenu(parent.getTopMenu());
                            children.setLevel(parent.getLevel() + 1);
                        }
                        parent.getChildren().add(children);
                    }
                } else if (id.equals(parent.getPid())) {
                    selfIdEqSelfParent.add(id);
                }

                if (roleMenuMap.containsKey(children.getId())) {
                    children.setHasPermission(1);
                }
            }
        }
    }

    //判断当前登录权限用
    private static void foreachNodesCheckRole(List<MenuRoleVO> treeList, List<Serializable> selfIdEqSelfParent, Map<Long, RoleMenu> roleMenuMap) {
        for (MenuRoleVO parent : treeList) {
            Serializable id = parent.getId();
            for (MenuRoleVO children : treeList) {
                if (parent != children) {
                    //parent != children 这个来判断自己的孩子不允许是自己，因为有时候，根节点的parent会被设置成为自己
                    if (id.equals(children.getPid())) {
                        parent.initChildren();

                        if (!roleMenuMap.containsKey(children.getId())) {
                            continue;
                        }

                        if (0L == parent.getPid()) {
                            children.setTopMenu(parent.getName());
                            children.setLevel(2);
                        } else {
                            children.setTopMenu(parent.getTopMenu());
                            children.setLevel(parent.getLevel() + 1);
                        }
                        parent.getChildren().add(children);
                    }
                } else if (id.equals(parent.getPid())) {
                    selfIdEqSelfParent.add(id);
                }
            }

            //1层 2层 再加一下
            for (MenuRoleVO children : treeList) {
                if (parent != children) {
                    if (id.equals(children.getPid())) {

                        if (parent.getChildren().contains(children) ||
                                children.getSize() == 0) {
                            continue;
                        }

                        if (0L == parent.getPid()) {
                            children.setTopMenu(parent.getName());
                            children.setLevel(2);
                        } else {
                            children.setTopMenu(parent.getTopMenu());
                            children.setLevel(parent.getLevel() + 1);
                        }
                        parent.getChildren().add(children);
                    }
                }
            }
        }
    }

    /**
     * 动态判断redirect
     *
     * @param baseNode
     */
    private static void checkRedirect(MenuRoleVO baseNode) {
        checkMenuRedirect(baseNode, baseNode.getChildren());
    }

    /**
     * 判断菜单是否需要跳转
     *
     * @param baseNode /
     * @param menus    /
     * @return /
     */
    private static Boolean checkMenuRedirect(MenuRoleVO baseNode, Set<MenuRoleVO> menus) {
        if (baseNode.getSize() > 0) {
            for (MenuRoleVO menu : menus) {
                //如果是大屏类型的 2层-3层 直接跳转
                if (menu.getPath().endsWith("Datav")) {
                    baseNode.setRedirect(menu.getComponent());
                    return Boolean.TRUE;
                }

                //如果是不隐藏 和 没有子菜单 跳转
                if (menu.getSize() == 0 && 0 == menu.getHidden()) {
                    baseNode.setRedirect(menu.getComponent());
                    return Boolean.TRUE;
                }
            }

            //一轮没有合适的菜单 去三级菜单找
            for (MenuRoleVO menu : menus) {
                if (menu.getSize() > 0) {
                    if (checkMenuRedirect(baseNode, menu.getChildren())) {
                        return Boolean.TRUE;
                    }
                }
            }
        }

        return Boolean.FALSE;
    }
}
