package cn.joylau.code;

import org.apache.maven.plugin.AbstractMojo;
import org.codehaus.plexus.util.FileUtils;
import org.codehaus.plexus.util.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.dom4j.io.XMLWriter;

import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;

/**
 * @goal make-win-service
 * @phase package
 */
public class WindowsServiceMojo extends AbstractMojo {
    /**
     * @parameter property="project.build.directory"
     * @required
     */
    private File targetDir;

    /**
     * @parameter property="project.basedir"
     * @required
     * @readonly
     */
    private File baseDir;
    /**
     * @parameter property="project.build.sourceDirectory"
     * @required
     * @readonly
     */
    private File sourceDir;
    /**
     * @parameter property="project.build.testSourceDirectory"
     * @required
     * @readonly
     */
    private File testSourceDir;

    /** @parameter property="project.groupId"
     *  @required
     */
    private String groupId;

    /** @parameter property="project.artifactId"
     *  @required
     */
    private String artifactId;

    /** @parameter property="project.version"
     *  @required
     */
    private String version;

    /** @parameter property="project.description"
     */
    private String description;

    /**
     * @parameter property="arguments"
     */
    private String[] arguments;

    /**
     * @parameter property="vmOptions"
     */
    private String vmOptions;

    /**
     * @parameter property="programArguments"
     */
    private String programArguments;


    private static final String EXE_FILE_URL = "http://image.joylau.cn/plugins/joylau-springboot-daemon-windows/service.exe";
    private static final String XML_FILE_URL = "http://image.joylau.cn/plugins/joylau-springboot-daemon-windows/service.xml";
    private static final String CONFIG_FILE_URL = "http://image.joylau.cn/plugins/joylau-springboot-daemon-windows/service.exe.config";
    private static final String README_FILE_URL = "http://image.joylau.cn/plugins/joylau-springboot-daemon-windows/reamdme.txt";

    public void execute() {
        getLog().info("开始生成 Windows Service 必要的文件");
        try {
            /*创建文件夹*/
            File distDir = new File(targetDir, File.separator + "dist");
            if (distDir.exists()) {
                try {
                    FileUtils.deleteDirectory(distDir);
                } catch (IOException e) {
                    getLog().error("删除目录失败!请检查文件是否在使用");
                    e.printStackTrace();
                }
            }
            FileUtils.mkdir(distDir.getPath());
            File logDir = new File(distDir,File.separator + "logs");
            FileUtils.mkdir(logDir.getPath());

            /*下载文件*/
            FileUtils.copyURLToFile(new URL(README_FILE_URL), new File(distDir, File.separator + "readme.txt"));
            FileUtils.copyURLToFile(new URL(XML_FILE_URL), new File(distDir,File.separator+getJarPrefixName()+".xml"));
            FileUtils.copyURLToFile(new URL(EXE_FILE_URL), new File(distDir,File.separator+getJarPrefixName()+".exe"));
            FileUtils.copyURLToFile(new URL(CONFIG_FILE_URL), new File(distDir,File.separator+getJarPrefixName()+".exe.config"));
            FileUtils.copyFile(new File(targetDir.getPath() + File.separator + getJarName()), new File(distDir, File
                    .separator + getJarName()));

            convert(new File(distDir.getPath()+File.separator+getJarPrefixName()+".xml"));
            createBat(distDir, "install.bat", "install");
            createBat(distDir, "uninstall.bat", "uninstall");
            createBat(distDir, "start.bat", "start");
            createBat(distDir, "stop.bat", "stop");
            createBat(distDir, "restart.bat", "restart");

            getLog().info("正在制作压缩包....");
            String zipDir = targetDir.getPath() + File.separator + getJarPrefixName() + ".zip";
            ZipUtils.zip(distDir.getPath(), zipDir);

            getLog().info("正在清除临时文件....");
            FileUtils.deleteDirectory(distDir);
            getLog().info("制作完成,文件:" + zipDir);
        } catch (Exception e) {
            getLog().error("制作Windows Service 失败:",e);
        }
    }


    /**
     * 属性转化
     * @param xmlFile xml文件
     */
    private void convert(File xmlFile){
        SAXReader reader = new SAXReader();
        try {
            Document document = reader.read(xmlFile);
            Element root = document.getRootElement();
            root.element("id").setText(artifactId);
            root.element("name").setText(getJarPrefixName());
            root.element("description").setText(null == description ? "暂无描述" : description);
            if (arguments.length > 0) {
                getLog().warn("arguments 参数设置已过期,参数配置可能不会生效,请分别设置 vmOptions 参数 和 programArguments 参数 [https://github.com/JoyLau/joylau-springboot-daemon-windows]");
            }
            String vm_options = StringUtils.isEmpty(vmOptions) ? " " : " " + vmOptions + " ";
            String program_arguments = StringUtils.isEmpty(programArguments) ? "" : " " + programArguments;
            root.element("arguments").setText(vm_options + "-jar " + getJarName() +  program_arguments);
            saveXML(document,xmlFile);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 保存 XML 文件
     * @param document 文档
     * @param xmlFile xml文件
     */
    private void saveXML(Document document, File xmlFile){
        try {
            XMLWriter writer = new XMLWriter(new OutputStreamWriter(new FileOutputStream(xmlFile), StandardCharsets.UTF_8));
            writer.write(document);
            writer.flush();
            writer.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @param outDri   输出目录
     * @param fileName 文件名
     * @param text     命令文本
     */
    private void createBat(File outDri, String fileName, String text) {
        if (!outDri.exists()) {
            FileUtils.mkdir(outDri.getPath());
        }
        File file = new File(outDri, fileName);
        try (FileWriter w = new FileWriter(file)) {
            w.write("@echo off\n" +
                    "%1 mshta vbscript:CreateObject(\"Shell.Application\").ShellExecute(\"cmd.exe\",\"/c %~s0 ::\",\"\",\"runas\",1)(window.close)&&exit\n" +
                    "%~dp0" + getJarPrefixName() + ".exe " + text + "\n" +
                    "echo The " + getJarPrefixName() + " service current state:\n" +
                    "%~dp0" + getJarPrefixName() + ".exe status\n" +
                    "pause");
        } catch (IOException e) {
//            throw new MojoExecutionException("Error creating file ", e);
            e.printStackTrace();
        }
        // ignore
    }

    /**
     * 获取jar包前缀名
     * @return String
     */
    private String getJarPrefixName() {
        return artifactId + "-" + version;
    }

    /**
     * 获取jar包全名
     * @return String
     */
    private String getJarName() {
        return getJarPrefixName() + ".jar";
    }
}