package com.infoepoch.pms.dispatchassistant.common.utils;


import com.infoepoch.pms.dispatchassistant.domain.basic.organization.Organization;
import com.infoepoch.pms.dispatchassistant.domain.basic.user.User;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;

public class TreeTool {

    /**
     * 将用户生成ztree需要的json格式
     */
    public static List<Map<String, Object>> getCMCCZTreeJson(List<User> users, boolean multiple) {
        List<Map<String, Object>> list = new ArrayList<>();
        if (!CollectionUtils.isEmpty(users)) {
            //构建list
            List<Map<String, Object>> children = users.stream().map(user -> {
                Map<String, Object> mapUser = new HashMap<>();
                mapUser.put("id", user.getId());
                mapUser.put("name", user.getFullname());
                mapUser.put("departmentName", user.getOrganizationName());
                mapUser.put("open", false);
                mapUser.put("nocheck", false);
                mapUser.put("level", 2);
                return mapUser;
            }).collect(Collectors.toList());

            Map<String, Object> m = new HashMap<>();
            m.put("id", users.get(0).getOrganizationId());
            m.put("name", users.get(0).getOrganizationName());
            m.put("level", 1);
            m.put("open", false);
            if (!multiple)
                m.put("nocheck", true);
            else
                m.put("nocheck", false);
            m.put("children", children);
            list.add(m);
        }
        return list;
    }

    /**
     * 用户数据转换为工作流组件所需的格式
     *
     * @param userMapList
     * @param multiple
     * @return
     */
    public static List<Map<String, Object>> getCMCCZTreeJson(Map<String, List<User>> userMapList, boolean multiple) {
        List<Map<String, Object>> list = new ArrayList<>();
        for (String key : userMapList.keySet()) {
            List<User> userList = userMapList.get(key);
            if (!CollectionUtils.isEmpty(userList)) {
                //构建list
                List<Map<String, Object>> children = userList.stream().map(user -> {
                    Map<String, Object> mapUser = new HashMap<>();
                    mapUser.put("id", user.getId());
                    mapUser.put("name", user.getFullname());
                    mapUser.put("departmentName", user.getOrganizationName());
                    mapUser.put("open", false);
                    mapUser.put("nocheck", false);
                    mapUser.put("level", 2);
                    return mapUser;
                }).collect(Collectors.toList());

                Map<String, Object> m = new HashMap<>();
                m.put("id", userList.get(0).getOrganizationId());
                m.put("name", userList.get(0).getOrganizationName());
                m.put("level", 1);
                m.put("open", false);
                if (!multiple)
                    m.put("nocheck", true);
                else {
                    m.put("nocheck", false);
                }
                m.put("children", children);
                list.add(m);
            }
        }

        return list;
    }

    /**
     * 用户树路径遍历
     *
     * @param resultMap
     * @param node
     * @param pathStack
     */
    public static void nodeLoopCallback(Map<String, List<String>> resultMap, Map<String, Object> node, Stack<String> pathStack) {
        pathStack.push(StringTool.getString(node.get("value")));// 入栈
        List<Map<String, Object>> children = node.get("children") == null ? new ArrayList<>() : (List<Map<String, Object>>) node.get("children");
        if (children == null || children.size() == 0) {
            List<String> list = new ArrayList<>(pathStack);
            resultMap.put(StringTool.getString(node.get("value")), list);
        } else {
            for (Map<String, Object> cNode : children) {
                nodeLoopCallback(resultMap, cNode, pathStack);// 深度优先，进入递归
                pathStack.pop();// 回溯时出栈
            }
        }
    }

    /**
     * 部门树路径遍历
     *
     * @param resultMap
     * @param node
     * @param pathStack
     */
    public static void nodeLoopCallback(Map<String, List<String>> resultMap, Organization node, Stack<String> pathStack) {
        pathStack.push(node.getId());// 入栈
        List<Organization> children = node.getChildren();
        if (children == null || children.size() == 0) {
            List<String> list = new ArrayList<>(pathStack);
            resultMap.put(node.getId(), list);
        } else {
            for (Organization cNode : children) {
                nodeLoopCallback(resultMap, cNode, pathStack);// 深度优先，进入递归
                pathStack.pop();// 回溯时出栈
            }
        }
    }

    /**
     * 递归循环
     *
     * @param list         列表
     * @param childrenFunc 获取子列表的方法
     * @param callback     回调方法
     * @param <T>          输入泛型
     * @param <R>          输出泛型
     */
    public static <T, R> List<R> loopCallback(List<T> list, Function<T, List<T>> childrenFunc, Function<T, R> callback) {
        List<R> resultList = new ArrayList<>();
        for (T t : list) {
            List<T> children = childrenFunc.apply(t);
            if (children != null && children.size() > 0) {
                loopCallback(children, childrenFunc, callback);
            }
            resultList.add(callback.apply(t));
        }
        return resultList;
    }

    /**
     * 递归循环
     *
     * @param list         列表
     * @param childrenFunc 获取子列表的方法
     * @param callback     回调方法
     * @param <T>          输入泛型
     */
    public static <T> void loopCallback(List<T> list, Function<T, List<T>> childrenFunc, Consumer<T> callback) {
        for (T t : list) {
            List<T> children = childrenFunc.apply(t);
            if (children != null && children.size() > 0) {
                loopCallback(children, childrenFunc, callback);
            }
            callback.accept(t);
        }
    }

    /**
     * @param list
     * @param childrenFunc
     * @param callback
     * @return
     */
    public static List<Map<String, Object>> loopCallbackMap(List<Map<String, Object>> list, Function<Map<String, Object>, List<Map<String, Object>>> childrenFunc, Function<Map<String, Object>, Map<String, Object>> callback) {
        List<Map<String, Object>> resultList = new ArrayList<>();
        for (Map<String, Object> t : list) {
            List<Map<String, Object>> children = childrenFunc.apply(t);
            if (children != null && children.size() > 0) {
                loopCallbackMap(children, childrenFunc, callback);
            }
            resultList.add(callback.apply(t));
        }
        return resultList;
    }

    /**
     * @param list
     * @param childrenFunc
     * @param callback
     */
    public static void loopCallbackMap(List<Map<String, Object>> list, Function<Map<String, Object>, List<Map<String, Object>>> childrenFunc, Consumer<Map<String, Object>> callback) {
        for (Map<String, Object> t : list) {
            List<Map<String, Object>> children = childrenFunc.apply(t);
            if (children != null && children.size() > 0) {
                loopCallbackMap(children, childrenFunc, callback);
            }
            callback.accept(t);
        }
    }

}
