package com.yihu.hos.tenant.service;

import com.yihu.hos.tenant.model.DBInfoModel;
import org.springframework.stereotype.Component;

import java.io.*;

/**
 * MYSQL数据库导出/导入 (测试版）
 *
 * @author HZY
 * @vsrsion 1.0
 * Created at 2017/1/18.
 */
@Component
public class MySqlImportAndExport {

//    public static void main(String args[]) throws Exception {
//        DBInfoModel db = new DBInfoModel();
//        db.setUserName("root");
//        db.setPassword("xmjkzl");
//        db.setHost("172.19.103.57");
//        db.setPort(3306);
//        db.setDbName("ccc");
////
////        db.setUserName("root");
////        db.setPassword("123");
////        db.setHost("192.168.131.119");
////        db.setPort(3306);
////        db.setDbName("learn");
//        MySqlImportAndExport mySqlImportAndExport = new MySqlImportAndExport();
////      MySqlImportAndExport.export(db,"e://learn_copy.sql");//这里简单点异常我就直接往上抛
//        mySqlImportAndExport.importSql(db,"e://learn.sql");
//    }

    /**
     * 根据属性文件的配置导出指定位置的指定数据库到指定位置
     *
     * @param db         数据库信息
     * @param exportPath 导出的sql文件路径
     * @throws IOException
     */
    public void export(DBInfoModel db, String exportPath) throws Exception {
        Runtime runtime = Runtime.getRuntime();
//        String mysqlPath = getMysqlPath(db,runtime);
//        System.out.println("安装地址："+mysqlPath);
        String command = getExportCommand(db, exportPath);
        System.out.println(command);
        runtime.exec(command);//这里简单一点异常我就直接往上抛
    }


    /**
     * 在命令窗口进行mysql的数据库导入一般分三步走：
     * 第一步是登到到mysql； mysql -uusername -ppassword -hhost -Pport -DdatabaseName;如果在登录的时候指定了数据库名则会
     * 直接转向该数据库，这样就可以跳过第二步，直接第三步；
     * 第二步是切换到导入的目标数据库；use 数据库名；
     * 第三步是开始从目标文件导入数据到目标数据库；source importPath；
     *
     * @param db         数据库信息
     * @param importPath 导入的sql文件路径
     * @throws IOException
     */
    public String importSql(DBInfoModel db, String importPath) {
        Runtime runtime = Runtime.getRuntime();
        //因为在命令窗口进行mysql数据库的导入一般分三步走，所以所执行的命令将以字符串数组的形式出现
        String cmdarray[] = getImportCommand(db, importPath);//根据属性文件的配置获取数据库导入所需的命令，组成一个数组
        try {
            //runtime.exec(cmdarray);//这里也是简单的直接抛出异常
            Process process = runtime.exec(cmdarray[0]);
            Thread.sleep(300);//没睡眠的话会出现问题：出现异常的时候不会被捕获；
            //执行了第一条命令以后已经登录到mysql了，所以之后就是利用mysql的命令窗口
            //进程执行后面的代码
            OutputStream os = process.getOutputStream();
            OutputStreamWriter writer = new OutputStreamWriter(os);
            //命令1和命令2要放在一起执行
            writer.write(cmdarray[1] + "\r\n" + cmdarray[2]);
            writer.flush();
            writer.close();
            os.close();
        } catch (IOException e) {
            e.printStackTrace();
            return e.toString();
        } catch (Exception e) {
            e.printStackTrace();
            return e.toString();
        }
        return null;

    }

