package com.apobates.forum.utils.lang;

import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * 枚举的扩展结构
 *
 * @author xiaofanku
 * @since 20200511
 */
public interface EnumArchitecture {
    public final static Logger logger = LoggerFactory.getLogger(EnumArchitecture.class);
    
    int getSymbol();
    
    String getTitle();
    
    static Map<Integer, String> getInstance(Class<?> instance) {
        boolean isInstance = false;
        Class<?>[] dec = instance.getInterfaces();
        for (Class<?> decFace : dec) {
            if (EnumArchitecture.class.isAssignableFrom(decFace)) {
                isInstance = true;
                break;
            }
        }
        if (!isInstance) {
            return Collections.emptyMap();
        }
        Object[] ins = instance.getEnumConstants();
        return Stream.of(ins).map(obj->{
            try{
                EnumArchitecture B = (EnumArchitecture)obj;
                return B;
            }catch(Exception e){
                return null;
            }
        }).filter(Objects::nonNull).collect(Collectors.toMap(EnumArchitecture::getSymbol, EnumArchitecture::getTitle));
    }
    
    @SuppressWarnings("unchecked")
    static <T> Optional<T> getInstance(int symbol, Class<T> instance) {
        boolean isInstance = false;
        Class<?>[] dec = instance.getInterfaces();
        for (Class<?> decFace : dec) {
            if (EnumArchitecture.class.isAssignableFrom(decFace)) {
                isInstance = true;
                break;
            }
        }
        if (!isInstance) {
            return Optional.empty();
        }
        T data = null;
        Object[] ins = instance.getEnumConstants();
        for (Object tmp : ins) {
            EnumArchitecture B = (EnumArchitecture) tmp;
            if (B.getSymbol() == symbol) {
                data = (T)B;
                break;
            }
        }
        return Optional.ofNullable(data);
    }
}