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.VmsCtlrMapper;
import com.its.vms.dto.NET;
import com.its.vms.dto.TbVmsCtlrDto;
import com.its.vms.dto.TbVmsCtlrSttsDto;
import com.its.vms.entity.TbVmsCtlr;
import com.its.vms.global.AppRepository;
import com.its.vms.process.DbmsData;
import com.its.vms.process.DbmsDataProcess;
import com.its.vms.process.DbmsDataType;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.io.File;
import java.util.*;

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

    private final ApplicationConfig config;
    private final VmsCtlrMapper vmsCtlrMapper;
    private int historyMin;

    @PostConstruct
    private void init() {
        log.info("VmsCtlrService.init: Start.");
        this.historyMin = -1;
        log.info("VmsCtlrService.init: ..End.");
    }

    public void loadDb() {
        loadCtlrInfo();
    }

    public void initCtlrInfo() {
        try {
            for (Map.Entry<Long, TbVmsCtlr> e : AppRepository.getInstance().getCtlrMap().entrySet()) {
                TbVmsCtlr obj = e.getValue();
                obj.setDelYn("Y");
            }
        }
        catch (Exception e) {
            log.error("VmsCtlrService.initCtlrInfo: Exception: {}", e.toString());
        }
    }

    public void loadCtlrInfo() {
        initCtlrInfo();
        try {
            List<TbVmsCtlrDto> infoList  = this.vmsCtlrMapper.selectAll();
            log.info("VmsCtlrService.loadCtlrInfo(), {} EA", infoList.size());
            for (TbVmsCtlrDto dto : infoList) {
                log.info("VmsCtlrService.loadCtlrInfo: {}", dto);
                TbVmsCtlr obj = dto.toEntity();
                if (obj.getCtlrId().trim().equals("")) {
                    log.error("VmsCtlrService.loadCtlrInfo: Controller Ip Address Error: {}", obj);
                    continue;
                }

                AppRepository.getInstance().getCtlrMap().put(obj.getCtlrNmbr(), obj);
                AppRepository.getInstance().getCtlrIpMap().put(obj.getCtlrIp(), obj);
                obj.getStts().initUnknown();

                obj.setLocalFormDir(this.config.getFtpFormDir() + File.separator + obj.getCtlrNmbr());
                obj.setFtpFormDir(ApplicationConfig.FTP_FORM + File.separator + obj.getCtlrNmbr() + File.separator);
                obj.setFtpDownload(true);

                this.config.makeDirectory(obj.getLocalFormDir(), "VMS " + obj.getCtlrNmbr() + " Directory.");
            }
        }
        catch (Exception e) {
            log.error("VmsCtlrService.loadCtlrInfo: {}", e.toString());
        }

        for (Map.Entry<Long, TbVmsCtlr> obj : AppRepository.getInstance().getCtlrMap().entrySet()) {
            log.info("VmsCtlrService.VmsCtlr: {}", obj.toString());
        }
    }

    public void updateCtlrStts(boolean isRun, TbVmsCtlr AObj) {
        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;
        }

        //제어기 상태정보 업데이트
        List<TbVmsCtlrSttsDto> ctlrSttsList = Collections.synchronizedList(new ArrayList<>());
        String UPDT_DT = SysUtils.getSysTime();
        int normal = 0;
        int error  = 0;
        for (Map.Entry<Long, TbVmsCtlr> e : AppRepository.getInstance().getCtlrMap().entrySet()) {
            TbVmsCtlr obj = e.getValue();
            if (AObj != null && AObj.getCtlrNmbr() != obj.getCtlrNmbr()) {
                continue;
            }

            obj.getStts().setUpdtDt(UPDT_DT);

            if (isRun && obj.getNetState() >= NET.LOGINED && obj.getChannel() != null) {
                //제어기 통신정상
                normal++;
                obj.getStts().setCmncSttsCd("CMS0");
                obj.getStts().setCommSttsCd("CMS0");
            }
            else {
                //제어기 통신이상
                error++;
                obj.getStts().initError();
            }

            if (isRun) {
                ctlrSttsList.add(obj.getStts());
            }
            else {
                this.vmsCtlrMapper.updateCtlrStts(obj.getStts());
                if (insHs) {
                    this.vmsCtlrMapper.insertCtlrSttsHs(obj.getStts());
                }
            }
        }

        // 제어기 상태정보 DB 업데이트
        if (!ctlrSttsList.isEmpty()) {
            DbmsDataProcess dbmsDataProcess = (DbmsDataProcess) AppUtils.getBean(DbmsDataProcess.class);
            dbmsDataProcess.add(new DbmsData(DbmsDataType.DBMS_DATA_CTLR_STTS_LIST, insHs, ctlrSttsList));
        }

        log.info("VmsCtlrService.updateCtlrStts: total {}, normal {}, error {}", normal + error, normal, error);
    }

    public void monitoringSession() {
        long currMilliSeconds = System.currentTimeMillis();
        for (Map.Entry<Long, TbVmsCtlr> e : AppRepository.getInstance().getCtlrMap().entrySet()) {
            TbVmsCtlr obj = e.getValue();
//            if (obj.getNetState() >= NET.LOGIN_REQ && obj.getChannel() != null) {
//                // 주차정보시스템 통신정상
//                long recvTimout = currMilliSeconds - obj.getLastRecvTime();
//                if (recvTimout > 15*1000) {
//                    log.error("VmsCtlrService.monitoringSession: Idle timeout: {}, ipAddr={}, Idle={} sec.", obj.getID(), obj.getRSE_ID(), (int)(recvTimout/1000L));
//                    obj.setLastRecvTime();
//                    obj.sendFrED();
//                }
//
//            }
        }
    }
}
