package com.community.commom.utils;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 权举类型转换utils
 * Created by wuxuewen on 2017/3/14.
 */
public class EnumUtils {

    /**
     * 把enum封成list，便于前端调用
     *
     * @return 例如：
     * model.addAttribute("cateList", Enums.toList(Enums.BrandCate.class));
     * <select cname="type" >
     * <c:forEach var="type" items="${cateList}">
     * <option value="${type.key}">${type.cname}</option>
     * </c:forEach>
     * </select>
     */
    public static <T extends Enum> List<T> toList(Class<T> clazz) {
        return Arrays.asList(clazz.getEnumConstants());
    }

    /**
     * 转为MAP
     *
     * @param clazz         Enums.class
     * @param keyMethodName MethodName
     * @param <T>           Enums
     * @return Map<Object,Object>
     */
    public static <T extends Enum> Map<Object, T> toMap(Class<T> clazz, String keyMethodName) {
        T[] universe = getEnumConstantsShared(clazz);
        if (universe == null) {
            return null;
        }
        Map<Object, T> directory = new HashMap<>();
        for (T constant : universe)
            try {
                Object key;
                if (keyMethodName != null && keyMethodName.trim().length() > 0) {
                    Method method = constant.getClass().getMethod(keyMethodName);
                    key = method.invoke(constant);
                } else {
                    key = constant.name();
                }
                directory.put(key, constant);
            } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
                e.printStackTrace();
            }
        return directory;
    }

    /**
     * 转为MAP
     *
     * @param clazz         Enums.class
     * @param keyMethodName MethodName
     * @param valMethodName MethodName
     * @param <T>           Enums
     * @return Map<String,Object>
     */
    public static <T extends Enum> Map<String, Object> toMap(Class<T> clazz, String keyMethodName, String valMethodName) {
        T[] universe = getEnumConstantsShared(clazz);
        if (universe == null) {
            return null;
        }
        Map<String, Object> directory = new HashMap<>(2 * universe.length);
        for (T constant : universe)
            try {
                Object key, value;
                if (keyMethodName != null && keyMethodName.trim().length() > 0) {
                    Method method = constant.getClass().getMethod(keyMethodName);
                    key = method.invoke(constant);
                } else {
                    key = constant.name();
                }
                if (valMethodName != null && valMethodName.trim().length() > 0) {
                    Method method = constant.getClass().getMethod(valMethodName);
                    value = method.invoke(constant);
                } else {
                    value = constant;
                }
                directory.put(key.toString(), value);
            } catch (NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
                e.printStackTrace();
            }
        return directory;
    }


    /**
     * 获取权举对象列表
     *
     * @param clazz Enum.class
     * @param <T>   Enum
     * @return Enums
     */
    private static <T extends Enum> T[] getEnumConstantsShared(Class<T> clazz) {
        T[] enumConstants;
        if (!clazz.isEnum()) return null;
        try {
            final Method values = clazz.getMethod("values");
            @SuppressWarnings("unchecked")
            T[] temporaryConstants = (T[]) values.invoke(null);
            enumConstants = temporaryConstants;
        } catch (InvocationTargetException | NoSuchMethodException |
                IllegalAccessException ex) {
            return null;
        }
        return enumConstants;
    }
}
