package com.its.vms.service;

import com.its.app.AppUtils;
import com.its.app.utils.SysUtils;
import com.its.vms.config.ApplicationConfig;
import com.its.vms.dao.mapper.UnitSystMapper;
import com.its.vms.entity.TbUnitSyst;
import com.its.vms.entity.TbUnitSystStts;
import com.its.vms.process.DbmsData;
import com.its.vms.process.DbmsDataProcess;
import com.its.vms.process.DbmsDataType;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.MDC;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Calendar;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Getter
@Service
@RequiredArgsConstructor
@Transactional(rollbackFor = {Exception.class})
public class UnitSystService {

    private final DbmsDataProcess dbmsDataProcess;
    private final UnitSystMapper mapper;
    private final ConcurrentHashMap<String, TbUnitSyst> dataMap = new ConcurrentHashMap<>();
    private final TbUnitSystStts unitSystStts = TbUnitSystStts.builder().build();

    private String processId;
    private int historyMin;
    public static String _srcIpAddr;

    @PostConstruct
    private void init() {
        log.info("UnitSystService.init: start.");
        ApplicationConfig applicationConfig = (ApplicationConfig) AppUtils.getBean(ApplicationConfig.class);
        this.processId = applicationConfig.getId();
        this.historyMin = -1;

        try {
            InetAddress local = InetAddress.getLocalHost();
            String localIp = local.getHostAddress();
            long ipAddr = SysUtils.ipToLong(localIp);
            UnitSystService._srcIpAddr = String.format("%03d.%03d.%03d.%03d-", (ipAddr>>24)&0xFF, (ipAddr>>16)&0xFF, (ipAddr>>8)&0xFF, (ipAddr)&0xFF);
        } catch (UnknownHostException e) {
            UnitSystService._srcIpAddr = "127.000.000.001-";
            log.error("UnitSystService.init: UnknownHostException");
        }

        log.info("UnitSystService.init. _srcIpAddr: {}.", UnitSystService._srcIpAddr);
        log.info("UnitSystService.init. processId: {}.", this.processId);
        log.info("UnitSystService.init: ..end.");
    }

    @PreDestroy
    public void destroyService() {
        log.error("UnitSystService.destroy. system terminated.......");
        updateUnitSystStts(false);
//        if (OS.isWindows()) {
//            MainUI UI = MainUI.getInstance();
//            if (UI != null) {
//                System.exit(0);
//            }
//        }
    }

    public void loadMaster() {
        try {
            // 초기화, 기존 정보 삭제로 초기화
            for (Map.Entry<String, TbUnitSyst> e : this.dataMap.entrySet()) {
                e.getValue().setDelYn("Y");
            }

            List<TbUnitSyst> systList = this.mapper.selectAll();
            log.info("UnitSystService.selectAll(), {} EA", systList.size());
            for (TbUnitSyst unit : systList) {
                if (unit.getSystId().equals(this.processId)) {
                    this.unitSystStts.setSYST_ID(this.processId);
                    String localIp = unit.getSystIp1().trim();
                    long ipAddr = SysUtils.ipToLong(localIp);
                    UnitSystService._srcIpAddr = String.format("%03d.%03d.%03d.%03d-", (ipAddr>>24)&0xFF, (ipAddr>>16)&0xFF, (ipAddr>>8)&0xFF, ipAddr&0xFF);
                    log.info("UnitSystService.loadMaster: _srcIpAddr: {}.", UnitSystService._srcIpAddr);
                }

                if (unit.getSystType().contentEquals("UOT")) {
                    unit.setSystIp1(unit.getSystIp1().trim());
                    this.dataMap.put(unit.getSystId(), unit);
                }
            }
        }
        catch (Exception e) {
            log.error("UnitSystService.selectAll: Exception: {}.", e.toString());
        }
    }

    public void updateUnitSystStts(boolean isRun) {
        String keyData = "unit";
        MDC.put("id", keyData);
        boolean insHs = false;
        Calendar cal = Calendar.getInstance();
        int min = cal.get(Calendar.MINUTE);
        if ((min % 5) == 0 && this.historyMin != min) {
            insHs = true;
            this.historyMin = min;
        }

        String SYST_STTS_CD = isRun ? "SPS1" : "SPS3";
        this.unitSystStts.setSYST_ID(this.processId);
        this.unitSystStts.setUPDT_DT(SysUtils.getSysTime());
        this.unitSystStts.setSYST_STTS_CD(SYST_STTS_CD);

        if (!isRun) {
           this.mapper.updateUnitSystStts(this.unitSystStts);
            if (insHs) {
                this.mapper.insertUnitSystSttsHs(this.unitSystStts);
            }
        }
        else {
            this.dbmsDataProcess.add(new DbmsData(DbmsDataType.DBMS_DATA_UNIT_SYST_STTS, insHs, this.unitSystStts));
            if (insHs) {
                loadMaster();
            }
        }
        MDC.remove(keyData);
        MDC.clear();
    }
}
