package com.dayou.utils;

import com.dayou.enums.CodeMsgEnumInterface;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;

/**
 * 根据实现CodeMsgEnumInterface接口的枚举 的code值或msg值返回相匹配的枚举类型
 *
 * @author lq
 */
public class EnumUtils {

    private static final Logger logger = LoggerFactory.getLogger(EnumUtils.class);

    /**
     * 对应的枚举类需要只需实现CodeMsgEnumInterface接口
     *
     * @param codeOrMsg code（Number类型）值 或者 msg（String类型）值
     * @param clazz     枚举class
     * @param <T>       枚举对象
     * @return 根据传入的codeOrMsg 匹配对应的枚举
     */
    public static <T extends CodeMsgEnumInterface> T match(Object codeOrMsg, Class<T> clazz, T defaultValue) {
        if (codeOrMsg == null || clazz == null) {
            return defaultValue;
        }
        if (clazz.isEnum()) {
            try {
                T[] enumConstants = clazz.getEnumConstants();
                if (enumConstants == null || enumConstants.length == 0) {
                    return null;
                }
                for (T t : enumConstants) {
                    if (codeOrMsg instanceof Number) {
                        if (codeOrMsg.equals(t.getCode())) {
                            return t;
                        }
                    } else if (codeOrMsg instanceof String) {
                        if (((String) codeOrMsg).trim().equals(t.getMsg())) {
                            return t;
                        }
                    } else {
                        return defaultValue;
                    }
                }
            } catch (Exception e) {
                logger.error("match error {}", e);
            }
        }
        return defaultValue;
    }

    public static <K, V, T extends CodeMsgEnumInterface<K, V>> List<K> getEnumKeyList(Class<T> clazz) {
        List<K> list = new ArrayList<>();
        if (clazz != null) {
            if (clazz.isEnum()) {
                T[] enumConstants = clazz.getEnumConstants();
                if (enumConstants == null || enumConstants.length == 0) {
                    return null;
                }
                for (T t : enumConstants) {
                    list.add(t.getCode());
                }
            }
        }
        return list;
    }



    /**
     * 对应的枚举类需要只需实现ICodeMsgEnum接口
     *
     * @param codeOrMsg code（Number类型 string类型）值 或者 msg（String类型 Number类型）值 其他类型不支持
     * @param clazz     枚举class
     * @param <T>       枚举对象
     * @return 根据传入的codeOrMsg 匹配对应的枚举 如果返回NULL 则没匹配到
     */
    public static <T extends CodeMsgEnumInterface> T match(Object codeOrMsg, Class<T> clazz) {
        if (codeOrMsg == null || clazz == null) {
            return null;
        }
        logger.debug("codeOrMsg is {} clazz is {} ", codeOrMsg, clazz.getName());
        if (clazz.isEnum()) {
            T[] enumConstants = clazz.getEnumConstants();
            if (enumConstants == null || enumConstants.length == 0) {
                return null;
            }
            for (T t : enumConstants) {
                if (codeOrMsg instanceof Number) {
                    if (codeOrMsg.equals(t.getCode())) {
                        return t;
                    } else {
                        if (codeOrMsg.equals(t.getMsg())) {
                            return t;
                        }
                    }
                } else if (codeOrMsg instanceof String) {
                    if (((String) codeOrMsg).trim().equals(t.getMsg())) {
                        return t;
                    } else {
                        if (((String) codeOrMsg).trim().equals(t.getCode())) {
                            return t;
                        }
                    }
                } else {
                    logger.error("this enumutils only support String or Number types  of codeOrMsg ");
                    return null;
                }
            }
        }
        //没有匹配到对应的枚举
        return null;
    }


    /**
     * 该枚举是否包含 code or msg
     *
     * @param codeOrMsg
     * @param clazz
     * @param <T>
     * @return
     */
    public static <T extends CodeMsgEnumInterface> boolean containsCodeOrMsg(Object codeOrMsg, Class<T> clazz) {
        T match = match(codeOrMsg, clazz);
        return match == null ? false : true;
    }


    public static  <K,V,T extends CodeMsgEnumInterface<K,V>> K  getKByV(V v, Class<T> clazz){
        T t=EnumUtils.match(v,clazz);
        K k =null;
        if(t!=null){
            k=t.getCode();
        }
        return k;
    }

    public static  <K,V,T extends CodeMsgEnumInterface<K,V>> V  getVByK(K k, Class<T> clazz){
        T t=EnumUtils.match(k,clazz);
        V v =null;
        if(t!=null){
            v=t.getMsg();
        }
        return v;
    }

}
