package com.ruoyi.common.core.utils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class TreeUtils {

    public static <T> List<T> buildTree(List<T> list) {
        return buildTree(list, "getId", "getParentId");
    }
    public static <T> List<T> buildTree(List<T> list, String idField, String pidField)
    {
        List<T> returnList = new ArrayList<>();
        List<Long> tempList = list.stream().map(entity ->
        {
            try {
                Method m = entity.getClass().getMethod(idField);
                return (Long)m.invoke(entity);
            } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }).collect(Collectors.toList());
        for (T entity : list) {
            long parentId;
            try {
                Method m = entity.getClass().getMethod(pidField);
                parentId = (Long) m.invoke(entity);
            } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
            // 如果是顶级节点, 遍历该父节点的所有子节点
            if (!tempList.contains(parentId)) {
                recursionFn(list, entity, idField, pidField);
                returnList.add(entity);
            }
        }
        if (returnList.isEmpty())
        {
            returnList = list;
        }
        return returnList;
    }

    private static <T> void recursionFn(List<T> list, T t, String idField, String pidField)
    {
        // 得到子节点列表
        List<T> childList = getChildList(list, t, idField, pidField);
        try {
            Method m = t.getClass().getMethod("setChildren", List.class);
            m.invoke(t, childList);
        } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
            throw new RuntimeException(e);
        }

        for (T tChild : childList)
        {
            if (hasChild(list, tChild, idField, pidField))
            {
                recursionFn(list, tChild, idField, pidField);
            }
        }
    }

    private static <T> List<T> getChildList(List<T> list, T t, String idField, String pidField)
    {
        List<T> tlist = new ArrayList<>();
        for (T n : list) {
            try {
                Method methodN = n.getClass().getMethod(pidField);
                long parentIdN = (Long) methodN.invoke(n);
                Method methodT = t.getClass().getMethod(idField);
                long idT = (Long) methodT.invoke(t);
                if (parentIdN == idT) {
                    tlist.add(n);
                }
            } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
        return tlist;
    }

    /**
     * 判断是否有子节点
     */
    private static <T> boolean hasChild(List<T> list, T t, String idField, String pidField)
    {
        return getChildList(list, t, idField, pidField).size() > 0;
    }
}
