package com.its.pis;

import com.its.app.AppUtils;
import com.its.app.utils.SysUtils;
import com.its.pis.config.ProcessConfig;
import com.its.pis.process.DbmsJobProcess;
import com.its.pis.service.UnitSystService;
import com.its.pis.service.VdsCtlrService;
import com.its.pis.ui.JTextAreaOutputStream;
import com.its.pis.ui.MainUI;
import com.its.pis.xnettcp.center.CenterTcpServerService;
import com.its.pis.xnettcp.vds.VdsTcpClientCommService;
import lombok.extern.slf4j.Slf4j;
import org.apache.catalina.connector.Connector;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.boot.Banner;
import org.springframework.boot.CommandLineRunner;
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.annotation.Configuration;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.web.bind.annotation.CrossOrigin;

import javax.swing.*;
import java.awt.*;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.PrintStream;

@Slf4j
@EnableAsync
@Configuration
@SpringBootApplication
@ComponentScan(basePackages = {"com.its.pis.config", "com.its.pis.dao.mapper", "com.its"})
@CrossOrigin("*")
public class PisCommServerApplication implements CommandLineRunner, ApplicationListener<ContextClosedEvent>, InitializingBean, DisposableBean {
//public class PisCommServerApplication implements ApplicationListener<ContextClosedEvent>, InitializingBean, DisposableBean {

    private Connector connector;

    public static void main(String[] args) {
        File file1 = new File("./conf/pis-comm-server.pid");
        if (file1.exists()) {
            System.out.println(System.getProperty("Program Already Running....."));
            log.error("Program Already Running.....");
            //return;
        }

        ApplicationContext context = new SpringApplicationBuilder(PisCommServerApplication.class)
                //.web(WebApplicationType.NONE)
                .listeners(new ApplicationPidFileWriter("./conf/pis-comm-server.pid"))
                .headless(false)
                .bannerMode(Banner.Mode.OFF)
                .run(args);

//        SpringApplication application = new SpringApplicationBuilder()
//                .sources(PisCommServerApplication.class)
//                .listeners(new ApplicationPidFileWriter("./conf/pis-comm-server.pid"))
//                .build();
//        application.run(args);
    }

    @Override
    public void run(String... args) throws Exception {
        SwingUtilities.invokeLater(() -> {
            String pathOfImage = "C:\\DEV\\ITS\\01.WINDOWS\\22.05.GUMI\\JAVA\\pis-comm-server\\src\\main\\resources\\static\\image\\application.png";
            String sysTime = SysUtils.getSysTimeStr();
            //JFrame.setDefaultLookAndFeelDecorated(true);
            JFrame frame = new JFrame("PIS 통신 서버 - [" + sysTime + "]");
            MainUI UI = new MainUI(frame);
            frame.setIconImage(Toolkit.getDefaultToolkit().getImage(pathOfImage));
            frame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE);
            frame.setContentPane(UI.getRootPanel());
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.addWindowListener(new WindowAdapter() {
                @Override
                public void windowClosing(WindowEvent e) {
                    if (JOptionPane.showConfirmDialog(UI.getRootPanel(), "시스템을 종료 하시겠습니까?", "시스템 종료", 0) == 0) {
                        System.exit(0);
                    } else {
                        frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
                    }
                }
            });
            frame.pack();
            frame.setBounds(100, 100, 1000, 800);
            frame.setLocationRelativeTo(null);
            frame.setVisible(true);

            JTextArea logArea = UI.getTaLog();
            logArea.setText(null);
            JTextAreaOutputStream out = new JTextAreaOutputStream(logArea);
            System.setOut(new PrintStream(out));
        });

        ProcessConfig processConfig = (ProcessConfig) AppUtils.getBean(ProcessConfig.class);