    /**
     * 生成导出sql命令
     * 在拼装命令语句的时候有一点是需要注意的：一般我们在命令窗口直接使用命令来
     * 进行导出的时候可以简单使用“>”来表示导出到什么地方，即mysqldump -uusername -ppassword databaseName > exportPath，
     * 但在Java中这样写是不行的，它需要你用-r明确的指出导出到什么地方，如：
     * mysqldump -uusername -ppassword databaseName -r exportPath。（经验证> 也是可以）
     *
     * @param exportPath 输出路径
     * @return
     */
    public String getExportCommand(DBInfoModel db, String exportPath) {
        StringBuffer command = new StringBuffer();
        //window需要进入mysql安装的bin目录
        if (System.getProperties().getProperty("os.name").contains("Windows")) {
            System.out.println("===========操作系统是:" + System.getProperties().getProperty("os.name"));
            //TODO 获取mysql的安装路径
            String mysqlPath = "C:\\Program Files\\MySQL\\MySQL Server 5.6\\bin";
            String cmd = "cmd /c C: && cd " + mysqlPath + " && ";
            command.append(cmd);
        }
        command.append("mysqldump -u").append(db.getUserName()).append(" -p").append(db.getPassword())//密码是用的小p，而端口是用的大P。
                .append(" -h").append(db.getHost()).append(" -P").append(db.getPort()).append(" ").append(db.getDbName()).append(" > ").append(exportPath);
        return command.toString();
    }


    /**
     * 生成导入文件的命令行
     * 如果在登录的时候指定了数据库名则会
     * 直接转向该数据库，这样就可以跳过第二步，直接第三步；
     *
     * @param db         数据库信息
     * @param importPath 导入的sql文件路径
     * @return
     */
    public String[] getImportCommand(DBInfoModel db, String importPath) {
        //第一步，获取登录命令语句

        StringBuffer loginCommand = new StringBuffer();
        //window需要进入mysql安装的bin目录
        if (System.getProperties().getProperty("os.name").contains("Windows")) {
            System.out.println("===========操作系统是:" + System.getProperties().getProperty("os.name"));
            //TODO 获取mysql的安装路径
            String mysqlPath = "C:\\Program Files\\MySQL\\MySQL Server 5.6\\bin ";
            String cmd = "cmd /c C: && cd " + mysqlPath + " && ";
            loginCommand.append(cmd);
        }
        loginCommand.append("mysql --default-character-set=utf8 -u").append(db.getUserName()).append(" -p").append(db.getPassword()).append(" -h").append(db.getHost())
                .append(" -P").append(db.getPort());
        //第二步，创建数据库 获取切换数据库到目标数据库的命令语句
        String switchCommand = new StringBuffer("CREATE DATABASE " + db.getDbName() + "; use ").append(db.getDbName()).append(";").toString();
        //第三步，获取导入的命令语句
        String importCommand = new StringBuffer("source ").append(importPath).toString();
        //需要返回的命令语句数组
        String[] commands = new String[]{loginCommand.toString(), switchCommand, importCommand};
        return commands;
    }

    public String getMysqlPath(DBInfoModel db, Runtime runtime) throws Exception {
        //第一步，获取登录命令语句

        StringBuffer loginCommand = new StringBuffer();
        //window需要进入mysql安装的bin目录
        if (System.getProperties().getProperty("os.name").contains("Windows")) {
            System.out.println("===========操作系统是:" + System.getProperties().getProperty("os.name"));
            //TODO 获取mysql的安装路径
            String mysqlPath = "C:\\Program Files\\MySQL\\MySQL Server 5.6\\bin ";
            String cmd = "cmd /c C: && cd " + mysqlPath + " && ";
            loginCommand.append(cmd);
        }
        loginCommand.append("mysql -u").append(db.getUserName()).append(" -p").append(db.getPassword()).append(" -h").append(db.getHost())
                .append(" -P").append(db.getPort());

        Process process = runtime.exec(loginCommand.toString());
        //执行了第一条命令以后已经登录到mysql了，所以之后就是利用mysql的命令窗口
        //进程执行后面的代码
        OutputStream os = process.getOutputStream();
        OutputStreamWriter writer = new OutputStreamWriter(os);
        //命令1和命令2要放在一起执行
        writer.write("select @@basedir as basePath from dual" + "\r\n");
        writer.flush();
        writer.close();
        //需要返回的命令语句数组
        InputStream is = process.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        String line;
        while ((line = reader.readLine()) != null) {
            System.out.println(line);
        }
        process.waitFor();
        is.close();
        reader.close();
        process.destroy();
        os.close();

        return "";
    }

}
