package com.unis.crk.Generator;

import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.core.exceptions.MybatisPlusException;
import com.baomidou.mybatisplus.core.toolkit.StringPool;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.generator.AutoGenerator;
import com.baomidou.mybatisplus.generator.InjectionConfig;
import com.baomidou.mybatisplus.generator.config.*;
import com.baomidou.mybatisplus.generator.config.po.TableInfo;
import com.baomidou.mybatisplus.generator.config.rules.DateType;
import com.baomidou.mybatisplus.generator.config.rules.NamingStrategy;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * 代码生成器
 * @author pengxl
 * @version 1.0
 * 创建时间: 2019/05/24 13:23
 */
public class CodeGenerator {

    /**数据库配置**/
    private final static String DRIVER_CLASS_NAME = "com.mysql.cj.jdbc.Driver";
    private final static String URL = "jdbc:mysql://127.0.0.1:3308/crk_nmg?useUnicode=true&characterEncoding=UTF-8&useSSL=true&serverTimezone=GMT%2b8";
    private final static String USER_NAME = "root";
    private final static String PASSWORD = "123456";

    /**作者**/
    private final static String AUTHOR = "TangSong";

    /**是否覆盖**/
    private final static Boolean FileOverride = true;

    /**生成代码包路径**/
//    private final static String PACKAGE_PATH = "com.unis.crk.business.kcgl";
//    private final static String PACKAGE_PATH = "com.unis.crk.common";
//    private final static String PACKAGE_PATH = "com.unis.crk.basic";
    private final static String PACKAGE_PATH = "com.unis.crk.common";
    /**MapperXML文件生成路径**/
//    private final static String MAPPER_XML_FILE_PATH = "/src/main/resources/mapper/business/qcrk/";
//    private final static String MAPPER_XML_FILE_PATH = "/src/main/resources/mapper/common/";
//    private final static String MAPPER_XML_FILE_PATH = "/src/main/resources/mapper/basic/";
    private final static String MAPPER_XML_FILE_PATH = "/src/main/resources/mapper/common/";



    /**
     * <p>
     * 读取控制台内容
     * </p>
     */
    public static String scanner(String tip) {
        Scanner scanner = new Scanner(System.in);
        StringBuilder help = new StringBuilder();
        help.append("请输入" + tip + "：");
        System.out.println(help.toString());
        if (scanner.hasNext()) {
            String ipt = scanner.next();
            if (StringUtils.isNotEmpty(ipt)) {
                return ipt;
            }
        }
        throw new MybatisPlusException("请输入正确的" + tip + ":");
    }





    public static void main(String[] args) {
        // 代码生成器
        AutoGenerator mpg = new AutoGenerator();
        /***************全局配置************/
        GlobalConfig gc = new GlobalConfig();
        String projectPath = System.getProperty("user.dir");
        gc.setOutputDir(projectPath + "/src/main/java");
        gc.setAuthor(AUTHOR);
        gc.setFileOverride(FileOverride); //是否覆盖
        gc.setEnableCache(false);
        gc.setOpen(false);
        gc.setSwagger2(true);
        gc.setDateType(DateType.ONLY_DATE);
        gc.setBaseResultMap(true);
        gc.setIdType(IdType.UUID);
        mpg.setGlobalConfig(gc);

        /***************数据源配置************/
        DataSourceConfig dsc = new DataSourceConfig();
        dsc.setDbType(DbType.MYSQL);
        dsc.setDriverName(DRIVER_CLASS_NAME);
        dsc.setUrl(URL);
        dsc.setUsername(USER_NAME);
        dsc.setPassword(PASSWORD);
        // dsc.setSchemaName("public");
        mpg.setDataSource(dsc);
        /***************包配置************/
        PackageConfig pc = new PackageConfig();
        pc.setParent(PACKAGE_PATH);
        mpg.setPackageInfo(pc);
        /***************自定义配置，自定义MapperXML输出配置************/
        InjectionConfig cfg = new InjectionConfig() {
            @Override
            public void initMap() {
                //自定义模板参数类型为Map,模板中取值为${cfg.参数名}
            }
        };
        String templatePath = "/templates/my-mapper.xml.vm";
        String mapperXmlFilePath = projectPath + MAPPER_XML_FILE_PATH;
        List<FileOutConfig> focList = new ArrayList<>();
        focList.add(new FileOutConfig(templatePath) {
            @Override
            public String outputFile(TableInfo tableInfo) {
                return mapperXmlFilePath + tableInfo.getEntityName() + "Mapper" + StringPool.DOT_XML;
            }
        });
        cfg.setFileOutConfigList(focList);
        mpg.setCfg(cfg);
        /***************配置自定义Controller生成模板,关闭默认MapperXml输出************/
        TemplateConfig template = new TemplateConfig();
//        template.setController("/templates/my-controller1.java.vm");
//        template.setService("/templates/my-service1.java.vm");
//        template.setServiceImpl("/templates/my-serviceImpl1.java.vm");
//        template.setMapper("/templates/my-mapper.java.vm");
//        TemplateConfig template = new TemplateConfig();
        template.setController("/templates/my-controller.java.vm");
        template.setService("/templates/my-service.java.vm");
        template.setServiceImpl("/templates/my-serviceImpl.java.vm");
        template.setMapper("/templates/my-mapper.java.vm");
//        template.setMapper(null);
//        template.setController(null);
//        template.setService(null);
//        template.setServiceImpl(null);

        template.setXml(null);
        mpg.setTemplate(template);
        /***************************数据库表配置***************************************/
        String[] tableNames = scanner("表名,多个表','隔开").split(",");
        StrategyConfig strategy = new StrategyConfig();
        strategy.setNaming(NamingStrategy.underline_to_camel);
        strategy.setColumnNaming(NamingStrategy.underline_to_camel);
        strategy.setEntityLombokModel(true);
        strategy.setRestControllerStyle(true);
        strategy.setInclude(tableNames);
        strategy.setControllerMappingHyphenStyle(false);
        strategy.setTablePrefix(pc.getModuleName() + "_");
        // strategy.setSuperEntityColumns("id");
        mpg.setStrategy(strategy);
        // 执行生成代码
        mpg.execute();
        //生成vo
//        produceViewObject(false,tableNames);
    }

