package com.its.vds.stat.server;

import com.its.vds.stat.server.config.ApplicationConfig;
import com.its.vds.stat.server.controller.VdsStatBatchServerController;
import com.its.vds.stat.server.service.UnitSystService;
import com.its.vds.stat.server.utils.SpringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.Banner;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.context.ApplicationPidFileWriter;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationListener;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.scheduling.annotation.EnableAsync;

import java.text.SimpleDateFormat;
import java.util.Date;

@Slf4j
@SpringBootApplication
@EnableAsync
@ComponentScan(basePackages = { "com.its.vds.stat.server.utils", "com.its.vds.stat.server" })
public class VdsStatServerApplication
		implements CommandLineRunner, ApplicationListener<ContextClosedEvent>, InitializingBean, DisposableBean {

	private static boolean isTerminated = false;
	public static final String APPLICATION_NAME = "vds-stat-server";
	@Autowired
	private static ApplicationContext context;

	public static void main(String[] args) {
		SpringApplication application = new SpringApplicationBuilder()
				.sources(VdsStatServerApplication.class)
				.listeners(new ApplicationPidFileWriter("./conf/" + APPLICATION_NAME + ".pid"))
				.registerShutdownHook(true)
				.build();
		application.setBannerMode(Banner.Mode.OFF);
		application.run(args);
	}

	@Override
	public void run(String... args) throws Exception {

		ApplicationConfig applicationConfig = SpringUtils.getBean(ApplicationConfig.class);

		log.info("");
		log.info("");
		log.info("************************************************************************************");
		log.info("**                                                                                **");
		log.info("**                         Intelligent Traffic System                             **");
		log.info("**                           VDS STAT Server Program.                             **");
		log.info("**                                                                                **");
		log.info("**                                                                   [ver.1.0]    **");
		log.info("**          {}", applicationConfig.getProcessId());
		log.info("** startup: {}", applicationConfig.getBootingTime());
		log.info("************************************************************************************");
		if (args.length == 2) {
			String startStr = args[0];
			String endStr = args[1];

			applicationConfig.setStartSchedule(false);

			VdsStatBatchServerController batchServerController = SpringUtils.getBean(VdsStatBatchServerController.class);
			batchServerController.run(startStr, endStr);

			int exitCode = SpringApplication.exit(context, () -> 0);
			System.exit(exitCode);
		}
		else {
			UnitSystService unitSystService = SpringUtils.getBean(UnitSystService.class);
			unitSystService.processStart();

			applicationConfig.setStartSchedule(true);
		}
		Runtime.getRuntime().addShutdownHook(new Thread(() -> {
			log.error("on shutdown hook.");
			applicationConfig.setStartSchedule(false);
			terminateApplication();
		}));
	}

	public void terminateApplication() {
		SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
		log.info("**    Application Terminated: {}, {}", sdfDate.format(new Date()), isTerminated);
		if (!isTerminated) {
			isTerminated = true;
			log.info("************************************************************************************");
            try {
                UnitSystService unitSystService = SpringUtils.getBean(UnitSystService.class);
                unitSystService.processStop();
            }
            catch (Exception e) {
                log.error("**    unitSystService.processStop: {}", e.getMessage());
            }
			log.info("************************************************************************************");
		}
	}

	@Override
	public void onApplicationEvent(ContextClosedEvent contextClosedEvent) {
		log.error("onApplicationEvent: {}", contextClosedEvent);
		terminateApplication();
	}

	@Override
	public void destroy() throws Exception {
		log.error("Application destroy: isTerminated({})", isTerminated);
	}

	@Override
	public void afterPropertiesSet() throws Exception {
        log.info("Application afterPropertiesSet");
	}

}
