package com.gyee.frame.schdule.windturbinestatetime;

import com.gyee.frame.common.feign.IAdapterService;
import com.gyee.frame.common.feign.RemoteServiceBuilder;
import com.gyee.frame.mapper.auto.*;
import com.gyee.frame.model.auto.*;
import com.gyee.frame.model.config.WindturbineStandby;
import com.gyee.frame.model.custom.export.PointDataDB;
import com.gyee.frame.model.custom.export.TsPointData;
import org.apache.poi.ss.formula.functions.T;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Component
public class TaskWindturbineStateTime {
    @Resource
    private ScadafaultMapper scadafaultMapper;
    @Resource
    private WindTurbineTestingPointAi2Mapper windTurbineTestingPointAi2Mapper;
    @Resource
    private WindTurbineTestingPointDi2Mapper windTurbineTestingPointDi2Mapper;
    @Resource
    private StateDuratimeMapper stateDuratimeMapper;
    @Resource
    private StandbyTimeMapper standbyTimeMapper;
    @Resource
    private RemoteServiceBuilder remoteServiceBuilder;

    @Value("${windturbineStandby.GZ}")
    private String gzUniformcode;
    @Value("${windturbineStandby.DJ}")
    private String djUniformcode;
    @Value("${windturbineStandby.MTBFD}")
    private long mtbfd;
    @Value("${windturbineStandby.ZGZ}")
    private String zgzUniformcode;

    private int count = 0;
    private List<WindTurbineTestingPointAi2> standbyCodes;
    private List<WindTurbineTestingPointAi2> faultCodes;
    private List<WindTurbineTestingPointDi2> zgzCodes;