    /**
     * 根据表名生成VO对象,用于mybatis-plus代码生成以后再生成
     *
     * @param isTablePrefix
     * @param tableNames
     */
    private static void produceViewObject(boolean isTablePrefix, String... tableNames) {

        String projectPath = System.getProperty("user.dir");
        /***************包配置************/
        for (int i = 0; i < tableNames.length; i++) {
            String tableName = tableNames[i];
            tableName = isTablePrefix ? tableName.substring(tableName.indexOf("_") + 1) : tableName;
            String packagePath = org.apache.commons.lang.StringUtils.replace(PACKAGE_PATH,".","/");
            String outPutDir = projectPath+"/src/main/java/"+packagePath+"/entity/vo/";
            String baseFileName = underline2Camel(tableName, false);
            try {
                File outFile = new File(outPutDir);
                if (!outFile.exists()) {
                    outFile.mkdirs();
                }
                File voFile = new File(outFile, baseFileName + "Vo.java");
                if (!voFile.exists()) {
                    voFile.createNewFile();
                }else {
                    if (!FileOverride){ //不覆盖文件跳过
                        continue;
                    }
                }
                BufferedReader reader = new BufferedReader(
                        new FileReader(projectPath+"/src/main/resources/templates/my-vo.java.vm"));
                FileWriter fw = new FileWriter(voFile);
                String line = null;
                while ((line = reader.readLine()) != null) {
                    // 将实体类中的entity变为Vo
                    line = line.replace("${entity}", baseFileName).replace("${package}",PACKAGE_PATH);
                    // 去掉mybatis-plus注解
                    if (line.contains("TableName") || line.contains("TableField") || line.contains("Accessors")) {
                        continue;
                    }
                    line += "\r\n";
                    fw.write(line);
                }
                fw.close();
                reader.close();
                System.out.println("生成vo:"+baseFileName + "Vo.java");
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 下划线转驼峰法(默认小驼峰)
     *
     * @param line 源字符串
     * @param smallCamel 大小驼峰,是否为小驼峰(驼峰，第一个字符是大写还是小写)
     * @return 转换后的字符串
     */
    public static String underline2Camel(String line, boolean... smallCamel) {
        if (org.apache.commons.lang.StringUtils.isBlank(line)) {
            return "";
        }
        StringBuffer sb = new StringBuffer();
        Pattern pattern = Pattern.compile("([A-Za-z\\d]+)(_)?");
        Matcher matcher = pattern.matcher(line);
        // 匹配正则表达式
        while (matcher.find()) {
            String word = matcher.group();
            // 当是true 或则是空的情况
            if ((smallCamel.length == 0 || smallCamel[0]) && matcher.start() == 0) {
                sb.append(Character.toLowerCase(word.charAt(0)));
            } else {
                sb.append(Character.toUpperCase(word.charAt(0)));
            }

            int index = word.lastIndexOf('_');
            if (index > 0) {
                sb.append(word.substring(1, index).toLowerCase());
            } else {
                sb.append(word.substring(1).toLowerCase());
            }
        }
        return sb.toString();
    }

    /**
     * 驼峰法转下划线
     *
     * @param line 源字符串
     * @return 转换后的字符串
     */
    public static String camel2Underline(String line) {
        if (org.apache.commons.lang.StringUtils.isBlank(line)) {
            return "";
        }
        line = String.valueOf(line.charAt(0)).toUpperCase().concat(line.substring(1));
        StringBuffer sb = new StringBuffer();
        Pattern pattern = Pattern.compile("[A-Z]([a-z\\d]+)?");
        Matcher matcher = pattern.matcher(line);
        while (matcher.find()) {
            String word = matcher.group();
            sb.append(word.toUpperCase());
            sb.append(matcher.end() == line.length() ? "" : "_");
        }
        return sb.toString();
    }

}
