package com.zi.mwms.solution;

import java.io.*;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.util.Arrays;
import java.util.PriorityQueue;

import com.cim.idm.framework.autoconfigure.ZidmPlatformLicenseAutoConfiguration;
import de.codecentric.boot.admin.server.config.EnableAdminServer;
import org.mybatis.spring.annotation.MapperScan;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.PropertySource;
import org.springframework.context.event.EventListener;
import org.springframework.core.env.Environment;

import com.cim.idm.framework.banner.ZIDMBanner;
import com.zi.mwms.solution.config.Globals;

@SpringBootApplication(scanBasePackages = { "com.cim.idm","com.zi.mwms"},exclude = ZidmPlatformLicenseAutoConfiguration.class)
@PropertySource("file:${configRootPath}/db/oracle.properties")
@PropertySource("file:${configRootPath}/middleware/middleware.properties")
@MapperScan("com.cim.idm.dao")
//@EnableAdminServer
public class Application {

	private static Logger log = LoggerFactory.getLogger(Application.class);
	private static final Object daemonLock = new Object();
	private static volatile Application daemon = null;
	private static ApplicationContext applicationContext;
	private static final File wmsBaseFile;
	private static final File mesHomeFile;
	private static final File mesConfigDir;

	private static final String separator = System.getProperty("file.separator");

	static {
		String classFileRootPath = Application.class.getResource("/").getPath();

		String userDir = "";
		if(classFileRootPath.endsWith("/target/classes/")){
			userDir = classFileRootPath.substring(0,classFileRootPath.length()-16);
		}
		else {
			userDir = System.getProperty("user.dir");
		}

		// Home first
		String home = System.getProperty(Globals.WMS_HOME_PROP);
		File homeFile = null;

		if (home != null) {
			File f = new File(home);
			try {
				homeFile = f.getCanonicalFile();
			} catch (IOException ioe) {
				homeFile = f.getAbsoluteFile();
			}
		}

		if (homeFile == null) {
			// First fall-back. See if current directory is a bin directory
			// in a normal Tomcat install
			File bootstrapJar = new File(userDir, "bootstrap.jar");

			if (bootstrapJar.exists()) {
				File f = new File(userDir, "..");
				try {
					homeFile = f.getCanonicalFile();
				} catch (IOException ioe) {
					homeFile = f.getAbsoluteFile();
				}
			}
		}

		if (homeFile == null) {
			// Second fall-back. Use current directory
			File f = new File(userDir);
			try {
				homeFile = f.getCanonicalFile();
			} catch (IOException ioe) {
				homeFile = f.getAbsoluteFile();
			}
		}
		mesHomeFile = homeFile;
		System.setProperty(Globals.WMS_HOME_PROP, mesHomeFile.getPath());

		// Then base
		String base = System.getProperty(Globals.WMS_BASE_PROP);
		if (base == null) {
			wmsBaseFile = mesHomeFile;
		} else {
			File baseFile = new File(base);
			try {
				baseFile = baseFile.getCanonicalFile();
			} catch (IOException ioe) {
				baseFile = baseFile.getAbsoluteFile();
			}
			wmsBaseFile = baseFile;
		}
		System.setProperty(Globals.WMS_BASE_PROP, wmsBaseFile.getPath());

		String configDir = System.getProperty(Globals.WMS_CONF_PROP);

		if (configDir == null) {
			File mesParentDir = wmsBaseFile.getParentFile();
			File checkDir = new File(mesParentDir, "Environment" + separator + "config");
			if(checkDir.exists()) {
				mesConfigDir = checkDir;
			}
			else {
				mesConfigDir = new File(wmsBaseFile,"conf");
			}
		} else {
			File configDirFile = new File(configDir);
			try {
				configDirFile = configDirFile.getCanonicalFile();
			} catch (IOException ioe) {
				configDirFile = configDirFile.getAbsoluteFile();
			}
			mesConfigDir = configDirFile;
		}
		if(mesConfigDir.getPath().contains("\\bin"))
		{
			String newpath=mesConfigDir.getPath().split("\\\\bin")[0]+"\\conf";
			System.setProperty(Globals.WMS_CONF_PROP, newpath);
		}
		else{
			System.setProperty(Globals.WMS_CONF_PROP, mesConfigDir.getPath());
		}
	}

	@Autowired Environment env;
	public static void main(String[] args) {
		PriorityQueue<Double> pq = new PriorityQueue<Double>((a, b) -> b.compareTo(a));
		String command = "start";
		if(Arrays.asList(args).stream().anyMatch(s -> s.equals("start")
				|| s.equals("stop") || s.equals("help"))) {
			if (args.length > 0) {
				command = args[args.length - 1];
			}
		}
		if (command.equals("stop")) {
			//shutdownApp();
		}else if(command.equals("start")) {
			synchronized (daemonLock) {
				if (daemon == null) {
					Application bootstrap = new Application();
					daemon = bootstrap;
				}
			}
			daemon.start(args);
		}else {
			log.warn("Bootstrap: command \"" + command + "\" does not exist.");
		}
	}

	private void start(String[] args) {
		SpringApplicationBuilder application = new SpringApplicationBuilder(Application.class);
		application.banner(new ZIDMBanner());
		applicationContext = application.run(args);
	}

	@EventListener
	void handleApplicationReadyEvent(ApplicationReadyEvent event) {
		String company = env.getProperty("company");
		String factory = env.getProperty("factory");
		String cim = env.getProperty("cim");
		String mode = env.getProperty("mode");
		String svr = env.getProperty("svr");
		
		log.info("***********************************************************************************************");
		log.info("[{} {} {} {} {}] server start complete, PID={}", company, factory, cim, mode, svr, getProcessID());
		log.info("***********************************************************************************************");
	}
	
	public static final int getProcessID() {  
        RuntimeMXBean runtimeMXBean = ManagementFactory.getRuntimeMXBean();
        return Integer.valueOf(runtimeMXBean.getName().split("@")[0]).intValue();  
    } 

//	@PreDestroy
//	public static void shutdownApp() throws MalformedObjectNameException, InstanceNotFoundException, IntrospectionException, ReflectionException, MBeanException, IOException{
//		log.info("Shutdown MES Application : {}", System.getProperty("Seq"));
//		int exitCode = SpringApplication.exit(applicationContext, (ExitCodeGenerator)(()->0));
//		System.exit(exitCode);
//	}
}
