package com.sqx.modules.utils;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;

public class TreeUtils {

    /**
     * 将 List 集合转为树状结构
     * @param nodes 待转换的 List 集合，其中对象必须包含指定的父级字段和节点ID字段
     * @param parentIdField 父级字段名称
     * @param idField 节点ID字段名称
     * @param <T> 对象类型
     * @return 转换后的树状结构
     */
    public static <T> List<T> listToTree(List<T> nodes, String parentIdField, String idField) throws NoSuchFieldException, IllegalAccessException {
        List<T> treeNodes = new ArrayList<>();
        for (T node : nodes) {
            Object parentIdValue = getFieldValue(node, parentIdField);
            int parentId = Integer.parseInt(parentIdValue.toString());
            if (parentId == 0) {
                //父ID为0为根节点， 直接加入列表中
                treeNodes.add(node);
                continue;
            }
            // 将节点加入对应的父节点中
            for (T parent : nodes) {
                Object idValue = getFieldValue(parent, idField);
                int id = Integer.parseInt(idValue.toString());
                if (id == parentId) {
                    Object children = getFieldValue(parent, "children");
                    if (children == null){
                        setFieldValue(parent,"children",new ArrayList());
                    }
                    ((List<T>)getFieldValue(parent, "children")).add(node);
                }
            }
        }
        return treeNodes;
    }

    /**
     * 反射获取对象的属性值
     * @param obj 目标对象
     * @param fieldName 属性名
     * @return 属性值
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    private static Object getFieldValue(Object obj, String fieldName) throws NoSuchFieldException, IllegalAccessException {
        Class<?> clazz = obj.getClass();
        Field field = clazz.getDeclaredField(fieldName);
        field.setAccessible(true);
        return field.get(obj);
    }

    /**
     * 反射设置对象的属性值
     * @param obj 目标对象
     * @param fieldName 属性名
     * @param value 属性值
     * @throws NoSuchFieldException
     * @throws IllegalAccessException
     */
    private static void setFieldValue(Object obj, String fieldName, Object value) {
        try {
            Class<?> clazz = obj.getClass();
            java.lang.reflect.Field field = clazz.getDeclaredField(fieldName);
            field.setAccessible(true);
            field.set(obj, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

