package cn.estsh.i3plus.ext.mes.pcn.apiservice.util;

import cn.estsh.i3plus.ext.mes.pcn.pojo.util.MesPcnExtEnumUtil;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.*;

/**
 * @Description:
 * @Author: jokelin
 * @Date: 2020/12/22 9:47 AM
 * @Modify:
 */
@Slf4j
public class EnumExtUtil {


    public static void main(String[] args) throws ClassNotFoundException{
        Class clazz = MesPcnExtEnumUtil.class;
        Map<String, Object> map = getEnumByName(clazz, "HQL_EXPRESSION");
        System.out.println(clazz.getName());
        System.out.println(map.toString());
    }

    /**
     * 单层级枚举
     *
     * @param clz         包路径
     * @param enumName   类名
     * @return 枚举集合
     * @throws ClassNotFoundException 当类没找到throw
     */
    public static Map<String, Object> getEnumByName(Class clz, String enumName) {
        Class innerClazz[] = clz.getDeclaredClasses();// 获取常量类中的所有内部类
        Class<Enum> clazz = null;
        for (Class aClass : innerClazz) {
            if (aClass.getSimpleName().equals(enumName)) {
                clazz = aClass;
                break;
            }
        }
        return clazz == null ? null : reflectGetEnumConstants(clazz);
    }

    /**
     * 根据路径找枚举
     *
     * @param clazz 类路径
     * @return 枚举项集合
     */
    private static Map<String, Object> reflectGetEnumConstants(Class clazz) {
        Map<String, Object> enumMap;
        enumMap = new HashMap<>(8);

        Optional<Method> getCodeMethodOp = getMethod(clazz, "getCode");
        Optional<Method> getValueMethodOp = getMethod(clazz, "getValue");
        Optional<Method> getDescriptionMethodOp = getMethod(clazz, "getDescription");

        List<Map<String, Object>> data = new ArrayList<>();
        // 获取所有枚举项
        Enum[] enumConstants = (Enum[]) clazz.getEnumConstants();
        for (Enum enumConstant : enumConstants) {
            Map<String, Object> eachData = new HashMap<>(8);

            getValueMethodOp.ifPresent(d -> eachData.put("value", invokeGetMethod(enumConstant, d)));
            getCodeMethodOp.ifPresent(d -> eachData.put("code", invokeGetMethod(enumConstant, d)));
            getDescriptionMethodOp.ifPresent(d -> eachData.put("description", invokeGetMethod(enumConstant, d)));

            data.add(eachData);
        }
        enumMap.put("enumName", clazz.getSimpleName());
        enumMap.put("valuesList", data);

        return enumMap;
    }

    /**
     * 对一个枚举项调用一个方法
     *
     * @param enumConstant 枚举项
     * @param method       调用方法
     * @return get方法返回
     */
    private static Object invokeGetMethod(Enum enumConstant, Method method) {
        try {
            method.setAccessible(true);
            return method.invoke(enumConstant);
        } catch (IllegalAccessException e) {
            log.debug("MES获取枚举接口 非法访问:{}", e.getMessage());
        } catch (InvocationTargetException e) {
            log.debug("MES获取枚举接口 执行方法失败:{}", e.getMessage());
        }
        return null;
    }

    /**
     * 根据方法名反射获取类中的方法
     *
     * @param clazz      类
     * @param methodName 方法名
     * @return {@link Optional}形式的方法
     */
    private static Optional<Method> getMethod(Class clazz, String methodName) {
        Method method = null;
        try {
            method = clazz.getMethod(methodName);
        } catch (NoSuchMethodException e) {
            log.debug("MES获取枚举接口 --> 枚举类：{},没有方法名:{}", clazz.getSimpleName(), methodName);
        }
        return Optional.ofNullable(method);
    }

}
