package cn.reghao.tnb.oss.store.tomcat;

import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.startup.Tomcat;
import org.springframework.stereotype.Component;

import java.io.File;

/**
 * @author reghao
 * @date 2024-12-19 11:28:16
 */
@Component
public class TomcatStarter implements Runnable {
    private final int port;
    private final String baseDir;
    private final Tomcat tomcat;
    private final GlobalServlet globalServlet;

    public TomcatStarter(GlobalServlet globalServlet) {
        this.port = 8080;
        this.baseDir = String.format("/opt/tmp/tomcat%s", port);
        this.tomcat = new Tomcat();
        this.globalServlet = globalServlet;
    }

    public void run() {
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                    try {
                        tomcat.destroy();
                    } catch (LifecycleException e) {
                        e.printStackTrace();
                    }
                })
        );
        try {
            init();
        } catch (LifecycleException e) {
            e.printStackTrace();
        }
    }

    private void configDir(String baseDir) {
        File root = new File(baseDir);
        if (!root.isDirectory() && !root.mkdirs()) {
            throw new RuntimeException("请提供Tomcat工作目录");
        }
        String path4root = root.getAbsolutePath();
        tomcat.setBaseDir(path4root);
        File webapps = new File(path4root + "/webapps");
        if (!webapps.isDirectory() && !webapps.mkdirs()) {
            throw new RuntimeException("无法创建webapps目录");
        }
    }

    private void init() throws LifecycleException {
        // 设置工作目录
        tomcat.setBaseDir(baseDir);
        configDir(baseDir);

        // 主机名, 将生成目录: {工作目录}/work/Tomcat/{主机名}/ROOT
        tomcat.setHostname("localhost");
        System.out.println("工作目录: " + tomcat.getServer().getCatalinaBase().getAbsolutePath());

        tomcat.setPort(port);
        Connector conn = tomcat.getConnector(); // Tomcat 9.0 必须调用 Tomcat#getConnector() 方法之后才会监听端口
        System.out.println("连接器设置完成: " + conn);

        // contextPath要使用的上下文映射，""表示根上下文
        // docBase上下文的基础目录，用于静态文件。相对于服务器主目录必须存在 ({主目录}/webapps/{docBase})
        String docBase = "";
        Context ctx = tomcat.addContext("", /*{webapps}/~*/ null);

        Tomcat.addServlet(ctx, "globalServlet", globalServlet);
        ctx.addServletMappingDecoded("/", "globalServlet");

        tomcat.start();
        System.out.println("tomcat 已启动");
        tomcat.getServer().await();
    }
}
