package xyz.wbsite.dbtool.javafx.manger.callable;

import xyz.wbsite.dbtool.javafx.manger.FreeMarkerManager;
import xyz.wbsite.dbtool.javafx.manger.ManagerFactory;
import xyz.wbsite.dbtool.javafx.manger.XmlManager;
import xyz.wbsite.dbtool.javafx.po.AbstractDBmapper;
import xyz.wbsite.dbtool.javafx.po.DataBase;
import xyz.wbsite.dbtool.javafx.po.Module;
import xyz.wbsite.dbtool.javafx.po.MySQLDBmapper;
import xyz.wbsite.dbtool.javafx.po.OracleDBmapper;
import xyz.wbsite.dbtool.javafx.po.Project;
import xyz.wbsite.dbtool.javafx.po.SQLiteDBmapper;
import xyz.wbsite.dbtool.javafx.po.Table;
import xyz.wbsite.dbtool.javafx.tool.Tool;
import xyz.wbsite.dbtool.web.frame.utils.FileUtil;
import xyz.wbsite.dbtool.web.frame.utils.ResourceUtil;

import java.io.File;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.concurrent.Callable;

public class SpringBootCallable implements Callable {

    private File root;
    private Project project;
    private AbstractDBmapper dBmapper;
    private FreeMarkerManager freeMarkerManager;

    public SpringBootCallable(Project project, File root) {
        this.root = root;
        this.project = project;
        this.freeMarkerManager = ManagerFactory.getFreeMarkerManager();
        // 根据配置获取数据库处理器
        if (project.getDatabase().name().equals(DataBase.MySQL.name())) {
            this.dBmapper = new MySQLDBmapper();
        } else if (project.getDatabase().name().equals(DataBase.Oracle.name())) {
            this.dBmapper = new OracleDBmapper();
        } else if (project.getDatabase().name().equals(DataBase.SQLite.name())) {
            this.dBmapper = new SQLiteDBmapper();
        } else {
            this.dBmapper = new MySQLDBmapper();
        }
    }

    public Boolean call() throws Exception {
        // 创建项目文件夹
        File projectDir = Tool.createPath(root, project.getProjectName());
        // 清空内容
        Tool.clear(projectDir);
        // 生成java目录
        File javaDir = Tool.createPath(projectDir.getAbsolutePath(), "src", "main", "java");
        // 生成资源目录
        File resourcesDir = Tool.createPath(projectDir.getAbsolutePath(), "src", "main", "resources");
        // 生成域名目录
        File domainDir = javaDir;
        for (String s : project.getProjectBasePackage().split("\\.")) {
            domainDir = Tool.createPath(domainDir.getAbsolutePath(), s);
        }
        // 生成单元测试java目录
        File testJavaDir = Tool.createPath(projectDir.getAbsolutePath(), "src", "test", "java");
        File testDomainDir = testJavaDir;
        for (String s : project.getProjectBasePackage().split("\\.")) {
            testDomainDir = Tool.createPath(testDomainDir.getAbsolutePath(), s);
        }
        // 生成单元测试resources目录
        File testResourcesDir = Tool.createPath(projectDir.getAbsolutePath(), "src", "test", "resources");

        // 生成POM
        generatePom(projectDir, project);

        {//生成java文件
            //生成 Controller
            System.out.println("生成模块:action");
            generateController(Tool.createPath(domainDir.getAbsolutePath(), "action"), project);

            // 生成 Config
            System.out.println("生成模块:config");
            generateConfig(Tool.createPath(domainDir.getAbsolutePath(), "config"), project);


            {// 模块
                for (Module module : project.getModules()) {// 业务模块
                    module.setProjectAuthor(project.getProjectAuthor());
                    module.setProjectBasePackage(project.getProjectBasePackage());
                    module.setProjectName(project.getProjectName());

                    File moduleDir = Tool.createPath(domainDir.getAbsolutePath(), "module", module.getModuleName());

                    System.out.println("生成模块:Entity");
                    generateEntity(Tool.createPath(moduleDir.getAbsolutePath(), "ent"), module);
                    System.out.println("生成模块:Mapper");
                    generateMapper(Tool.createPath(moduleDir.getAbsolutePath(), "mpr"), module);
                    System.out.println("生成模块:Manager");
                    generateManager(Tool.createPath(moduleDir.getAbsolutePath(), "mgr"), module);
                    System.out.println("生成模块:Request");
                    generateRequest(Tool.createPath(moduleDir.getAbsolutePath(), "req"), module);
                    System.out.println("生成模块:Response");
                    generateResponse(Tool.createPath(moduleDir.getAbsolutePath(), "rsp"), module);
                }

                if (project.isNeedSys()) {//生成系统模块
                    Module module = new Module();
                    module.setModuleName("system");
                    module.setProjectAuthor(project.getProjectAuthor());
                    module.setProjectBasePackage(project.getProjectBasePackage());
                    module.setProjectName(project.getProjectName());
                    File moduleDir = Tool.createPath(domainDir.getAbsolutePath(), "module", "system");
                    generateSystemModule(moduleDir, module);
                }
            }

            // frame等内容
            System.out.println("生成模块:frame");
            generateFrame(Tool.createPath(domainDir.getAbsolutePath(), "frame"), project);

            // Task
            System.out.println("生成模块:task");
            generateTask(Tool.createPath(domainDir.getAbsolutePath(), "task"), project);

            // Application
            System.out.println("生成模块:Application");
            generateApplication(Tool.createPath(domainDir.getAbsolutePath()), project);
        }

        {//生成resources文件
            System.out.println("生成模块:Resources");
            generateResources(resourcesDir, project);
            System.out.println("生成模块:Static");
            generateStatic(resourcesDir, project);
            System.out.println("生成模块:Templates");
            generateTemplates(resourcesDir, project);
        }

        {//生成Test
            System.out.println("生成模块:Test");
            generateTest(testDomainDir, project);
        }

        {//生成Test Resources
            System.out.println("生成模块:Test Resources");
            generateTestResources(testResourcesDir, project);
        }
        System.out.println("finish");
        return true;
    }


