import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.converts.MySqlTypeConvert;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.config.rules.IColumnType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class ExecuteCore {

    public static void main(String[] args) throws IOException {

        Properties properties = new Properties();
        // 使用InPutStream流读取properties文件
        try{
            properties.load(ExecuteCore.class.getClassLoader().getResourceAsStream("config.properties"));
        }catch (Exception e){
            e.printStackTrace();
            properties.load(ExecuteCore.class.getClassLoader().getResourceAsStream("config.properties"));
        }
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();

        // 全局策略配置
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/output"); // 生成文件的输出目录,默认D根目录
        gc.setFileOverride(true); // 是否覆盖已有文件
        gc.setAuthor(properties.getProperty("author"));
        gc.setOpen(true);        // 是否打开输出目录,默认true
        gc.setEnableCache(false); // 是否在xml中添加二级缓存配置,默认false
        gc.setSwagger2(properties.getProperty("isEnableSwagger").equals("true")?true:false);    // 开启 swagger2 模式,默认false，这里推荐使用JApiDocs，使用方法见：https://blog.csdn.net/u013919153/article/details/110440311
        gc.setEntityName("%s");   //指定生成实体类名称
        gc.setMapperName("%sMapper");   // mapper文件名称
        gc.setXmlName("%sMapper");      // xml文件名称
        gc.setServiceName("I%sService");    // 服务名称
        gc.setServiceImplName("%sServiceImpl"); // 服务接口名称
        gc.setBaseResultMap(true);
        gc.setBaseColumnList(true);

        mpg.setGlobalConfig(gc);

        // 数据源配置
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setUrl(properties.getProperty("url"));
        dsc.setDriverName(properties.getProperty("driver-class-name"));
        dsc.setUsername(properties.getProperty("username"));
        dsc.setPassword(properties.getProperty("password"));
        dsc.setTypeConvert(new MySqlTypeConvertCustom());
        mpg.setDataSource(dsc);

        // 包名配置
        PackageConfig pc = new PackageConfig();
        pc.setModuleName(null);   //模块名
        pc.setParent(properties.getProperty("parentPackage")); //包名
        pc.setEntity(properties.getProperty("entityPackage"));   //数据库对应的包名
        pc.setMapper(properties.getProperty("mapperPackage"));    //Mapper对应的包名
        pc.setController(properties.getProperty("controllerPackage")); //Controller对应的包名
        mpg.setPackageInfo(pc);

        // 自定义配置
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                // to do nothing
            }
        };

        List<FileOutConfig> focList = new ArrayList<>();


        // 如果模板引擎是 freemarker
        String templatePath = "/templates/mapper.xml.ftl";

        // 自定义输出配置
        // 自定义配置会被优先输出
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义xml输出文件名
                return projectPath + "/output/mapper/"
                        + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });


        // 自定义配置会被优先输出
        focList.add(new FileOutConfig( "/templates/controller.java.ftl") {
            @Override
            public String outputFile(TableInfo tableInfo) {
                // 自定义xml输出文件名
                return projectPath + "/output/com/changfa/controller/"
                        + tableInfo.getControllerName()  + StringPool.DOT_JAVA;
            }
        });
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);

        // 配置模板
        TemplateConfig templateConfig = new TemplateConfig();
        // 配置自定义输出模板
        // templateConfig.setEntity();
        // templateConfig.setService();
        //templateConfig.setController(null);
        templateConfig.setXml(null);

        mpg.setTemplate(templateConfig);

        // 策略配置
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel); // 数据库表映射到实体的命名策略
        strategy.setColumnNaming(NamingStrategy.underline_to_camel); // 数据库表字段映射到实体的命名策略, 未指定按照 naming 执行
        strategy.setSuperEntityClass(properties.getProperty("superEntityClass")); //自定义继承的Entity类全称，带包名
        strategy.setEntityTableFieldAnnotationEnable(true);
        strategy.setSuperEntityColumns(properties.getProperty("superEntityColumns").split(","));// 自定义基础的Entity类，公共字段
        strategy.setEntityLombokModel(true); // 是否为lombok模型
        strategy.setEntityBooleanColumnRemoveIsPrefix(true); // Boolean类型字段是否移除is前缀
        strategy.setRestControllerStyle(true); // 生成 @RestController 控制器，个人觉得有点多余
        strategy.setSuperControllerClass("com.changfa.base.BaseController");
        if(!"*".equals(properties.getProperty("tableName"))){
            strategy.setInclude(properties.getProperty("tableName").split(","));  //当对某张表有所改动但只想重新生成这张表，可以这样设置
        }
        strategy.setControllerMappingHyphenStyle(true); // 驼峰转连字符 如 umps_user 变为 upms/user
        strategy.setTablePrefix("t_"); // 表前缀
        mpg.setStrategy(strategy);
        mpg.setTemplateEngine(new FreemarkerTemplateEngine()); //设置模板引擎类型，默认为 velocity
        mpg.execute();
    }
}

/**
 * 自定义类型转换 ,解决mybatis plus自动生成代码tinyint(1)自动转换为Boolean
 */
class MySqlTypeConvertCustom extends MySqlTypeConvert implements ITypeConvert {
    @Override
    public IColumnType processTypeConvert(GlobalConfig globalConfig, String fieldType) {
        String t = fieldType.toLowerCase();
        if (t.contains("tinyint(1)")) {
            return DbColumnType.INTEGER;
        }
        return super.processTypeConvert(globalConfig, fieldType);
    }
}
