package cn.reghao.tnb.sb.db.autobatis.table;

import cn.reghao.tnb.sb.db.autobatis.annotation.field.*;
import cn.reghao.tnb.sb.db.autobatis.StringUtil;
import cn.reghao.tnb.sb.util.ClassUtil;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.*;
import java.util.stream.Collectors;

/**
 * MyBatis 表自动化管理工具
 *
 * @author reghao
 * @date 2019-11-28 09:38:18
 */
public class TableManager {
    private static Map<String, String> typeMap = new HashMap<>();

    static {
        // 数值类型
        typeMap.put("boolean", "tinyint(1)");
        typeMap.put("short", "smallint");
        typeMap.put("int", "int");
        typeMap.put("long", "bigint");
        typeMap.put("double", "decimal");
        typeMap.put("java.lang.Boolean", "tinyint(1)");
        typeMap.put("java.lang.Short", "int");
        typeMap.put("java.lang.Integer", "int");
        typeMap.put("java.lang.Long", "bigint");
        typeMap.put("java.lang.Double", "decimal");
        // 字符串类型
        typeMap.put("java.lang.String", "varchar");
        // 日期类型
        typeMap.put("java.sql.Timestamp", "timestamp");
    }

    /**
     * 类转换为表结构
     *
     * @param
     * @return
     * @date 2020-04-02 下午10:26
     */
    public Table classToTable(Class clazz) {
        String classname = ClassUtil.classname(clazz);
        String tableName = StringUtil.separateByUnderline(classname);
        String uniqueKey = null;

        List<TableField> tableFields = new ArrayList<>();
        Field[] fields = clazz.getDeclaredFields();
        List<Field> list = new ArrayList<>();
        list.addAll(Arrays.asList(fields));
        list.addAll(superClassFields(clazz));

        for (Field field : list) {
            String fieldName = StringUtil.separateByUnderline(field.getName());
            String typeName = field.getType().getName();

            Unique unique = field.getAnnotation(Unique.class);
            if (unique != null) {
                uniqueKey = fieldName;
            }

            Mediumint mediumint = field.getAnnotation(Mediumint.class);
            Char char1 = field.getAnnotation(Char.class);
            Varchar varchar = field.getAnnotation(Varchar.class);
            Mediumtext mediumtext = field.getAnnotation(Mediumtext.class);
            TimeStamp timestamp = field.getAnnotation(TimeStamp.class);
            if (mediumint != null) {
                String type = mediumint.name();
                tableFields.add(new TableField(FieldType.numeric, fieldName, type));
            } else if (char1 != null) {
                int len = char1.value();
                String type = char1.name() + "(" + len + ")";
                tableFields.add(new TableField(FieldType.string, fieldName, type));
            } else if (varchar != null) {
                int len = varchar.value();
                String type = typeMap.get(typeName) + "(" + len + ")";
                tableFields.add(new TableField(FieldType.string, fieldName, type));
            } else if (mediumtext != null) {
                String type = mediumtext.name();
                tableFields.add(new TableField(FieldType.string, fieldName, type));
            } else if (timestamp != null) {
                String type = typeMap.get(typeName);
                tableFields.add(new TableField(FieldType.timestamp, fieldName, type));
            } else {
                tableFields.add(new TableField(FieldType.numeric, fieldName, typeMap.get(typeName)));
            }
        }

        return new Table(tableName, uniqueKey, tableFields);
    }

    /**
     * 父类的字段
     *
     * @param
     * @return
     * @date 2020-04-17 下午3:21
     */
    private List<Field> superClassFields(Class clazz) {
        Class superClass = clazz.getSuperclass();
        return Arrays.stream(superClass.getDeclaredFields())
                .filter(field -> field.getModifiers() == Modifier.PROTECTED)
                .collect(Collectors.toList());
    }

    public String tableName(Class clazz) {
        String classname = ClassUtil.classname(clazz);
        return StringUtil.separateByUnderline(classname);
    }

    /**
     * 表字段
     *
     * @param
     * @return
     * @date 2020-04-03 下午2:02
     */
    public List<String> tableFields(Class clazz) {
        Field[] fields = clazz.getDeclaredFields();
        List<Field> list = new ArrayList<>();
        list.addAll(Arrays.asList(fields));
        list.addAll(superClassFields(clazz));

        List<String> list1 = new ArrayList<>();
        for (Field field : list) {
            list1.add(StringUtil.separateByUnderline(field.getName()));
        }

        return list1;
    }

    /**
     * 类字段
     *
     * @param
     * @return
     * @date 2020-04-03 下午2:02
     */
    public List<String> classFields(Class clazz) {
        Field[] fields = clazz.getDeclaredFields();
        List<Field> list = new ArrayList<>();
        list.addAll(Arrays.asList(fields));
        list.addAll(superClassFields(clazz));

        List<String> list1 = new ArrayList<>();
        for (Field field : list) {
            list1.add(field.getName());
        }

        return list1;
    }
}