    /**
     * 生成POM.xml
     *
     * @param root
     * @param project
     */
    public void generatePom(File root, Project project) {
        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("projectName", project.getProjectName());
        ctx.put("basePackage", project.getProjectBasePackage());
        ctx.put("dataBase", project.getDatabase().toString());
        ctx.put("project", project);
        freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "pom.xml"), "SpringBoot/pom.ftl", ctx);
    }

    /**
     * 生成Controller类
     *
     * @param root
     * @param project
     */
    public void generateController(File root, Project project) {
        Tool.clear(root);
        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("basePackage", project.getProjectBasePackage());
        ctx.put("author", project.getProjectAuthor());
        ctx.put("date", new Date());
        ctx.put("modules", project.getModules());

        File control = Tool.createPath(root.getAbsolutePath(), "control");
        File screen = Tool.createPath(root.getAbsolutePath(), "screen");
        freeMarkerManager.outputTemp(Tool.createFile(control.getAbsolutePath(), "Header.java"), "SpringBoot/java/action/control/Header.java", ctx);

        {
            File ajax = Tool.createPath(root.getAbsolutePath(), "ajax");
            HashMap<String, Object> ctxss = new HashMap<String, Object>();
            ctxss.put("basePackage", project.getProjectBasePackage());
            ctxss.put("author", project.getProjectAuthor());
            ctxss.put("date", new Date());

            for (Module module : project.getModules()) {
                File m = Tool.createPath(ajax.getAbsolutePath(), module.getModuleName());
                ctxss.put("moduleName", module.getModuleName());

                for (Table table : module.getTables()) {
                    if (table.getHtml()){
                        ctxss.put("table", table);
                        freeMarkerManager.outputTemp(Tool.createFile(m.getAbsolutePath(), table.getCName() + "Ajax.java"), "SpringBoot/java/action/ajax/Ajax.java", ctxss);
                    }
                }
            }

            if (project.isNeedSys()) {//生成系统模块
                File system = Tool.createPath(ajax.getAbsolutePath(), "system");

                for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/action/ajax/system/")) {
                    freeMarkerManager.outputTemp(Tool.createFile(system.getAbsolutePath(), name), "SpringBoot/java/action/ajax/system/" + name, ctx);
                }
            }
        }

        if (project.isNeedApi()){
            File api = Tool.createPath(root.getAbsolutePath(), "api");

            for (Module module : project.getModules()) {
                File m = Tool.createPath(api.getAbsolutePath(), module.getModuleName());

                for (Table table : module.getTables()) {
                    HashMap<String, Object> ctxss = new HashMap<String, Object>();
                    ctxss.put("basePackage", project.getProjectBasePackage());
                    ctxss.put("module", module.getModuleName());
                    ctxss.put("author", project.getProjectAuthor());
                    ctxss.put("date", new Date());
                    ctxss.put("table", table);
                    freeMarkerManager.outputTemp(Tool.createFile(m.getAbsolutePath(), table.getCName() + "Api.java"), "SpringBoot/java/action/api/Api.java", ctxss);
                }
            }

            if (project.isNeedSys()) {//生成系统模块
                File system = Tool.createPath(api.getAbsolutePath(), "system");

                for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/action/api/system/")) {
                    freeMarkerManager.outputTemp(Tool.createFile(system.getAbsolutePath(), name), "SpringBoot/java/action/api/system/" + name, ctx);
                }
            }
        }
        freeMarkerManager.outputTemp(Tool.createFile(screen.getAbsolutePath(), "Index.java"), "SpringBoot/java/action/screen/Index.java", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "GlobalController.java"), "SpringBoot/java/action/GlobalController.java", ctx);
    }

    public void generateConfig(File root, Project project) {
        if (!root.exists()) {
            root.mkdirs();
        } else {
            Tool.clear(root);
        }
        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("basePackage", project.getProjectBasePackage());
        ctx.put("projectName", project.getProjectName());
        ctx.put("author", project.getProjectAuthor());
        ctx.put("date", new Date());

        //config
        freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "ActionConfig.java"), "SpringBoot/java/config/ActionConfig.java", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "CacheConfig.java"), "SpringBoot/java/config/CacheConfig.java", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "FreeMarkerConfig.java"), "SpringBoot/java/config/FreeMarkerConfig.java", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "SecurityConfig.java"), "SpringBoot/java/config/SecurityConfig.java", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "TaskConfig.java"), "SpringBoot/java/config/TaskConfig.java", ctx);
        if (project.isNeedAsync()) {
            freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "ThreadPoolConfig.java"), "SpringBoot/java/config/ThreadPoolConfig.java", ctx);
        }
        freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "WebMvcConfig.java"), "SpringBoot/java/config/WebMvcConfig.java", ctx);
        if (project.getDatabase().name().equals(DataBase.SQLite.name())) {
            freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "SQLiteConfig.java"), "SpringBoot/java/config/SQLiteConfig.java", ctx);
        }
        if (project.isNeedMoreDB()) {
            freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "MapperMainConfig.java"), "SpringBoot/java/config/MapperMainConfig.java", ctx);
            freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "MapperTwoConfig.java"), "SpringBoot/java/config/MapperTwoConfig.java", ctx);
        }
    }

    /**
     * 生成entity
     *
     * @param root
     * @param md
     */
    public void generateEntity(File root, Module md) {
        if (!root.exists()) {
            root.mkdirs();
        } else {
            Tool.clear(root);
        }

        for (Table table : md.getTables()) {
            HashMap<String, Object> ctx = new HashMap<String, Object>();
            ctx.put("tool", Tool.class);
            ctx.put("basePackage", md.getProjectBasePackage());
            ctx.put("moduleName", md.getModuleName());
            ctx.put("table", table);
            ctx.put("author", md.getProjectAuthor());
            ctx.put("date", new Date());

            File file = Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + ".java");
            freeMarkerManager.outputTemp(file, "SpringBoot/java/module/ent/entity.ftl", ctx);
        }
    }

    /**
     * 生成Mapper
     *
     * @param root
     * @param md
     */
    public void generateMapper(File root, Module md) {
        if (!root.exists()) {
            root.mkdirs();
        } else {
            Tool.clear(root);
        }
        HashMap<String, Object> ctx = new HashMap<String, Object>();

        ctx.put("tool", Tool.class);
        ctx.put("module", md);
        ctx.put("dataBase", project.getDatabase().toString());
        ctx.put("basePackage", md.getProjectBasePackage());
        ctx.put("moduleName", md.getModuleName());
        ctx.put("author", md.getProjectAuthor());
        ctx.put("date", new Date());

        for (Table table : md.getTables()) {
            ctx.put("table", table);
            if (table.getSys()) {
                freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "Mapper" + ".java"), "SpringBoot/java/module/mpr/Mapper.java", ctx);
            }else {
                freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "Mapper" + ".java"), "SpringBoot/java/module/mpr/Mapper_NSYS.java", ctx);
            }

            if (table.getSys()) {
                freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "Mapper" + ".xml"), "SpringBoot/java/module/mpr/" + project.getDatabase().name() + "_mapper.xml", ctx);
            } else {
                freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "Mapper" + ".xml"), "SpringBoot/java/module/mpr/" + project.getDatabase().name() + "_NSYS_mapper.xml", ctx);
            }
        }
    }

    public void generateManager(File root, Module md) {
        if (!root.exists()) {
            root.mkdirs();
        } else {
            Tool.clear(root);
        }
        HashMap<String, Object> ctx = new HashMap<String, Object>();

        ctx.put("tool", Tool.class);
        ctx.put("module", md);
        ctx.put("basePackage", md.getProjectBasePackage());
        ctx.put("moduleName", md.getModuleName());
        ctx.put("author", md.getProjectAuthor());
        ctx.put("date", new Date());

        for (Table table : md.getTables()) {
            ctx.put("table", table);
            freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "Manager" + ".java"), "SpringBoot/java/module/mgr/manager.ftl", ctx);
            freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "ManagerImpl" + ".java"), "SpringBoot/java/module/mgr/managerImpl.ftl", ctx);
        }
    }

    /**
     * 生成Request
     *
     * @param root
     * @param md
     */
    public void generateRequest(File root, Module md) {
        if (!root.exists()) {
            root.mkdirs();
        } else {
            Tool.clear(root);
        }

        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("tool", Tool.class);
        ctx.put("module", md);
        ctx.put("basePackage", md.getProjectBasePackage());
        ctx.put("moduleName", md.getModuleName());
        ctx.put("author", md.getProjectAuthor());
        ctx.put("date", new Date());

        for (Table table : md.getTables()) {
            ctx.put("table", table);

            if (table.getCreate()) {
                freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "CreateRequest" + ".java"), "SpringBoot/java/module/req/createRequestClass.ftl", ctx);
            }

            if (table.getDelete()) {
                freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "DeleteRequest" + ".java"), "SpringBoot/java/module/req/deleteRequestClass.ftl", ctx);
            }

            if (table.getUpdate()) {
                freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "UpdateRequest" + ".java"), "SpringBoot/java/module/req/updateRequestClass.ftl", ctx);
            }

            if (table.getFind()) {
                freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "FindRequest" + ".java"), "SpringBoot/java/module/req/findRequestClass.ftl", ctx);
            }

            if (table.getGet()) {
                freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "GetRequest" + ".java"), "SpringBoot/java/module/req/getRequestClass.ftl", ctx);
            }

            if (table.getSearch()) {
                freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "SearchRequest" + ".java"), "SpringBoot/java/module/req/searchRequestClass.ftl", ctx);
            }
        }
    }

    /**
     * 生成一般文件
     *
     * @param root
     * @param md
     */
    public void generateResponse(File root, Module md) {
        if (!root.exists()) {
            root.mkdirs();
        } else {
            Tool.clear(root);
        }

        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("tool", Tool.class);
        ctx.put("module", md);
        ctx.put("basePackage", md.getProjectBasePackage());
        ctx.put("moduleName", md.getModuleName());
        ctx.put("author", md.getProjectAuthor());
        ctx.put("date", new Date());

        for (Table table : md.getTables()) {
            ctx.put("table", table);

            if (table.getCreate()) {
                freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "CreateResponse" + ".java"), "SpringBoot/java/module/rsp/createResponseClass.ftl", ctx);
            }

            if (table.getDelete()) {
                freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "DeleteResponse" + ".java"), "SpringBoot/java/module/rsp/deleteResponseClass.ftl", ctx);
            }

            if (table.getUpdate()) {
                freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "UpdateResponse" + ".java"), "SpringBoot/java/module/rsp/updateResponseClass.ftl", ctx);
            }

            if (table.getFind()) {
                freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "FindResponse" + ".java"), "SpringBoot/java/module/rsp/findResponseClass.ftl", ctx);
            }

            if (table.getGet()) {
                freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "GetResponse" + ".java"), "SpringBoot/java/module/rsp/getResponseClass.ftl", ctx);
            }

            if (table.getSearch()) {
                freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "SearchResponse" + ".java"), "SpringBoot/java/module/rsp/searchResponseClass.ftl", ctx);
            }
        }
    }

    public void generateSystemModule(File root, Module md) {
        File ent = Tool.createPath(root.getAbsolutePath(), "ent");
        File mpr = Tool.createPath(root.getAbsolutePath(), "mpr");
        File mgr = Tool.createPath(root.getAbsolutePath(), "mgr");
        File req = Tool.createPath(root.getAbsolutePath(), "req");
        File rsp = Tool.createPath(root.getAbsolutePath(), "rsp");

        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("basePackage", md.getProjectBasePackage());
        ctx.put("moduleName", md.getModuleName());
        ctx.put("author", md.getProjectAuthor());
        ctx.put("date", new Date());
        ctx.put("dataBase", project.getDatabase().toString());

        for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/module/system/ent/")) {
            freeMarkerManager.outputTemp(Tool.createFile(ent.getAbsolutePath(), name), "SpringBoot/java/module/system/ent/" + name, ctx);
        }

        for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/module/system/mgr/")) {
            freeMarkerManager.outputTemp(Tool.createFile(mgr.getAbsolutePath(), name), "SpringBoot/java/module/system/mgr/" + name, ctx);
        }

        for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/module/system/mpr/")) {
            if (name.endsWith(".java")) {
                freeMarkerManager.outputTemp(Tool.createFile(mpr.getAbsolutePath(), name), "SpringBoot/java/module/system/mpr/" + name, ctx);
            } else if (name.contains(project.getDatabase().name())) {
                //todo dateBase调试
//                freeMarkerManager.outputTemp(Tool.createFile(mpr.getAbsolutePath(), name), "SpringBoot/java/module/system/mpr/" + name, ctx);
                freeMarkerManager.outputTemp(Tool.createFile(mpr.getAbsolutePath(), name.replaceAll(project.getDatabase().name() + "_", "")), "SpringBoot/java/module/system/mpr/" + name, ctx);
            }
        }

        for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/module/system/req/")) {
            freeMarkerManager.outputTemp(Tool.createFile(req.getAbsolutePath(), name), "SpringBoot/java/module/system/req/" + name, ctx);
        }

        for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/module/system/rsp/")) {
            freeMarkerManager.outputTemp(Tool.createFile(rsp.getAbsolutePath(), name), "SpringBoot/java/module/system/rsp/" + name, ctx);
        }
    }

    /**
     * 生成frame类
     *
     * @param root
     * @param project
     */
    public void generateFrame(File root, Project project) {
        if (!root.exists()) {
            root.mkdirs();
        } else {
            Tool.clear(root);
        }
        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("basePackage", project.getProjectBasePackage());
        ctx.put("moduleName", project.getProjectName());
        ctx.put("timestamp", new Date().getTime());

        File auth = Tool.createPath(root.getAbsolutePath(), "auth");
        File base = Tool.createPath(root.getAbsolutePath(), "base");
        File excel = Tool.createPath(root.getAbsolutePath(), "excel");
        File excelannotation = Tool.createPath(excel.getAbsolutePath(), "annotation");
        File excelconverter = Tool.createPath(excel.getAbsolutePath(), "converter");
        File exception = Tool.createPath(excel.getAbsolutePath(), "exception");
        File excelhandler = Tool.createPath(excel.getAbsolutePath(), "handler");
        File excellistener = Tool.createPath(excel.getAbsolutePath(), "listener");
        File schedule = Tool.createPath(root.getAbsolutePath(), "schedule");
        File utils = Tool.createPath(root.getAbsolutePath(), "utils");
        File validation = Tool.createPath(root.getAbsolutePath(), "validation");

        //auth
        for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/frame/auth/")) {
            freeMarkerManager.outputTemp(Tool.createFile(auth.getAbsolutePath(), name), "SpringBoot/java/frame/auth/" + name, ctx);
        }

        //base
        for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/frame/base/")) {
            freeMarkerManager.outputTemp(Tool.createFile(base.getAbsolutePath(), name), "SpringBoot/java/frame/base/" + name, ctx);
        }

        //excel
        for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/frame/excel/")) {
            freeMarkerManager.outputTemp(Tool.createFile(excel.getAbsolutePath(), name), "SpringBoot/java/frame/excel/" + name, ctx);
        }
        for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/frame/excel/annotation/")) {
            freeMarkerManager.outputTemp(Tool.createFile(excelannotation.getAbsolutePath(), name), "SpringBoot/java/frame/excel/annotation/" + name, ctx);
        }
        for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/frame/excel/converter/")) {
            freeMarkerManager.outputTemp(Tool.createFile(excelconverter.getAbsolutePath(), name), "SpringBoot/java/frame/excel/converter/" + name, ctx);
        }
        for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/frame/excel/exception/")) {
            freeMarkerManager.outputTemp(Tool.createFile(exception.getAbsolutePath(), name), "SpringBoot/java/frame/excel/exception/" + name, ctx);
        }
        for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/frame/excel/handler/")) {
            freeMarkerManager.outputTemp(Tool.createFile(excelhandler.getAbsolutePath(), name), "SpringBoot/java/frame/excel/handler/" + name, ctx);
        }
        for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/frame/excel/listener/")) {
            freeMarkerManager.outputTemp(Tool.createFile(excellistener.getAbsolutePath(), name), "SpringBoot/java/frame/excel/listener/" + name, ctx);
        }

        //schedule
        for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/frame/schedule/")) {
            freeMarkerManager.outputTemp(Tool.createFile(schedule.getAbsolutePath(), name), "SpringBoot/java/frame/schedule/" + name, ctx);
        }

        //utils
        for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/frame/utils/")) {
            ArrayList<String> filters = new ArrayList<>();
            filters.add("MailUtil.java");

            if (filters.contains(name)) {
                if (project.isNeedEMail()) {
                    freeMarkerManager.outputTemp(Tool.createFile(utils.getAbsolutePath(), name), "SpringBoot/java/frame/utils/" + name, ctx);
                }
            } else {
                freeMarkerManager.outputTemp(Tool.createFile(utils.getAbsolutePath(), name), "SpringBoot/java/frame/utils/" + name, ctx);
            }
        }

        //validation
        for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/frame/validation/")) {
            freeMarkerManager.outputTemp(Tool.createFile(validation.getAbsolutePath(), name), "SpringBoot/java/frame/validation/" + name, ctx);
        }
    }


    /**
     * 生成frame类
     *
     * @param root
     * @param project
     */
    public void generateTask(File root, Project project) {
        if (!root.exists()) {
            root.mkdirs();
        } else {
            Tool.clear(root);
        }
        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("basePackage", project.getProjectBasePackage());
        ctx.put("moduleName", project.getProjectName());
        ctx.put("timestamp", new Date().getTime());

        //task
        for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/java/task/")) {
            freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), name), "SpringBoot/java/task/" + name, ctx);
        }
    }

    /**
     * 生成base类
     *
     * @param root
     * @param project
     */
    public void generateApplication(File root, Project project) {
        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("basePackage", project.getProjectBasePackage());
        ctx.put("moduleName", project.getProjectName());
        ctx.put("project", project);
        ctx.put("timestamp", new Date().getTime());
        freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "Application.java"), "SpringBoot/java/Application.ftl", ctx);
    }

    /**
     * 生成properties
     *
     * @param root
     * @param project
     */
    public void generateResources(File root, Project project) {
        HashMap<String, Object> ctx = new HashMap<String, Object>();

        ctx.put("basePackage", project.getProjectBasePackage());
        ctx.put("tool", Tool.class);
        ctx.put("dataBase", project.getDatabase().toString());
        ctx.put("author", project.getProjectAuthor());
        ctx.put("dBmapper", dBmapper);
        ctx.put("date", new Date());
        ctx.put("author", project.getProjectAuthor());
        ctx.put("projectName", project.getProjectName());
        ctx.put("project", project);
        freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "start-dev.bat"), "SpringBoot/resources/start-dev.bat", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "start-prod.bat"), "SpringBoot/resources/start-prod.bat", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "application.properties"), "SpringBoot/resources/application.ftl", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "application-dev.properties"), "SpringBoot/resources/application-dev.ftl", ctx);
        freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "application-prod.properties"), "SpringBoot/resources/application-prod.ftl", ctx);
        Tool.outputResource("SpringBoot/resources/logback-spring-dev.xml", Tool.createFile(root.getAbsolutePath(), "logback-spring-dev.xml"));
        Tool.outputResource("SpringBoot/resources/logback-spring-prod.xml", Tool.createFile(root.getAbsolutePath(), "logback-spring-prod.xml"));

        File dbtool = Tool.createPath(root.getAbsolutePath(), "dbtool");
        {
            XmlManager xmlManager = ManagerFactory.getXmlManager();
            xmlManager.saveAs(dbtool, project);
        }

        for (Module module : project.getModules()) {
            ctx.put("moduleName", module.getModuleName());
            ctx.put("module", module);
            File tableDir = Tool.createPath(dbtool.getAbsolutePath(), module.getModuleName() + "_table");
            for (Table table : module.getTables()) {
                ctx.put("table", table);
                freeMarkerManager.outputTemp(Tool.createFile(tableDir.getAbsolutePath(), project.getDatabase().name() + "_" + table.getTableName() + ".sql"), "SpringBoot/resources/dbtool/table.ftl", ctx);
            }
            freeMarkerManager.outputTemp(Tool.createFile(tableDir.getAbsolutePath(), project.getDatabase().name() + "_ALL_TABLE" + ".sql"), "SpringBoot/resources/dbtool/tableAll.ftl", ctx);
        }

        if (project.isNeedSys()) {//生成系统模块
            File system = Tool.createPath(dbtool.getAbsolutePath(), "system_table");

            for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/resources/dbtool/system/")) {
                if (name.contains(project.getDatabase().name())) {
                    freeMarkerManager.outputTemp(Tool.createFile(system.getAbsolutePath(), name), "SpringBoot/resources/dbtool/system/" + name, ctx);
                }
            }
        }

