package com.infoepoch.pms.agent.common.utils.enums;

import com.infoepoch.pms.agent.platform.shared.exception.ValidationException;

import java.util.*;

/**
 * 枚举工具类
 */
public class EnumUtils {

    /**
     * 取枚举的值/文本对
     * 示例：
     * {
     * "0" : "text0",
     * "1" : "text1",
     * "2" : "text2"
     * }
     * 前端vue绑定方式：
     * <div v-for="(item, index) in Object.keys(enumData)">{{item}} : {{enumData[item]}}</div>
     */
    public static <T extends EnumBase> Map<Integer, String> getMap(Class<T> enumType) {
        Map<Integer, String> map = new HashMap<>();
        for (T t : enumType.getEnumConstants()) {
            map.put(t.getValue(), t.getText());
        }
        return map;
    }

    public static <T extends EnumBase> List<Map<String, Object>> getList(Class<T> enumType) {
        List<Map<String, Object>> mapList = new ArrayList<>();
        for (T t : enumType.getEnumConstants()) {
            HashMap<String, Object> map = new HashMap<>(4);
            map.put("value", t.getValue());
            map.put("text", t.getText());
            mapList.add(map);
        }
        return mapList;
    }

    public static <T extends EnumBase> List<Integer> getValueList(Class<T> enumType) {
        List<Integer> values = new ArrayList<>();
        for (T t : enumType.getEnumConstants()) {
            values.add(t.getValue());
        }
        return values;
    }

    public static <T extends EnumBase> String getTextByValues(Class<T> enumType, List<String> values) {
        StringBuilder sb = new StringBuilder();
        for (T t : enumType.getEnumConstants()) {
            if (values.stream().anyMatch(s -> s.equals(String.valueOf(t.getValue())))) {
                sb.append(t.getText());
                sb.append(",");
            }
        }
        return sb.toString();
    }

    public static <T extends EnumBase> List<EnumTree> getEnumTreeList(Class<T> enumType) {
        List<EnumTree> map = new ArrayList<EnumTree>();
        for (T t : enumType.getEnumConstants()) {
            map.add(new EnumTree(t.getValue(), t.getText()));
        }
        return map;
    }

    /**
     * 取枚举项值/文本集合
     * 示例：
     * [
     * { "value" : "0", "text" : "text0" },
     * { "value" : "1", "text" : "text1" },
     * { "value" : "2", "text" : "text2" }
     * ]
     * 前端vue绑定方式：
     * <div v-for="(item, index) in Object.keys(enumData)">{{item.value}} : {{item.text}}</div>
     */
    public static <T extends EnumBase> List<Map<String, Object>> getItems(Class<T> enumType) {
        List<Map<String, Object>> list = new ArrayList();
        for (T t : enumType.getEnumConstants()) {
            Map<String, Object> map = new HashMap<>();
            map.put("value", t.getValue());
            map.put("text", t.getText());
            list.add(map);
        }
        return list;
    }

    public static <T extends EnumStringBase> Map<String, String> getEnumMap(Class<T> enumType) {
        Map<String, String> resultMap = new HashMap<>();
        for (T t : enumType.getEnumConstants()) {
            resultMap.put(t.getValue(), t.getText());
        }
        return resultMap;
    }

    /**
     * 解析枚举值，值非法时返回null
     */
    public static <T extends EnumBase> T getByValue(Class<T> enumType, int value) {
        for (T t : enumType.getEnumConstants()) {
            if (t.getValue() == value)
                return t;
        }
        return null;
    }

    /**
     * 解析枚举值，值非法时抛出异常
     */
    public static <T extends EnumBase> T getByValueReq(Class<T> enumType, int value)
            throws ValidationException {
        for (T t : enumType.getEnumConstants()) {
            if (t.getValue() == value)
                return t;
        }
        throw new ValidationException("枚举“" + enumType + "”中没有找到值为“" + value + "”的项。");
    }