    @Scheduled(cron = "0 0 1 * * ?")
    public void getStandbyTime() {

        //List<StandbyTime> standbyTimes = new ArrayList<>();
        Calendar thisDay = Calendar.getInstance();
        thisDay.add(Calendar.DATE,-1);

        Calendar begain = Calendar.getInstance();
        begain.add(Calendar.DATE,-2);
        Long latetime = getLatetime(thisDay);
        Long earlytime = getEarlytime(thisDay);
        //风机列表
        List<WindTurbineTestingPointAi2> wttpai2s = getStandbyCodes();
        for (WindTurbineTestingPointAi2 wttpai2 : wttpai2s) {
            try {
                Thread.sleep(38);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            List<TsPointData> historyRaw = remoteServiceBuilder.ShardingService().getHistoryRaw(wttpai2.getId(), begain.getTimeInMillis(), latetime);
            //当天第一个点
            List<TsPointData> collect2 = historyRaw.stream().filter(tpd -> tpd.getTs() > earlytime).collect(Collectors.toList());
            historyRaw = historyRaw.stream().sorted(Comparator.comparing(TsPointData::getTs).reversed()).collect(Collectors.toList());
            //跨天（前一天倒数第一个点）
            long standbytime = 0;//待机时间
            List<TsPointData> collect1 = historyRaw.stream().filter(tpd -> tpd.getTs() < earlytime).limit(1).collect(Collectors.toList());

            historyRaw = collect2.stream().sorted(Comparator.comparing(TsPointData::getTs).reversed()).collect(Collectors.toList());

            if (collect1 != null && collect1.size() > 0) {
                int ktq = (int) collect1.get(0).getDoubleValue();
                if (collect2 == null || collect2.size() == 0) continue;
                if (ktq == 0) {
                    standbytime += collect2.get(0).getTs() - earlytime;
                }
            }

            long standbyMoment = latetime;//待机时刻
            //测点列表
            for (TsPointData tsPointData : historyRaw) {
                //点值
                int doubleValue = (int) tsPointData.getDoubleValue();
                if (doubleValue == 0) {
                    standbytime += standbyMoment - tsPointData.getTs();
                    standbyMoment = tsPointData.getTs();
                } else {
                    standbyMoment = tsPointData.getTs();
                }
            }

            StandbyTime standbyTime = new StandbyTime();
            standbyTime.setCountday(thisDay.getTime());
            standbyTime.setStandbyhours(TimeUnit.MILLISECONDS.toMinutes(standbytime));
            standbyTime.setStationid(wttpai2.getWindpowerstationid());
            standbyTime.setWindturbineid(wttpai2.getWindturbineid());
            standbyTime.setModelid(wttpai2.getModelid());
            standbyTime.setStatetype("standby");

            //standbyTimes.add(standbyTime);
            standbyTimeMapper.insert(standbyTime);
        }
        //standbyTimeMapper.batchInsert(standbyTimes);
    }

    private Long getEarlytime(Calendar calcday) {
        Calendar day = (Calendar)calcday.clone();
        day.set(Calendar.HOUR_OF_DAY, 0);
        day.set(Calendar.MINUTE, 0);
        day.set(Calendar.SECOND, 0);
        return day.getTimeInMillis();
    }

    private Long getLatetime(Calendar calcday) {
        Calendar day = (Calendar)calcday.clone();
        day.set(Calendar.HOUR_OF_DAY, 23);
        day.set(Calendar.MINUTE, 59);
        day.set(Calendar.SECOND, 59);
        return day.getTimeInMillis();
    }

    public List<WindTurbineTestingPointAi2> getStandbyCodes() {
        if (standbyCodes == null) {
            WindTurbineTestingPointAi2Example wtspAi2Example = new WindTurbineTestingPointAi2Example();
            wtspAi2Example.createCriteria().andUniformcodeEqualTo(djUniformcode);
            standbyCodes = windTurbineTestingPointAi2Mapper.selectByExample(wtspAi2Example);
        }
        return standbyCodes;
    }

    public List<WindTurbineTestingPointDi2> getZgzCodes() {
        if(zgzCodes==null){
            WindTurbineTestingPointDi2Example wtspDi2Example = new WindTurbineTestingPointDi2Example();
            wtspDi2Example.createCriteria().andUniformcodeEqualTo(zgzUniformcode).andModelidNotEqualTo("UP105-2000-S");
            zgzCodes = windTurbineTestingPointDi2Mapper.selectByExample(wtspDi2Example);
        }
        return zgzCodes;
    }

    public List<WindTurbineTestingPointAi2> getFaultCodes() {
        if (faultCodes == null) {
            WindTurbineTestingPointAi2Example wtspAi2Example = new WindTurbineTestingPointAi2Example();
            wtspAi2Example.createCriteria().andUniformcodeEqualTo(gzUniformcode);
            faultCodes = windTurbineTestingPointAi2Mapper.selectByExample(wtspAi2Example);
        }
        return faultCodes;
    }

    @Scheduled(cron = "0 */30 * * * ?")
    public void getFaultTime() {
        /*if (count == 0) {
            count++;
            Calendar oldday = Calendar.getInstance();
            oldday.add(Calendar.MONTH, -16);
            getGZTime(oldday);
        } else {*/
            Calendar oldday = Calendar.getInstance();
            oldday.add(Calendar.HOUR, -10);
            getGZTime4(oldday);
            getGZTime5(oldday);
        //}
        /*for (int i = 0; i > -922; i--) {
            Calendar thisDay = Calendar.getInstance();
            thisDay.add(Calendar.DATE, i - 1);

            Calendar begain = Calendar.getInstance();
            begain.set(Calendar.HOUR_OF_DAY, 1);
            begain.add(Calendar.DATE, i - 2);

            getStandbyTime(thisDay, begain);

            try {
                Thread.sleep(8000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }*/

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  }

    /**
     * 2MW连续无故障计算
     * @param oldday
     */
    private void getGZTime4(Calendar oldday) {
        Calendar today = Calendar.getInstance();
        List<WindTurbineTestingPointAi2> wttpai2s = getStandbyCodes();
        wttpai2s=wttpai2s.stream().filter(wttpai2->wttpai2.getModel().equals("CCWE-1500") || wttpai2.getModel().equals("UP105")).collect(Collectors.toList());
        for (WindTurbineTestingPointAi2 wttpai2 : wttpai2s) {
            if(wttpai2.getWindturbineid().equals("SG01_99")){
                System.out.println();
            }
            List<TsPointData> historyRaw = remoteServiceBuilder.ShardingService().getHistoryRaw(wttpai2.getId(), oldday.getTime().getTime(), today.getTime().getTime());
            historyRaw = historyRaw.stream().sorted(Comparator.comparing(TsPointData::getTs).reversed()).collect(Collectors.toList());

            long duration = 0;//故障时间
            long noduration = 0;//无故障运行时间
            Date nodurationtime = new Date();//最近真故障（超过3小时）解除时间
            long faultTime = Calendar.getInstance().getTimeInMillis();
            //测点列表
            for (TsPointData tsPointData : historyRaw) {
                //点值
                int doubleValue = (int) tsPointData.getDoubleValue();
                if(doubleValue==4){
                    continue;
                }else if(doubleValue == 2){
                    duration = faultTime - tsPointData.getTs();
                    //超过3小时
                    if (duration > mtbfd) {
                        Calendar instance = Calendar.getInstance();
                        instance.setTimeInMillis(faultTime);
                        nodurationtime = instance.getTime();
                        noduration = today.getTime().getTime() - faultTime;
                        break;
                    }
                    //faultTime = tsPointData.getTs();
                }else {
                    faultTime = tsPointData.getTs();
                    continue;
                }
            }
            if (noduration == 0) {
                StateDuratimeExample sExample = new StateDuratimeExample();
                sExample.createCriteria().andWindturbineidEqualTo(wttpai2.getWindturbineid());
                List<StateDuratime> stateDuratimes = stateDuratimeMapper.selectByExample(sExample);
                //当前时间-最近真故障解除时间
                long l = today.getTime().getTime() - stateDuratimes.get(0).getRecentfaulttime().getTime();

                StateDuratime stateDuratime = new StateDuratime();
                stateDuratime.setDuraminute(TimeUnit.MILLISECONDS.toHours(l));

                stateDuratimeMapper.updateByExampleSelective(stateDuratime, sExample);
            } else {
                StateDuratime stateDuratime = new StateDuratime();
                stateDuratime.setCountttime(today.getTime());
                stateDuratime.setDuraminute(TimeUnit.MILLISECONDS.toHours(noduration));
                stateDuratime.setRecentfaulttime(nodurationtime);

                StateDuratimeExample stateDuratimeExample = new StateDuratimeExample();
                stateDuratimeExample.createCriteria().andWindturbineidEqualTo(wttpai2.getWindturbineid());
                stateDuratimeMapper.updateByExampleSelective(stateDuratime, stateDuratimeExample);
            }
        }

    }

    /**
     * 1.5MW连续无故障计算
     * @param oldday
     */
    private void getGZTime5(Calendar oldday) {
        Calendar today = Calendar.getInstance();
        List<WindTurbineTestingPointDi2> wttpdi2s = getZgzCodes();
        for (WindTurbineTestingPointDi2 wttpdi2 : wttpdi2s) {
            List<TsPointData> historyRaw = remoteServiceBuilder.ShardingService().getHistoryRaw(wttpdi2.getId(), oldday.getTime().getTime(), today.getTime().getTime());
            historyRaw = historyRaw.stream().sorted(Comparator.comparing(TsPointData::getTs).reversed()).collect(Collectors.toList());

            long duration = 0;//故障时间
            long noduration = 0;//无故障运行时间
            Date nodurationtime = new Date();//最近真故障（超过3小时）解除时间
            long faultTime = Calendar.getInstance().getTimeInMillis();
            //测点列表
            for (TsPointData tsPointData : historyRaw) {
                //点值
                int doubleValue = (int) tsPointData.getDoubleValue();
                if(doubleValue==0){
                    faultTime = tsPointData.getTs();
                    continue;
                }else if(doubleValue == 1){
                    duration = faultTime - tsPointData.getTs();
                    //超过3小时
                    if (duration > mtbfd) {
                        Calendar instance = Calendar.getInstance();
                        instance.setTimeInMillis(faultTime);
                        nodurationtime = instance.getTime();
                        noduration = today.getTime().getTime() - faultTime;
                        break;
                    }
                    //faultTime = tsPointData.getTs();
                }
            }
            if (noduration == 0) {
                StateDuratimeExample sExample = new StateDuratimeExample();
                sExample.createCriteria().andWindturbineidEqualTo(wttpdi2.getWindturbineid());
                List<StateDuratime> stateDuratimes = stateDuratimeMapper.selectByExample(sExample);
                //当前时间-最近真故障解除时间
                long l = today.getTime().getTime() - stateDuratimes.get(0).getRecentfaulttime().getTime();

                StateDuratime stateDuratime = new StateDuratime();
                stateDuratime.setDuraminute(TimeUnit.MILLISECONDS.toHours(l));

                stateDuratimeMapper.updateByExampleSelective(stateDuratime, sExample);
            } else {
                StateDuratime stateDuratime = new StateDuratime();
                stateDuratime.setCountttime(today.getTime());
                stateDuratime.setDuraminute(TimeUnit.MILLISECONDS.toHours(noduration));
                stateDuratime.setRecentfaulttime(nodurationtime);

                StateDuratimeExample stateDuratimeExample = new StateDuratimeExample();
                stateDuratimeExample.createCriteria().andWindturbineidEqualTo(wttpdi2.getWindturbineid());
                stateDuratimeMapper.updateByExampleSelective(stateDuratime, stateDuratimeExample);
            }
        }

    }

    private void getGZTime3(Calendar oldday) {
        Calendar today = Calendar.getInstance();
        List<WindTurbineTestingPointAi2> wttpai2s = getFaultCodes();
        //每台风机
        for (WindTurbineTestingPointAi2 wttpai2 : wttpai2s) {
            List<TsPointData> historyRaw = remoteServiceBuilder.ShardingService().getHistoryRaw(wttpai2.getId(), oldday.getTime().getTime(), today.getTime().getTime());
            historyRaw = historyRaw.stream().sorted(Comparator.comparing(TsPointData::getTs).reversed()).collect(Collectors.toList());

            long duration = 0;//故障时间
            long noduration = 0;//无故障运行时间
            Date nodurationtime = new Date();//最近真故障（超过3小时）解除时间
            long faultTime = historyRaw.get(0).getTs();
            //测点列表
            for (TsPointData tsPointData : historyRaw) {
                //点值
                int doubleValue = (int) tsPointData.getDoubleValue();
                if (doubleValue == 0) {
                    faultTime = tsPointData.getTs();
                    continue;
                } else if (doubleValue == 1) {
                    duration = faultTime - tsPointData.getTs();
                    //超过3小时
                    if (duration > mtbfd) {
                        //可以优化数据库
                        Calendar instance = Calendar.getInstance();
                        instance.setTimeInMillis(faultTime);
                        nodurationtime = instance.getTime();
                        noduration = today.getTime().getTime() - faultTime;
                        break;
                    }
                    faultTime = tsPointData.getTs();
                }
            }

            if (noduration == 0) {
                noduration = today.getTime().getTime() - oldday.getTime().getTime();
            }

            StateDuratime stateDuratime = new StateDuratime();
            stateDuratime.setCountttime(today.getTime());
            stateDuratime.setDuraminute(TimeUnit.MILLISECONDS.toHours(noduration));
            stateDuratime.setRecentfaulttime(nodurationtime);

            StateDuratimeExample stateDuratimeExample = new StateDuratimeExample();
            stateDuratimeExample.createCriteria().andWindturbineidEqualTo(wttpai2.getWindturbineid());
            stateDuratimeMapper.updateByExampleSelective(stateDuratime, stateDuratimeExample);
        }
    }

    private void getGZTime2(Calendar oldday) {
        Calendar today = Calendar.getInstance();
        List<FaultInfo> faultInfos = scadafaultMapper.selectByGZ(oldday.getTime());
        //风机、故障列表
        Map<String, List<FaultInfo>> faultInfoMap = faultInfos.stream().collect(Collectors.groupingBy(FaultInfo::getWindturbineId));
        for (Map.Entry<String, List<FaultInfo>> faultInfoEntry : faultInfoMap.entrySet()) {

            long duration = 0;//故障时间
            long noduration = 0;//无故障运行时间
            Date nodurationtime = new Date();//最近真故障（超过3小时）解除时间
            Date faultTime = faultInfoEntry.getValue().get(0).getFaultTime();

            for (FaultInfo faultInfo : faultInfoEntry.getValue()) {
                if (faultInfo.getMessageType() == 3) {
                    faultTime = faultInfo.getFaultTime();
                    continue;
                } else if (faultInfo.getMessageType() == 1) {
                    duration = faultTime.getTime() - faultInfo.getFaultTime().getTime();
                    //超过3小时
                    if (duration > mtbfd) {
                        nodurationtime = faultTime;
                        noduration = today.getTime().getTime() - nodurationtime.getTime();
                        break;
                    }
                    faultTime = faultInfo.getFaultTime();
                }
            }

            if (noduration == 0) {
                StateDuratimeExample sExample = new StateDuratimeExample();
                sExample.createCriteria().andWindturbineidEqualTo(faultInfoEntry.getKey());
                List<StateDuratime> stateDuratimes = stateDuratimeMapper.selectByExample(sExample);
                //当前时间-最近真故障解除时间
                long l = today.getTime().getTime() - stateDuratimes.get(0).getRecentfaulttime().getTime();

                StateDuratime stateDuratime = new StateDuratime();
                stateDuratime.setDuraminute(TimeUnit.MILLISECONDS.toHours(l));

                StateDuratimeExample stateDuratimeExample = new StateDuratimeExample();
                stateDuratimeExample.createCriteria().andWindturbineidEqualTo(faultInfoEntry.getKey());
                stateDuratimeMapper.updateByExampleSelective(stateDuratime, stateDuratimeExample);
            } else {
                StateDuratime stateDuratime = new StateDuratime();
                stateDuratime.setCountttime(today.getTime());
                stateDuratime.setDuraminute(TimeUnit.MILLISECONDS.toHours(noduration));
                stateDuratime.setRecentfaulttime(nodurationtime);

                StateDuratimeExample stateDuratimeExample = new StateDuratimeExample();
                stateDuratimeExample.createCriteria().andWindturbineidEqualTo(faultInfoEntry.getKey());
                stateDuratimeMapper.updateByExampleSelective(stateDuratime, stateDuratimeExample);
            }

        }
    }

    private void getGZTime(Calendar oldday) {
        Calendar today = Calendar.getInstance();
        List<FaultInfo> faultInfos = scadafaultMapper.selectByGZ(oldday.getTime());
        //风机、故障列表
        Map<String, List<FaultInfo>> faultInfoMap = faultInfos.stream().collect(Collectors.groupingBy(FaultInfo::getWindturbineId));
        for (Map.Entry<String, List<FaultInfo>> faultInfoEntry : faultInfoMap.entrySet()) {

            long duration = 0;//故障时间
            long noduration = 0;//无故障运行时间
            Date nodurationtime = new Date();//最近真故障（超过3小时）解除时间
            Date faultTime = faultInfoEntry.getValue().get(0).getFaultTime();

            for (FaultInfo faultInfo : faultInfoEntry.getValue()) {
                if (faultInfo.getMessageType() == 3) {
                    faultTime = faultInfo.getFaultTime();
                    continue;
                } else if (faultInfo.getMessageType() == 1) {
                    duration = faultTime.getTime() - faultInfo.getFaultTime().getTime();
                    //超过3小时
                    if (duration > mtbfd) {
                        nodurationtime = faultTime;
                        noduration = today.getTime().getTime() - nodurationtime.getTime();
                        break;
                    }
                    faultTime = faultInfo.getFaultTime();
                }
            }

            if (noduration == 0) {
                noduration = today.getTime().getTime() - oldday.getTime().getTime();
            }
            StateDuratime stateDuratime = new StateDuratime();
            stateDuratime.setCountttime(today.getTime());
            stateDuratime.setDuraminute(TimeUnit.MILLISECONDS.toHours(noduration));
            stateDuratime.setRecentfaulttime(nodurationtime);
            stateDuratime.setSnapid(faultInfoEntry.getValue().get(0).getSnapID());

            StateDuratimeExample stateDuratimeExample = new StateDuratimeExample();
            stateDuratimeExample.createCriteria().andWindturbineidEqualTo(faultInfoEntry.getKey());
            stateDuratimeMapper.updateByExampleSelective(stateDuratime, stateDuratimeExample);
        }
    }

}