        log.info("");
        log.info("");
        log.info("************************************************************************************");
        log.info("**                                                                                **");
        log.info("**                         Intelligent Traffic System                             **");
        log.info("**                      PIS Communication Server Program.                         **");
        log.info("**                                                                                **");
        log.info("**                                                                   [ver.1.0]    **");
        log.info("**          {}", processConfig.getId());
        log.info("** startup: {}", processConfig.getBootingDateTime());
        log.info("************************************************************************************");

        // init application
        DbmsJobProcess dbmsJobProcess = (DbmsJobProcess)AppUtils.getBean(DbmsJobProcess.class);
        dbmsJobProcess.run();

//        VdsDataProcess tcpServerDataProcess = (VdsDataProcess)AppUtils.getBean(VdsDataProcess.class);
//        tcpServerDataProcess.run();

        UnitSystService unitSystService = (UnitSystService)AppUtils.getBean(UnitSystService.class);
        unitSystService.loadMaster();
        unitSystService.updateUnitSystStts(true);

//        VdsCtlrService ctlrService = (VdsCtlrService)AppUtils.getBean(VdsCtlrService.class);
//        ctlrService.loadDb();
//        ctlrService.updateCtlrStts(true);

//        MainUI mainUI = MainUI.getInstance();
//        if (mainUI != null) {
//            mainUI.LoadControllerInfo(ctlrService);
//        }

//        VdsTcpClientCommService vdsCommClientService = (VdsTcpClientCommService)AppUtils.getBean(VdsTcpClientCommService.class);
//        vdsCommClientService.run();

        CenterTcpServerService centerService = (CenterTcpServerService)AppUtils.getBean(CenterTcpServerService.class);
        centerService.run();
//
//        UdpServerCenterComm udpServerCenterComm = (UdpServerCenterComm)AppUtils.getBean(UdpServerCenterComm.class);
//        udpServerCenterComm.run();

        // schedule enable
        processConfig.setStartSchedule(true);
    }

    public void terminateApplication() {
        UnitSystService unitSystService = (UnitSystService) AppUtils.getBean(UnitSystService.class);
        unitSystService.updateUnitSystStts(false);
        VdsCtlrService ctlrService = (VdsCtlrService) AppUtils.getBean(VdsCtlrService.class);
        ctlrService.updateCtlrStts(false);

        CenterTcpServerService centerService = (CenterTcpServerService)AppUtils.getBean(CenterTcpServerService.class);
        centerService.stop();

        VdsTcpClientCommService vdsCommClientService = (VdsTcpClientCommService)AppUtils.getBean(VdsTcpClientCommService.class);
        vdsCommClientService.shutdown();

//        TcpServerVdsComm tcpServersComm = (TcpServerVdsComm)AppUtils.getBean(TcpServerVdsComm.class);
//        tcpServersComm.getAcceptGroups().shutdownGracefully();
//        tcpServersComm.getWorkerGroups().shutdownGracefully();

//        UdpServerCenterComm udpServerCenterComm = (UdpServerCenterComm)AppUtils.getBean(UdpServerCenterComm.class);
//        udpServerCenterComm.getNioEventLoopGroup().shutdownGracefully();
    }
    @Override
    public void onApplicationEvent(ContextClosedEvent event) {
        log.error("Application Terminated: {}", event.getTimestamp());
        terminateApplication();
    }
    @Override
    public void afterPropertiesSet() throws Exception {
        //System.err.println("InitializingBean 인터페이스 구현 메서드입니다. 'Bean'이 생성될 때 마다 호출되는 메서드 입니다.");
    }
    @Override
    public void destroy() throws Exception {
        //System.err.println("DisposableBean 인터페이스 구현 메서드입니다. 'Bean'이 소멸될 때 마다 호출되는 메서드입니다");
    }

    /*@Bean
    public CommandLineRunner commandLineRunner(ApplicationContext ctx) {
        return args -> {
            System.out.println("Let's inspect the beans provided by Spring Boot:");
            String[] beanNames = ctx.getBeanDefinitionNames();
            Arrays.sort(beanNames);
            for (String beanName : beanNames) {
                System.out.println(beanName);
            }
        };
    }*/

}