    /**
     * 解析枚举值，值非法时返回默认值
     */
    public static <T extends EnumBase> T getByValue(Class<T> enumType, int value, T defaultValue) {
        for (T t : enumType.getEnumConstants()) {
            if (t.getValue() == value)
                return t;
        }
        return defaultValue;
    }

    /**
     * 解析枚举值，值非法时返回null
     */
    public static <T extends EnumBase> T getByValue(Class<T> enumType, String value) {
        for (T t : enumType.getEnumConstants()) {
            if (String.valueOf(t.getValue()).equals(value))
                return t;
        }
        return null;
    }

    /**
     * 解析枚举值，值非法时返回null
     */
    public static <T extends EnumStringBase> T getByKey(Class<T> enumType, String key) {
        for (T t : enumType.getEnumConstants()) {
            if (String.valueOf(t.getValue()).equals(key))
                return t;
        }
        return null;
    }

    /**
     * 解析枚举值，值非法时抛出异常
     */
    public static <T extends EnumBase> T getByValueReq(Class<T> enumType, String value)
            throws ValidationException {
        for (T t : enumType.getEnumConstants()) {
            if (String.valueOf(t.getValue()).equals(value))
                return t;
        }
        throw new ValidationException("枚举“" + enumType + "”中没有找到值为“" + value + "”的项。");
    }

    /**
     * 解析枚举值，值非法时返回默认值
     */
    public static <T extends EnumBase> T getByValue(Class<T> enumType, String value, T defaultValue) {
        for (T t : enumType.getEnumConstants()) {
            if (String.valueOf(t.getValue()).equals(value))
                return t;
        }
        return defaultValue;
    }

    /**
     * 解析枚举值，值非法时返回null
     */
    public static <T extends EnumStringBase> T getByStringValue(Class<T> enumType, String value) {
        for (T t : enumType.getEnumConstants()) {
            if (String.valueOf(t.getValue()).equals(value))
                return t;
        }
        return null;
    }

    /**
     * 解析枚举值，值非法时抛出异常
     */
    public static <T extends EnumStringBase> T getByStringValueReq(Class<T> enumType, String value)
            throws ValidationException {
        for (T t : enumType.getEnumConstants()) {
            if (String.valueOf(t.getValue()).equals(value))
                return t;
        }
        throw new ValidationException("枚举“" + enumType + "”中没有找到值为“" + value + "”的项。");
    }

    /**
     * 解析枚举值，值非法时返回默认值
     */
    public static <T extends EnumStringBase> T getByStringValue(Class<T> enumType, String value, T defaultValue) {
        for (T t : enumType.getEnumConstants()) {
            if (String.valueOf(t.getValue()).equals(value))
                return t;
        }
        return defaultValue;
    }

    /**
     * 根据文本解析枚举值，值非法时返回null
     */
    public static <T extends EnumBase> T getByText(Class<T> enumType, String text) {
        for (T t : enumType.getEnumConstants()) {
            if (t.getText().equals(text))
                return t;
        }
        return null;
    }

    public static <T extends EnumBase> List<Integer> getByTexts(Class<T> enumType, List<String> texts) {
        List<Integer> values = new ArrayList<>();
        for (T t : enumType.getEnumConstants()) {
            texts.forEach(s -> {
                if (t.getText().equals(s)) {
                    values.add(t.getValue());
                }
            });
        }
        return values;
    }

    public static <T extends EnumBase> List<String> getTextList(Class<T> enumType) {
        List<String> texts = new ArrayList<>();
        for (T t : enumType.getEnumConstants()) {
            texts.add(t.getText());
        }
        return texts;
    }

    /**
     * 根据value返回 text值，如不存在返回默认值
     *
     * @param value       value值
     * @param defaultText 默认text
     */
    public static <T extends EnumBase> String getTextByValue(Class<T> enumType, Integer value, String defaultText) {
        if (Objects.isNull(value)) {
            return defaultText;
        }
        for (T t : enumType.getEnumConstants()) {
            if (t.getValue() == value) {
                return t.getText();
            }
        }
        return defaultText;
    }
}