//        if (DataBase.Oracle.name().equals(project.getDatabase().name())) {
//            File lib = Tool.createPath(root.getAbsolutePath(), "lib");
//            Tool.outputResource("SpringBoot/resources/lib/ojdbc7-12.1.0.2.jar", Tool.createFile(lib.getAbsolutePath(), "ojdbc7-12.1.0.2.jar"));
//        }

        if (DataBase.SQLite.name().equals(project.getDatabase().name())) {
            File dbFile = Tool.createFile(root.getAbsolutePath(), project.getProjectName() + ".db3");
            Connection connection = null;
            Statement statement = null;
            try {
                Class.forName("org.sqlite.JDBC");
                connection = DriverManager.getConnection("jdbc:sqlite:" + dbFile.getAbsolutePath());

                for (File fileModule : dbtool.listFiles()) {
                    if (!fileModule.isDirectory()) {
                        continue;
                    }
                    for (File file : fileModule.listFiles()) {
                        if (file.getName().startsWith("SQLite_") && !file.getName().startsWith("SQLite_ALL_") && file.getName().endsWith(".sql")) {
                            statement = connection.createStatement();
                            String sql = FileUtil.readFileToString(file);
                            statement.execute(sql);
                            statement.close();
                        }
                    }
                }
            } catch (ClassNotFoundException | SQLException | IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (statement != null) statement.close();
                    if (connection != null) connection.close();
                } catch (Exception e) {

                }
            }
        }
    }

    public void generateTestResources(File root, Project project) {
        HashMap<String, Object> ctx = new HashMap<String, Object>();

        ctx.put("basePackage", project.getProjectBasePackage());
        ctx.put("projectName", project.getProjectName());
        ctx.put("tool", Tool.class);
        ctx.put("dataBase", project.getDatabase().toString());
        ctx.put("author", project.getProjectAuthor());
        ctx.put("dBmapper", dBmapper);
        ctx.put("date", new Date());
        ctx.put("project", project);
        freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "application.properties"), "SpringBoot/test/application.ftl", ctx);
        Tool.outputResource("SpringBoot/test/logback-spring.xml", Tool.createFile(root.getAbsolutePath(), "logback-spring.xml"));
    }

    /**
     * 生成static
     *
     * @param root
     * @param project
     */
    public void generateStatic(File root, Project project) {

        HashMap<String, Object> ctx = new HashMap<String, Object>();
        ctx.put("basePackage", project.getProjectBasePackage());
        ctx.put("tool", Tool.class);
        ctx.put("author", project.getProjectAuthor());
        ctx.put("date", new Date());
        ctx.put("modules", project.getModules());

        File static_ = Tool.createPath(root.getAbsolutePath(), "static");
        File css = Tool.createPath(static_.getAbsolutePath(), "css");
        File img = Tool.createPath(static_.getAbsolutePath(), "img");
        File dist = Tool.createPath(static_.getAbsolutePath(), "dist");

        {
            Tool.outputResource("SpringBoot/resources/static/favicon.ico", Tool.createFile(static_.getAbsolutePath(), "favicon.ico"));
        }

        {//css文件
            freeMarkerManager.outputTemp(Tool.createFile(css.getAbsolutePath(), "base.css"), "SpringBoot/resources/static/css/base.css", ctx);
        }

        {//img
            Tool.outputResource("SpringBoot/resources/static/img/logo.png", Tool.createFile(img.getAbsolutePath(), "logo.png"));
        }

        {//dist文件
            //jquery + vue + vue-router + axios
            Tool.outputResource("SpringBoot/resources/static/dist/lib.min.js", Tool.createFile(dist.getAbsolutePath(), "lib.min.js"));

            //element-ui
            Tool.outputResource("SpringBoot/resources/static/dist/index.min.js", Tool.createFile(dist.getAbsolutePath(), "index.min.js"));
            Tool.outputResource("SpringBoot/resources/static/dist/index.min.css", Tool.createFile(dist.getAbsolutePath(), "index.min.css"));

            File fonts = Tool.createPath(dist.getAbsolutePath(), "fonts");
            Tool.outputResource("SpringBoot/resources/static/dist/fonts/w-e-icon.woff", Tool.createFile(fonts.getAbsolutePath(), "w-e-icon.woff"));
            Tool.outputResource("SpringBoot/resources/static/dist/fonts/element-icons.woff", Tool.createFile(fonts.getAbsolutePath(), "element-icons.woff"));
            Tool.outputResource("SpringBoot/resources/static/dist/fonts/element-icons.ttf", Tool.createFile(fonts.getAbsolutePath(), "element-icons.ttf"));

        }
    }

    /**
     * 生成static
     *
     * @param root
     * @param project
     */
    public void generateTemplates(File root, Project project) {
        {//生成
            File templates = Tool.createPath(root.getAbsolutePath(), "templates");
            File control = Tool.createPath(templates.getAbsolutePath(), "control");
            File layout = Tool.createPath(templates.getAbsolutePath(), "layout");
            File screen = Tool.createPath(templates.getAbsolutePath(), "screen");
            Tool.outputResource("SpringBoot/resources/templates/control/nav.ftl", Tool.createFile(control.getAbsolutePath(), "nav.ftl"));
            Tool.outputResource("SpringBoot/resources/templates/control/macro.ftl", Tool.createFile(control.getAbsolutePath(), "macro.ftl"));
            Tool.outputResource("SpringBoot/resources/templates/layout/default.ftl", Tool.createFile(layout.getAbsolutePath(), "default.ftl"));
            Tool.outputResource("SpringBoot/resources/templates/screen/home.ftl", Tool.createFile(screen.getAbsolutePath(), "home.ftl"));
            Tool.outputResource("SpringBoot/resources/templates/screen/login.ftl", Tool.createFile(screen.getAbsolutePath(), "login.ftl"));
            Tool.outputResource("SpringBoot/resources/templates/403.ftl", Tool.createFile(templates.getAbsolutePath(), "403.ftl"));
            Tool.outputResource("SpringBoot/resources/templates/404.ftl", Tool.createFile(templates.getAbsolutePath(), "404.ftl"));
            Tool.outputResource("SpringBoot/resources/templates/500.ftl", Tool.createFile(templates.getAbsolutePath(), "500.ftl"));

            {
                HashMap<String, Object> ctx = new HashMap<String, Object>();
                ctx.put("basePackage", project.getProjectBasePackage());
                ctx.put("tool", new Tool());
                ctx.put("author", project.getProjectAuthor());
                ctx.put("date", new Date());
                ctx.put("modules", project.getModules());
                ctx.put("sysMD", project.isNeedSys());
                freeMarkerManager.outputTemp(Tool.createFile(screen.getAbsolutePath(), "index.ftl"), "SpringBoot/resources/templates/screen/index.ftl", ctx);

            }

            for (Module mo : project.getModules()) {
                for (Table table : mo.getTables()) {
                    if (table.getHtml()) {
                        File module = Tool.createPath(screen.getAbsolutePath(), mo.getModuleName());
                        HashMap<String, Object> ctx = new HashMap<String, Object>();
                        ctx.put("basePackage", project.getProjectBasePackage());
                        ctx.put("tool", Tool.class);
                        ctx.put("author", project.getProjectAuthor());
                        ctx.put("date", new Date());
                        ctx.put("table", table);
                        ctx.put("module", module.getName());
                        ctx.put("fields", table.getFields());
                        File file = Tool.createFile(module.getAbsolutePath(), table.getFName() + ".ftl");
                        freeMarkerManager.outputTemp(file, "SpringBoot/resources/templates/screen/module/mgr.ftl", ctx);
                    }
                }
            }

            if (project.isNeedSys()) {//生成系统模块
                File system = Tool.createPath(screen.getAbsolutePath(), "system");
                for (String name : ResourceUtil.getResourceFiles("/modules/SpringBoot/resources/templates/screen/module/system/")) {
                    Tool.outputResource("SpringBoot/resources/templates/screen/module/system/" + name, Tool.createFile(system.getAbsolutePath(), name));
                }
            }
        }
    }

    public void generateTest(File root, Project project) {

        {
            File config = Tool.createPath(root.getAbsolutePath(), "config");
            config.mkdirs();
            HashMap<String, Object> ctx = new HashMap<String, Object>();
            ctx.put("tool", Tool.class);
            ctx.put("basePackage", project.getProjectBasePackage());
            ctx.put("moduleName", project.getProjectName());
            ctx.put("author", project.getProjectAuthor());
            ctx.put("date", new Date());
            File file = Tool.createFile(config.getAbsolutePath(), "TestConfig" + ".java");
            freeMarkerManager.outputTemp(file, "SpringBoot/test/TestConfig.ftl", ctx);
        }

        {
            HashMap<String, Object> ctx = new HashMap<String, Object>();
            ctx.put("tool", Tool.class);
            ctx.put("basePackage", project.getProjectBasePackage());
            ctx.put("moduleName", project.getProjectName());
            ctx.put("author", project.getProjectAuthor());
            ctx.put("date", new Date());
            File file = Tool.createFile(root.getAbsolutePath(), "UtilTest" + ".java");
            freeMarkerManager.outputTemp(file, "SpringBoot/test/UtilTest.java", ctx);
        }

        for (Module md : project.getModules()) {
            File module = Tool.createPath(root.getAbsolutePath(), md.getModuleName());

            for (Table table : md.getTables()) {
                HashMap<String, Object> ctx = new HashMap<String, Object>();

                ctx.put("tool", Tool.class);
                ctx.put("module", md);
                ctx.put("basePackage", md.getProjectBasePackage());
                ctx.put("moduleName", md.getModuleName());
                ctx.put("table", table);
                ctx.put("author", md.getProjectAuthor());
                ctx.put("date", new Date());

                File file = Tool.createFile(module.getAbsolutePath(), Tool.ABB2Abb(table.getTableName()) + "Test" + ".java");
                freeMarkerManager.outputTemp(file, "SpringBoot/test/test.ftl", ctx);
            }
        }

        if (project.isNeedSys()) {//生成系统模块
            HashMap<String, Object> ctx = new HashMap<String, Object>();
            ctx.put("tool", Tool.class);
            ctx.put("basePackage", project.getProjectBasePackage());
            ctx.put("moduleName", project.getProjectName());
            ctx.put("author", project.getProjectAuthor());
            ctx.put("date", new Date());
            File system = Tool.createPath(root.getAbsolutePath(), "system");

            for (String apiFile : ResourceUtil.getResourceFiles("/modules/SpringBoot/test/system/")) {
                freeMarkerManager.outputTemp(Tool.createFile(system.getAbsolutePath(), apiFile), "SpringBoot/test/system/" + apiFile, ctx);
            }
        }

        {//数据初始化
            HashMap<String, Object> ctx = new HashMap<String, Object>();
            ctx.put("tool", Tool.class);
            ctx.put("basePackage", project.getProjectBasePackage());
            ctx.put("moduleName", project.getProjectName());
            ctx.put("author", project.getProjectAuthor());
            ctx.put("date", new Date());
            ctx.put("project", project);

            freeMarkerManager.outputTemp(Tool.createFile(root.getAbsolutePath(), "DataInit.java"), "SpringBoot/test/DataInit.java", ctx);
        }
    }
}
