package cc.smtweb.framework.test;



import cc.smtweb.framework.core.common.AbstractEnum;
import cc.smtweb.framework.core.common.IntEnum;
import cc.smtweb.framework.core.common.StrEnum;
import cc.smtweb.framework.core.common.SwEnum;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import java.lang.reflect.Field;
import java.lang.reflect.Type;

/**
 * Created by Akmm at 2017/5/12 17:14
 * 枚举类转js定义
 */
public class ToolEnum2Js {
    public static void main(String[] args) throws Exception {
        buildJs(SwEnum.class);//传枚举定义类
    }

    private static void buildJs(Class<?> cls) throws Exception {
        Class<?>[] classes = cls.getDeclaredClasses();// 获得代表内部类的Class对象组成的数组
        StringBuilder sb = new StringBuilder();
        for (Class<?> clazz : classes) {// 遍历Class对象数组
//            System.out.println("类的标准名称：" + clazz.getCanonicalName());
//            System.out.println("类的修饰符：" + Modifier.toString(clazz.getModifiers()));
            Type superClass = clazz.getGenericSuperclass();// 获得直接父类

//            System.out.print("类的直接继承类：");
            if (superClass.equals(IntEnum.class)) {
                buildJsInt(clazz, sb);
            }else if (superClass.equals(StrEnum.class)) {
                buildJsStr(clazz, sb);
            }else if (superClass.getTypeName().startsWith(AbstractEnum.class.getTypeName()+"<")){
                buildJsBean(clazz,sb);
            }

        }
        System.out.println(sb.substring(1));
    }

    private static void buildJsInt(Class<?> clazz, StringBuilder sb) throws Exception {
        IntEnum instance = (IntEnum) clazz.newInstance();
        Field[] fields = clazz.getDeclaredFields();// 获得该类对象的所有非继承域
        if (fields.length == 0) return;
        StringBuilder sbc = new StringBuilder(128);
        StringBuilder sbDefines = new StringBuilder(128);
        for (Field field : fields) {
            if (!field.getType().equals(AbstractEnum.IntEnumBean.class)) continue;
            AbstractEnum.IntEnumBean value = (AbstractEnum.IntEnumBean) field.get(instance);
            sbc.append(",\n").append(field.getName()).append(": ").append(value.value);
            sbDefines.append(",\n").append("{ value: ").append(value.value).append(", label: \"").append(value.name).append("\" }");
        }
        sb.append("\n").append("export const ").append(clazz.getSimpleName()).append(" = {\n").append(sbc.length()>2?sbc.substring(2):"").append(",\n...useEnumProps([\n").append(sbDefines.length()>2?sbDefines.substring(2):"").append("\n])").append("\n}");
    }

    private static void buildJsStr(Class<?> clazz, StringBuilder sb) throws Exception {
        StrEnum instance = (StrEnum) clazz.newInstance();
        Field[] fields = clazz.getDeclaredFields();// 获得该类对象的所有非继承域
        if (fields.length == 0) return;
        StringBuilder sbc = new StringBuilder(128);
        StringBuilder sbDefines = new StringBuilder(128);
        for (Field field : fields) {
            if (!field.getType().equals(AbstractEnum.StrEnumBean.class)) continue;
            AbstractEnum.StrEnumBean value = (AbstractEnum.StrEnumBean) field.get(instance);
            sbc.append(",\n").append(field.getName()).append(": \"").append(value.value).append("\"");
            sbDefines.append(",\n").append("{ value: \"").append(value.value).append("\", label: \"").append(value.name).append("\" }");
        }
        sb.append("\n").append("export const ").append(clazz.getSimpleName()).append(" = {\n").append(sbc.length()>2?sbc.substring(2):"").append(",\n...useEnumProps([\n").append(sbDefines.length()>2?sbDefines.substring(2):"").append("\n])").append("\n}");
    }

    private static void buildJsBean(Class<?> clazz, StringBuilder sb)throws Exception{
       Object instance = clazz.newInstance();
        Field[] fields = clazz.getDeclaredFields();// 获得该类对象的所有非继承域
        Type type1 = ((ParameterizedTypeImpl) clazz.getGenericSuperclass()).getActualTypeArguments()[0];
        Type type2 = ((ParameterizedTypeImpl) clazz.getGenericSuperclass()).getActualTypeArguments()[1];
        if (fields.length == 0) return;
        boolean isNumber = Integer.class.getTypeName().equals(type1.getTypeName());
        StringBuilder sbc = new StringBuilder(128);
        StringBuilder sbDefines = new StringBuilder(128);
        for (Field field : fields) {
            if (!field.getType().equals(type2)) continue;
            Object value = field.get(instance);
            if (isNumber){
                AbstractEnum.IntEnumBean tempValue = (AbstractEnum.IntEnumBean) field.get(instance);
                sbc.append(",\n").append(field.getName()).append(": ").append(tempValue.value);
                sbDefines.append(",\n").append("{ value: ").append(tempValue.value).append(", label: \"").append(tempValue.name).append("\"");
            }else {
                AbstractEnum.StrEnumBean tempValue = (AbstractEnum.StrEnumBean) field.get(instance);
                sbc.append(",\n").append(field.getName()).append(": \"").append(tempValue.value).append("\"");
                sbDefines.append(",\n").append("{ value: \"").append(tempValue.value).append("\", label: \"").append(tempValue.name).append("\"");
            }
            // 处理bean
            Field[] beanFields = value.getClass().getFields();// 获得该类对象的所有字段
            StringBuilder sbBean = new StringBuilder();
            sbBean.append(" bean: { ");
            if(beanFields.length >0 ){
                for(Field beanField: beanFields){
                    Object beanValue = beanField.get(value);
                    String name = beanField.getName();
                    sbBean.append("name".equals(name)?"label":name).append(": ").append(formatValue(beanValue)).append(", ");
                }
            }
            sbBean.append("}");
            sbDefines.append(",").append(sbBean.toString()).append(" }");
        }
        sb.append("\n").append("export const ").append(clazz.getSimpleName()).append(" = {\n").
                append(sbc.length()>2?sbc.substring(2):"").append(",\n...useEnumProps([\n").append(sbDefines.length()>2?sbDefines.substring(2):"").append("\n])").append("\n}");
    }
    private static String formatValue(Object obj){
        if(obj instanceof String){
            return "\""+obj.toString()+"\"";
        }
        return obj.toString();
    }
}
