package com.gyee.generation.task.thread;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.gyee.common.contant.ContantXk;
import com.gyee.common.model.PointData;
import com.gyee.generation.init.CacheContext;
import com.gyee.generation.model.auto.*;
import com.gyee.generation.model.vo.StatData;
import com.gyee.generation.service.auto.IProEconBrownoutsEvent2Service;
import com.gyee.generation.service.auto.IProEconBrownoutsEventService;
import com.gyee.generation.util.DateUtils;
import com.gyee.generation.util.StringUtils;
import com.gyee.generation.util.realtimesource.IEdosUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.*;
import java.util.concurrent.Callable;

public class BrownoutsThreadPool implements Callable<String>, Serializable {

    private Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final long serialVersionUID = 0;

    // 保存任务所需要的数据

    private Object threadPoolTaskData;
    private Map<String, List<PointData>> statusMap;

    private String wtId;
    private Map<String, ProEconBrownoutsEvent> oldBrownoutsStatusMap;

    private Map<String, ProEconBrownoutsEvent2> oldBrownoutsStatus2Map;

    private IProEconBrownoutsEventService proEconBrownoutsEventService;

    private IProEconBrownoutsEvent2Service proEconBrownoutsEvent2Service;

    private Map<Integer, String> statusDescriptionMap;

    private Map<String, Map<String, ProEconMainBrownouts2>> newMainBrownouts2Map;
    private Map<String, Map<String, ProEconMainBrownouts>> newMainBrownoutsMap;
    private IEdosUtil edosUtil;
    private Date begin;
    private Date end;


    public BrownoutsThreadPool(Object tasks,
                               Map<String, List<PointData>> statusMap, String wtId,
                               Map<String, ProEconBrownoutsEvent> oldBrownoutsStatusMap,
                               Map<String, ProEconBrownoutsEvent2> oldBrownoutsStatus2Map,
                               IProEconBrownoutsEventService proEconBrownoutsEventService,
                               IProEconBrownoutsEvent2Service proEconBrownoutsEvent2Service,
                               Map<Integer, String> statusDescriptionMap,
                               Map<String, Map<String, ProEconMainBrownouts2>> newMainBrownouts2Map,
                               Map<String, Map<String, ProEconMainBrownouts>> newMainBrownoutsMap,
                               IEdosUtil edosUtil, Date begin, Date end

    ) {

        this.threadPoolTaskData = tasks;
        this.statusMap = statusMap;
        this.wtId = wtId;
        this.oldBrownoutsStatusMap = oldBrownoutsStatusMap;
        this.oldBrownoutsStatus2Map = oldBrownoutsStatus2Map;
        this.proEconBrownoutsEventService = proEconBrownoutsEventService;
        this.proEconBrownoutsEvent2Service = proEconBrownoutsEvent2Service;
        this.statusDescriptionMap = statusDescriptionMap;
        this.newMainBrownoutsMap = newMainBrownoutsMap;
        this.newMainBrownouts2Map = newMainBrownouts2Map;
        this.begin = begin;
        this.end = end;
        this.edosUtil = edosUtil;


    }

