package com.xydl.cac.task;

import com.xydl.cac.entity.*;
import com.xydl.cac.iec.IecClient;
import com.xydl.cac.iec.NetErrorThread;
import com.xydl.cac.model.StaticVariable;
import com.xydl.cac.repository.*;
import com.xydl.cac.service.ModevTypeService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.PreDestroy;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

@Service
@Slf4j
public class Client61850Task {

    @Value("${cac.61850.enable:true}")
    public boolean enable;
    @Value("${cac.61850.check:false}")
    public boolean check;
    @Resource
    AsyncTask asyncTask;
    @Resource
    IcdFileRepository fileRepository;
    @Resource
    IcdIedRepository iedRepository;
    @Resource
    RptparamindexRepository rptparamindexRepository;
    @Resource
    ModevTypeService modevTypeService;
    @Resource
    NSensorRepository sensorRepository;
    @Resource
    IedDlConfigRepository dlConfigRepository;

    int shutdown = 0;

    @PreDestroy
    private void preDestroy() {
        shutdown = 1;
    }

    @Scheduled(cron = "0 * * * * ?")
    public void collectAll() {
        if (!enable) {
            return;
        }
        Calendar cal = Calendar.getInstance();
        int h = cal.get(Calendar.HOUR_OF_DAY);
        int m = cal.get(Calendar.MINUTE);
        m = h * 60 + m;

        List<Integer> typeIdList = new ArrayList<>();
        List<ModevType> modevTypeList = modevTypeService.listAll();
        for (ModevType type : modevTypeList) {
            int intervals = 30;
            if (type.getIntervals() != null) {
                intervals = type.getIntervals();
            }
            int x = m % intervals;
            if (x == 0) {
                typeIdList.add(type.getId());
            }
        }
        if (CollectionUtils.isEmpty(typeIdList)) {
            return;
        }

        List<NSensor> sensorList = sensorRepository.findByTypeIdIn(typeIdList);
        List<Integer> eqmidList = new ArrayList<>();
        for (NSensor sensor : sensorList) {
            if (sensor.getDevId() != null) {
                eqmidList.add(sensor.getDevId());
            }
        }
        if (CollectionUtils.isEmpty(eqmidList)) {
            return;
        }

        List<Rptparamindex> rptList = rptparamindexRepository.findAllByEqmidInAndColnameIsNotNullAndTablenameIsNotNull(eqmidList);
        List<IedDlConfig> dlList = dlConfigRepository.findByDevIdIn(eqmidList);
        if (CollectionUtils.isEmpty(rptList) && CollectionUtils.isEmpty(dlList)) {
            return;
        }
        List<IedDlConfig> dlNewList = new ArrayList<>();
        for (IedDlConfig item : dlList) {
            List<NSensor> senList = sensorRepository.findByDevId(item.getDevId());
            if (!CollectionUtils.isEmpty(senList)) {
                item.setSensor(senList.get(0));
                dlNewList.add(item);
            }
        }

        List<IcdFile> icdFileList = fileRepository.findAll();
        if (!CollectionUtils.isEmpty(icdFileList)) {
            for (IcdFile icdFile : icdFileList) {
                this.collectIcdFile(icdFile, rptList, dlNewList);
            }
        }
    }

    private void collectIcdFile(IcdFile icdFile, List<Rptparamindex> rptList, List<IedDlConfig> dlList) {
        if (shutdown == 1) {
            return;
        }
        List<IcdIed> iedList = iedRepository.findByIcdFileId(icdFile.getId());
        if (!CollectionUtils.isEmpty(iedList)) {
            for (IcdIed ied : iedList) {
                asyncTask.collectIed(icdFile.getXml(), ied, rptList, dlList);
            }
        }
    }

    @Scheduled(initialDelay = 60 * 1000, fixedDelay = 60 * 1000)
    private void testAll() {
        if (!check) {
            return;
        }
        List<IcdIed> iedTestList = new ArrayList<>();
        List<IcdFile> icdFileList = fileRepository.findAll();
        if (!CollectionUtils.isEmpty(icdFileList)) {
            for (IcdFile icdFile : icdFileList) {
                this.testOneFile(icdFile, iedTestList);
            }
        }
        StaticVariable.iedTestList = iedTestList;
    }

    private void testOneFile(IcdFile icdFile, List<IcdIed> iedTestList) {
        if (shutdown == 1) {
            return;
        }
        List<IcdIed> iedList = iedRepository.findByIcdFileId(icdFile.getId());
        if (!CollectionUtils.isEmpty(iedList)) {
            for (IcdIed ied : iedList) {
                this.testOneIed(icdFile.getXml(), ied);
                iedTestList.add(ied);
            }
        }
    }

    private void testOneIed(String xml, IcdIed ied) {
        if (shutdown == 1) {
            return;
        }
        IecClient iecClient = new IecClient();
        try {
            iecClient.init(ied, xml);
            iecClient.connect();
            ied.setConnected(true);
        } catch (Exception ex) {
            ied.setConnected(false);
            NetErrorThread thread = new NetErrorThread(ied.getId());
            thread.start();
        } finally {
            iecClient.disconnect();
        }
    }
}
