package com.its.pis.scheduler;

import com.its.app.AppUtils;
import com.its.app.utils.Elapsed;
import com.its.app.utils.StatisticsTime;
import com.its.pis.config.ProcessConfig;
import com.its.pis.service.StatisticsServices;
import com.its.pis.service.UnitSystService;
import com.its.pis.service.VdsCtlrService;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PreDestroy;

@Slf4j
@AllArgsConstructor
@EnableScheduling
@Component
public class SchedulerTask {

    private final ProcessConfig processConfig;
    private final UnitSystService unitSystService;
    private final VdsCtlrService vdsCtlrService;
    private final StatisticsServices statisticsServices;

    @Scheduled(cron = "6 * * * * *")  // 1분주기 작업 실행(매분 6초)
    public void UnitSystSchedule() {
        if (!this.processConfig.isStartSchedule()) {
            return;
        }
        Elapsed elapsed = new Elapsed();
        log.info("          UnitSystSchedule: start. {}", Thread.currentThread().getName());
        // 프로세스 상태정보 업데이트
        this.unitSystService.updateUnitSystStts(true);
        // 제어기 상태정보 업데이트(제어기/프로세스 상태정보 UDP 전송)
        this.vdsCtlrService.updateCtlrStts(true);
        log.info("          UnitSystSchedule: ..end. {} ms. {}", elapsed.milliSeconds(), Thread.currentThread().getName());
    }

    @Scheduled(cron = "15 1 0/1 * * *")    // 매시 1분 15초
    public void VdsRTCSchedule() {
        if (!this.processConfig.isStartSchedule()) {
            return;
        }
        Elapsed elapsed = new Elapsed();
        log.info("            VdsRTCSchedule: start. {}", Thread.currentThread().getName());
        // 온도정보(온도/입력전압/출력전압) 요청
        // 제어기 동기화 요청
        this.vdsCtlrService.requestRTC();
        log.info("            VdsRTCSchedule: ..end. {} ms. {}", elapsed.milliSeconds(), Thread.currentThread().getName());
    }

    @Scheduled(cron = "4/30 * * * * *")    // 30초마다 요청(4초, 34초)
    public void VdsSynchronizationSchedule() {
        if (!this.processConfig.isStartSchedule()) {
            return;
        }
        Elapsed elapsed = new Elapsed();
        log.info("VdsSynchronizationSchedule: start. {}", Thread.currentThread().getName());
        // 온도정보(온도/입력전압/출력전압) 요청
        // 제어기 동기화 요청
        this.vdsCtlrService.requestSynchronization();
        log.info("VdsSynchronizationSchedule: ..end. {} ms. {}", elapsed.milliSeconds(), Thread.currentThread().getName());
    }

    @Scheduled(cron = "9/30 * * * * *")    // 30초마다 요청(9초, 39초)
    public void VdsDataRequestSchedule() {
        if (!this.processConfig.isStartSchedule()) {
            return;
        }
        Elapsed elapsed = new Elapsed();
        // VDS 교통 데이터를 요청한 다음에 차량 정보를 요청한다.
        // 제어기에서 동기화가 안되기 때문에 교통 데이터를 요청한 다음에 5초 후에 요청한다.
        log.info("    VdsDataRequestSchedule: start. {}", Thread.currentThread().getName());
        this.vdsCtlrService.requestData();
        log.info("    VdsDataRequestSchedule: ..end. {} ms. {}", elapsed.milliSeconds(), Thread.currentThread().getName());
    }

    @Scheduled(cron = "40 0/5 * * * *")    // 정주기 5분 40초에 스케쥴 실행
    public void StatisticsSchedule() {
        if (!this.processConfig.isStartSchedule()) {
            return;
        }
        Elapsed elapsed = new Elapsed();
        log.info("     VdsStatisticsSchedule: start. {}", Thread.currentThread().getName());
        ProcessConfig processConfig = (ProcessConfig) AppUtils.getBean(ProcessConfig.class);
        if (processConfig.isStatistics()) {
            StatisticsTime its = new StatisticsTime();
            its.init();
            its.setProcessing(true);

//            if (true) {
//                // VDS 검지기 5분 가공
//                this.statisticsServices.CRT_TB_VDS_DTCT_HS(its.getPrcsFiveMin(), its.getPrcsFiveMinFrom(), its.getPrcsFiveMinTo());
//            }

            if (its.isStat15Min()) {
                // 5분 정주기 가공이 끝나고 15분 주기일 경우(00, 15, 30, 45 분 일경우 15분 통계 정보를 생성한다)
                this.statisticsServices.CRT_TB_VDS_DTCT_15M_STAT(its.getStat15MinFrom(), its.getStat15MinFrom(), its.getStat15MinTo());
            }

            if (its.isStatHour()) {
                // 매시 5분 가공완료후 1시간 통계
                this.statisticsServices.CRT_TB_VDS_DTCT_HH_STAT(its.getStatHourTime(), its.getStatHourTime(), its.getStatHourTo());
            }

            if (its.isStatDay()) {
                // 00시 10분 가공이 끝나면 이전일의 통계 정보를 가공.
                this.statisticsServices.CRT_TB_VDS_DTCT_DD_STAT(its.getStatDayFrom(), its.getStatDayFrom(), its.getStatDayTo());
            }

            if (its.isStatMon()) {
                //  02시 10분 가공이 끝나면 이전일의 월통계 정보를 누적 가공.
                String STAT_DT = its.getStatMonFrom().substring(0, 6) + "00000000";
                this.statisticsServices.CRT_TB_VDS_DTCT_MN_STAT(STAT_DT, its.getStatMonFrom(), its.getStatMonTo());
            }

//            if (its.isStatYear()) {
//                // 02시 35분 가공이 끝나면 이전일의 연통계 정보를 누적 가공.
//                String STAT_DT = its.getStatYearFrom().substring(0, 4) + "0000000000";
//                this.statisticsServices.CRT_TB_VDS_DTCT_YY_STAT(STAT_DT, its.getStatYearFrom(), its.getStatYearTo());
//            }
            its.setProcessing(false);
        }
        log.info("     VdsStatisticsSchedule: ..end. {} ms. {}", elapsed.milliSeconds(), Thread.currentThread().getName());
    }

    @PreDestroy
    public void onShutDown() {
        this.unitSystService.updateUnitSystStts(false);
    }
}