    public synchronized String call() throws Exception {


        // 处理一个任务，这里的处理方式太简单了，仅仅是一个打印语句

        //System.out.println("开始执行任务：" + threadPoolTaskData);

        String result = "";

        // //便于观察，等待一段时间


        try {


            Map<String, ProBasicEquipmentPoint> windturbinetestingpointnewMap = CacheContext.wtpAimap.get(wtId);

            //取实时状态数据 赋值给status

            if (windturbinetestingpointnewMap.containsKey(ContantXk.MXZT)) {
                ProBasicEquipmentPoint mxztPoint = windturbinetestingpointnewMap.get(ContantXk.MXZT);
                //获取5分钟没个间隔1秒钟，保证状态与时序库保持一致
                List<PointData> statusls = edosUtil.getHistoryDatasSnap(mxztPoint.getNemCode(), begin.getTime() / 1000, end.getTime() / 1000, null, 1L);
                statusMap.put(wtId, statusls);
            }

            List<ProEconBrownoutsEvent2> proEconBrownoutsEvent2ls = new ArrayList<>();
            List<ProEconBrownoutsEvent> proEconBrownoutsEventls = new ArrayList<>();


            ProEconBrownoutsEvent brownoutsEvent = null;
            ProEconBrownoutsEvent2 brownoutsEvent2;
            //获取5分钟的状态值
            List<PointData> statusls = statusMap.get(wtId);

            Map<String, ProBasicEquipmentPoint> wtpointmap = CacheContext.wtpAimap.get(wtId);
            //记录上次判定的状态值
            int lastStatus = (int) statusls.get(0).getPointValueInDouble();
            for (PointData stpo : statusls) {
                //获取当前状态
                int currentStatus = (int) stpo.getPointValueInDouble();
                //获取当前时间
                Date currentTime = new Date(stpo.getPointTime());
                //如果数据库中不存在该风机未完成的故障记录，进入
                if (brownoutsEvent == null) {
                    if (currentStatus == 8 || currentStatus == 9) {
                        brownoutsEvent = new ProEconBrownoutsEvent();
                        initialBrownoutsEvent(wtId, wtpointmap, currentStatus, currentTime, brownoutsEvent);
                        oldBrownoutsStatusMap.put(wtId, brownoutsEvent);

                        brownoutsEvent2 = new ProEconBrownoutsEvent2();
                        initialBrownoutsEvent2(wtId, wtpointmap, currentStatus, currentTime, brownoutsEvent2);
                        oldBrownoutsStatus2Map.put(wtId, brownoutsEvent2);
                    }


                    //将当前状态赋值给过去状态
                    lastStatus = currentStatus;
                } else if (lastStatus != currentStatus) {

                    //如果添加了状态值，状态值变化存储，并清空
                    if (oldBrownoutsStatusMap.containsKey(wtId)) {

                        //获取数据库中的状态值，状态值变化存储，并清空
                        brownoutsEvent = oldBrownoutsStatusMap.get(wtId);
                        if (brownoutsEvent == null) {
                            brownoutsEvent = new ProEconBrownoutsEvent();
                            initialBrownoutsEvent(wtId, wtpointmap, currentStatus, currentTime, brownoutsEvent);
                            oldBrownoutsStatusMap.put(wtId, brownoutsEvent);
                        } else {
                            finishBrownoutsEvent(wtId, brownoutsEvent, currentTime);
                            oldBrownoutsStatusMap.put(wtId, null);
                            brownoutsEvent = null;
                        }


                    }

                    if (oldBrownoutsStatus2Map.containsKey(wtId)) {

                        //获取数据库中的状态值，状态值变化存储，并清空
                        brownoutsEvent2 = oldBrownoutsStatus2Map.get(wtId);
                        if (brownoutsEvent2 == null) {
                            brownoutsEvent2 = new ProEconBrownoutsEvent2();
                            initialBrownoutsEvent2(wtId, wtpointmap, currentStatus, currentTime, brownoutsEvent2);
                            oldBrownoutsStatus2Map.put(wtId, brownoutsEvent2);
                        } else {
                            finishBrownoutsEvent2(wtId, brownoutsEvent2, currentTime);
                            oldBrownoutsStatus2Map.put(wtId, null);
                        }


                    }


                    lastStatus = currentStatus;
                }


            }
            //循环结束落盘，并清空
            if (oldBrownoutsStatusMap.containsKey(wtId)) {
                //获取数据库查询是否有风机对应时间的记录，如果没有写入数据库
                brownoutsEvent = oldBrownoutsStatusMap.get(wtId);
                if (brownoutsEvent != null) {
                    ProEconBrownoutsEvent finalItem = brownoutsEvent;
                    QueryWrapper<ProEconBrownoutsEvent> queryWrapper5 = new QueryWrapper<>();
                    queryWrapper5.eq("windpowerstation_id", finalItem.getWindpowerstationId()).eq("stop_Time", finalItem.getStopTime());
                    List<ProEconBrownoutsEvent> ls = proEconBrownoutsEventService.list(queryWrapper5);
                    //                            .stream().filter(i -> i.getWindpowerstationId().equals(finalItem.getWindpowerstationId())
                    //                                    && i.getStopTime().compareTo(finalItem.getStopTime()) == 0).collect(Collectors.toList());

                    if (ls.isEmpty()) {
                        proEconBrownoutsEventService.save(finalItem);
                        oldBrownoutsStatusMap.put(wtId, null);

                    }
                }


            }


            if (oldBrownoutsStatus2Map.containsKey(wtId)) {
                //获取数据库查询是否有风机对应时间的记录，如果没有写入数据库
                brownoutsEvent2 = oldBrownoutsStatus2Map.get(wtId);
                if (brownoutsEvent2 != null) {
                    ProEconBrownoutsEvent2 finalItem = brownoutsEvent2;
                    QueryWrapper<ProEconBrownoutsEvent2> queryWrapper5 = new QueryWrapper<>();
                    queryWrapper5.eq("windpowerstation_id", finalItem.getWindpowerstationId()).eq("stop_Time", finalItem.getStopTime());
                    List<ProEconBrownoutsEvent2> ls = proEconBrownoutsEvent2Service.list(queryWrapper5);
                    //                            .stream().filter(i -> i.getWindpowerstationId().equals(finalItem.getWindpowerstationId())
                    //                                    && i.getStopTime().compareTo(finalItem.getStopTime()) == 0).collect(Collectors.toList());

                    if (ls.isEmpty()) {
                        proEconBrownoutsEvent2Service.save(finalItem);
                        oldBrownoutsStatus2Map.put(wtId, null);

                    }
                }

            }

            List<ProEconBrownoutsEvent> templs = new ArrayList<>();
            for (ProEconBrownoutsEvent vo : proEconBrownoutsEventls) {
                templs.add(vo);
                if (templs.size() == 1000) {
                    proEconBrownoutsEventService.saveOrUpdateBatch(templs);
                    templs = new ArrayList<>();
                }
            }

            if (!templs.isEmpty()) {
                proEconBrownoutsEventService.saveOrUpdateBatch(templs);
            }


            List<ProEconBrownoutsEvent2> templs2 = new ArrayList<>();
            for (ProEconBrownoutsEvent2 vo : proEconBrownoutsEvent2ls) {
                templs2.add(vo);
                if (templs2.size() == 1000) {
                    proEconBrownoutsEvent2Service.saveOrUpdateBatch(templs2);
                    templs2 = new ArrayList<>();
                }
            }

            if (!templs2.isEmpty()) {
                proEconBrownoutsEvent2Service.saveOrUpdateBatch(templs2);
            }


            //            proEconBrownoutsEventService.saveOrUpdateBatch(proEconBrownoutsEventls);
            //            proEconBrownoutsEvent2Service.saveOrUpdateBatch(proEconBrownoutsEvent2ls);
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


        threadPoolTaskData = null;

        return result;

    }

    private void initialBrownoutsEvent(String wtId, Map<String, ProBasicEquipmentPoint> wtpointmap, Integer currentStatus, Date currentTime, ProEconBrownoutsEvent sub) throws Exception {
        ProBasicEquipment wt = CacheContext.wtmap.get(wtId);
        Map<String, ProEconMainBrownouts> timemap = null;
        if (newMainBrownoutsMap.containsKey(wt.getWindpowerstationId())) {
            timemap = newMainBrownoutsMap.get(wt.getWindpowerstationId());
        } else {
            timemap = new HashMap<>();
            newMainBrownoutsMap.put(wt.getWindpowerstationId(), timemap);
        }
        if (timemap.containsKey(String.valueOf(currentTime))) {
            ProEconMainBrownouts mainObj = timemap.get(String.valueOf(currentTime));
            sub.setMainId(mainObj.getId());
        }


        sub.setId(StringUtils.getUUID());
        sub.setWindpowerstationId(wt.getWindpowerstationId());
        sub.setWindturbineId(wt.getId());
        sub.setProjectId(wt.getProjectId());
        sub.setLineId(wt.getLineId());
        sub.setStopTime(currentTime);
        sub.setStartTime(null);
        sub.setStopHours(0.0);
        sub.setLossPower(0.0);

        sub.setStopTypeId(statusDescriptionMap.get(currentStatus));


        PointData data = edosUtil.getRealData(wtpointmap.get(ContantXk.CJ_SSGL));
        sub.setLimitLoad(StringUtils.round(data.getPointValueInDouble(), 2));
        data = edosUtil.getRealData(wtpointmap.get(ContantXk.CJ_SSFS));
        sub.setWindSpeed(StringUtils.round(data.getPointValueInDouble(), 2));


        long pried = DateUtils.secondsDiff(DateUtils.addMinutes(currentTime, -5), currentTime);
        List<PointData> hsls = edosUtil.getHistStat(wtpointmap.get(ContantXk.CJ_SSGL), DateUtils.addMinutes(currentTime, -5).getTime() / 1000, currentTime.getTime() / 1000, 1L, pried, StatData.MAX.getValue());
        if (StringUtils.notEmp(hsls) && hsls.size() > 0) {
            sub.setThisLoad(hsls.get(0).getPointValueInDouble());


            oldBrownoutsStatusMap.put(wtId, sub);
        }

    }

    private void initialBrownoutsEvent2(String wtId, Map<String, ProBasicEquipmentPoint> wtpointmap, Integer currentStatus, Date currentTime, ProEconBrownoutsEvent2 sub) throws Exception {
        ProBasicEquipment wt = CacheContext.wtmap.get(wtId);
        Map<String, ProEconMainBrownouts2> timemap = null;
        if (newMainBrownouts2Map.containsKey(wt.getWindpowerstationId())) {
            timemap = newMainBrownouts2Map.get(wt.getWindpowerstationId());

        } else {
            timemap = new HashMap<>();
            newMainBrownouts2Map.put(wt.getWindpowerstationId(), timemap);
        }
        if (timemap.containsKey(String.valueOf(currentTime))) {
            ProEconMainBrownouts2 mainObj = timemap.get(String.valueOf(currentTime));
            sub.setMainId(mainObj.getId());
        }

        sub.setId(StringUtils.getUUID());
        sub.setWindpowerstationId(wt.getWindpowerstationId());
        sub.setWindturbineId(wt.getId());
        sub.setProjectId(wt.getProjectId());
        sub.setLineId(wt.getLineId());
        sub.setStopTime(currentTime);
        sub.setStartTime(null);
        sub.setStopHours(0.0);
        sub.setLossPower(0.0);
        sub.setStopTypeId(statusDescriptionMap.get(currentStatus));


        PointData data = edosUtil.getRealData(wtpointmap.get(ContantXk.CJ_SSGL));
        sub.setLimitLoad(StringUtils.round(data.getPointValueInDouble(), 2));
        data = edosUtil.getRealData(wtpointmap.get(ContantXk.CJ_SSFS));
        sub.setWindSpeed(StringUtils.round(data.getPointValueInDouble(), 2));


        long pried = DateUtils.secondsDiff(DateUtils.addMinutes(currentTime, -5), currentTime);
        List<PointData> hsls = edosUtil.getHistStat(wtpointmap.get(ContantXk.CJ_SSGL), DateUtils.addMinutes(currentTime, -5).getTime() / 1000, currentTime.getTime() / 1000, 1L, pried, StatData.MAX.getValue());
        if (StringUtils.notEmp(hsls) && hsls.size() > 0) {
            sub.setThisLoad(hsls.get(0).getPointValueInDouble());

        }

        oldBrownoutsStatus2Map.put(wtId, sub);


    }


    private void finishBrownoutsEvent(String wpId, ProEconBrownoutsEvent item, Date currentTime) throws Exception {
        //        if (currentStatus != 8 && currentStatus != 9)
        //        {
        item.setStartTime(currentTime);
        double timehour = DateUtils.hoursDiff2(item.getStartTime(), item.getStopTime());
        item.setStopHours(timehour);
        double losspower = calLossPower(wpId, item.getStartTime(), item.getStopTime());
        item.setLossPower(losspower);
        proEconBrownoutsEventService.saveOrUpdate(item);


        //       }
    }

    private void finishBrownoutsEvent2(String wpId, ProEconBrownoutsEvent2 brownoutsEvent2, Date currentTime) throws Exception {
        //        if (currentStatus != 8 && currentStatus != 9)
        //        {
        brownoutsEvent2.setStartTime(currentTime);

        double timehour = DateUtils.hoursDiff2(brownoutsEvent2.getStartTime(), brownoutsEvent2.getStopTime());
        brownoutsEvent2.setStopHours(timehour);
        double losspower = calLossPower(wpId, brownoutsEvent2.getStartTime(), brownoutsEvent2.getStopTime());
        brownoutsEvent2.setLossPower(losspower);

        if (timehour <= 24) {
            proEconBrownoutsEvent2Service.saveOrUpdate(brownoutsEvent2);
        } else {
            int days = DateUtils.daysDiff1(brownoutsEvent2.getStartTime(), brownoutsEvent2.getStopTime());
            Calendar c = Calendar.getInstance();
            Date startTime = brownoutsEvent2.getStartTime();
            c.setTime(brownoutsEvent2.getStopTime());
            c.set(Calendar.HOUR_OF_DAY, 23);
            c.set(Calendar.MINUTE, 59);
            c.set(Calendar.SECOND, 59);
            for (int i = 0; i < days; i++) {
                if (i == 0) {
                    brownoutsEvent2.setStartTime(c.getTime());
                    losspower = calLossPower(wpId, brownoutsEvent2.getStartTime(), brownoutsEvent2.getStopTime());

                } else {
                    brownoutsEvent2.setStopTime(DateUtils.truncate(c.getTime()));
                    if (i == days - 1) {
                        brownoutsEvent2.setStartTime(startTime);

                    } else {
                        brownoutsEvent2.setStartTime(c.getTime());

                    }
                    losspower = calLossPower(wpId, brownoutsEvent2.getStartTime(), brownoutsEvent2.getStopTime());
                }
                brownoutsEvent2.setLossPower(losspower);
                proEconBrownoutsEvent2Service.saveOrUpdate(brownoutsEvent2);


                c.add(Calendar.DAY_OF_MONTH, 1);
            }
        }


        //        }

    }


    //修改后的限电损失统计，通过时序数据库历史切面计算
    private Double calLossPower(String windturbineId, Date startDate, Date endDate) throws Exception {
        double result = 0.0;

        Map<String, Map<String, ProBasicEquipmentPoint>> wtpAimap = CacheContext.wtpAimap;
        Map<String, ProBasicEquipmentPoint> wtpointmap = wtpAimap.get(windturbineId);

        Calendar c1 = Calendar.getInstance();
        c1.setTime(startDate);
        Calendar c2 = Calendar.getInstance();
        c2.setTime(endDate);
        //判定限电是否跨年
        if (endDate.after(startDate) && c1.get(Calendar.YEAR) == c2.get(Calendar.YEAR)) {
            //年限电欠发损失电量
            if (wtpointmap.containsKey(ContantXk.NXDTJSSDL)) {
                double beginvalue;
                double endvalue;


                List<String> pointid = new ArrayList<>();
                pointid.add(wtpointmap.get(ContantXk.NXDTJSSDL).getNemCode());
                List<PointData> xdbegin = edosUtil.getHistMatrix(pointid, startDate.getTime() / 1000);
                List<PointData> xdend = edosUtil.getHistMatrix(pointid, endDate.getTime() / 1000);


                if (xdbegin.size() == 1 && xdend.size() == 1) {
                    beginvalue = xdbegin.get(0).getPointValueInDouble();
                    endvalue = xdend.get(0).getPointValueInDouble();

                    if (endvalue > beginvalue) {
                        result = result + (endvalue - beginvalue);
                    }
                }
            }

            //年限电损失电量
            if (wtpointmap.containsKey(ContantXk.NXDJCLSSDL)) {
                double beginvalue;
                double endvalue;

                List<String> pointid = new ArrayList<>();
                pointid.add(wtpointmap.get(ContantXk.NXDJCLSSDL).getNemCode());
                List<PointData> xdbegin = edosUtil.getHistMatrix(pointid, startDate.getTime() / 1000);
                List<PointData> xdend = edosUtil.getHistMatrix(pointid, endDate.getTime() / 1000);


                if (xdbegin.size() == 1 && xdend.size() == 1) {
                    beginvalue = xdbegin.get(0).getPointValueInDouble();
                    endvalue = xdend.get(0).getPointValueInDouble();

                    if (endvalue > beginvalue) {
                        result = result + (endvalue - beginvalue);
                    }
                }
            }
        } else {
            Calendar c = Calendar.getInstance();
            c.setTime(DateUtils.truncate(startDate));
            c.add(Calendar.DAY_OF_MONTH, 1);
            //获得1月1日零点值
            Date endtime = c.getTime();
            //年限电欠发损失电量
            if (wtpointmap.containsKey(ContantXk.NXDTJSSDL)) {
                double beginvalue;
                double endvalue;

                List<String> pointid = new ArrayList<>();
                pointid.add(wtpointmap.get(ContantXk.NXDTJSSDL).getNemCode());
                List<PointData> xdbegin = edosUtil.getHistMatrix(pointid, startDate.getTime() / 1000);
                List<PointData> xdend = edosUtil.getHistMatrix(pointid, endtime.getTime() / 1000);


                if (xdbegin.size() == 1 && xdend.size() == 1) {
                    beginvalue = xdbegin.get(0).getPointValueInDouble();
                    endvalue = xdend.get(0).getPointValueInDouble();

                    if (endvalue > beginvalue) {
                        result = result + (endvalue - beginvalue);
                    }
                }
            }

            //年限电损失电量
            if (wtpointmap.containsKey(ContantXk.NXDJCLSSDL)) {
                double beginvalue;
                double endvalue;

                List<String> pointid = new ArrayList<>();
                pointid.add(wtpointmap.get(ContantXk.NXDJCLSSDL).getNemCode());
                List<PointData> xdbegin = edosUtil.getHistMatrix(pointid, startDate.getTime() / 1000);
                List<PointData> xdend = edosUtil.getHistMatrix(pointid, endtime.getTime() / 1000);


                if (xdbegin.size() == 1 && xdend.size() == 1) {
                    beginvalue = xdbegin.get(0).getPointValueInDouble();
                    endvalue = xdend.get(0).getPointValueInDouble();

                    if (endvalue > beginvalue) {
                        result = result + (endvalue - beginvalue);
                    }
                }
            }


            //日限电欠发损失电量
            if (wtpointmap.containsKey(ContantXk.NXDTJSSDL)) {

                double endvalue;


                List<String> pointid = new ArrayList<>();
                pointid.add(wtpointmap.get(ContantXk.NXDTJSSDL).getNemCode());

                List<PointData> xdend = edosUtil.getHistMatrix(pointid, endDate.getTime() / 1000);


                if (xdend.size() == 1) {

                    endvalue = xdend.get(0).getPointValueInDouble();

                    if (endvalue > 0) {
                        result = result + endvalue;
                    }
                }
            }

            //日限电损失电量
            if (wtpointmap.containsKey(ContantXk.NXDJCLSSDL)) {

                double endvalue;


                List<String> pointid = new ArrayList<>();
                pointid.add(wtpointmap.get(ContantXk.NXDJCLSSDL).getNemCode());

                List<PointData> xdend = edosUtil.getHistMatrix(pointid, endDate.getTime() / 1000);


                if (xdend.size() == 1) {

                    endvalue = xdend.get(0).getPointValueInDouble();

                    if (endvalue > 0) {
                        result = result + endvalue;
                    }
                }
            }
        }


        return result;

    }
}