package com.njcn.advance.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.SerializeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.njcn.advance.enums.AdvanceResponseEnum;
import com.njcn.advance.mapper.RelevantLogMapper;
import com.njcn.advance.mapper.RmpEventAdvanceMapper;
import com.njcn.advance.mapper.RmpEventDetailAssMapper;

import com.njcn.advance.pojo.dto.relevent.*;
import com.njcn.advance.pojo.po.PqsRelevanceLog;
import com.njcn.advance.service.EventRelevantAnalysisService;

import com.njcn.advance.utils.UtilNormalization;
import com.njcn.common.pojo.enums.common.DataStateEnum;
import com.njcn.common.pojo.exception.BusinessException;
import com.njcn.common.utils.PubUtils;
import com.njcn.device.pq.api.GeneralDeviceInfoClient;
import com.njcn.device.pq.api.LineFeignClient;
import com.njcn.device.pq.pojo.po.PqsTflgployass;
import com.njcn.device.pq.pojo.vo.AreaLineInfoVO;
import com.njcn.event.pojo.po.RmpEventDetailAssPO;
import com.njcn.event.pojo.po.RmpEventDetailPO;
import com.njcn.event.pojo.vo.AdvanceEventDetailVO;
import com.njcn.redis.utils.RedisUtil;
import com.njcn.system.api.DicDataFeignClient;
import com.njcn.system.enums.DicDataEnum;
import com.njcn.system.enums.DicDataTypeEnum;
import com.njcn.system.enums.SystemResponseEnum;
import com.njcn.system.pojo.po.DictData;
import com.njcn.user.api.UserFeignClient;
import com.njcn.user.pojo.po.User;
import com.njcn.web.factory.PageFactory;
import com.njcn.web.pojo.param.BaseParam;
import com.njcn.web.utils.RequestUtil;
import io.swagger.models.auth.In;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.sf.json.JSONObject;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * pqs
 *
 * @author cdf
 * @date 2023/6/30
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class EventRelevantAnalysisServiceImpl extends ServiceImpl<RmpEventAdvanceMapper, RmpEventDetailPO> implements EventRelevantAnalysisService {

    private final String redisSortKey = "NODESORT";


    private final DicDataFeignClient dicDataFeignClient;

    private final RelevantLogMapper relevantLogMapper;

    private final GeneralDeviceInfoClient generalDeviceInfoClient;

    private final RmpEventAdvanceMapper eventAdvanceMapper;

    private final LineFeignClient lineFeignClient;

    private final RmpEventDetailAssMapper rmpEventDetailAssMapper;

    private final UserFeignClient userFeignClient;

    private final RedisUtil redisUtil;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void processEvents(LocalDateTime startTime, LocalDateTime endTime) {

        TimeInterval timeInterval = new TimeInterval();


        LocalDateTime date = LocalDateTime.now();
        HandleEvent handleEvent = new HandleEvent();
        // 分析的事件进行处理
        List<EntityGroupEvtData> baseList = handleEvent.getData(startTime, endTime);
        if (CollectionUtil.isEmpty(baseList)) {
            throw new BusinessException("当前时间段暂无可分析事件");
        }
        List<EntityGroupEvtData> list3 = new ArrayList<>(baseList);



        Map<String, EntityMtrans> entityMtransMap = getNodeInfo();
        Set<Map.Entry<String, EntityMtrans>> setMtrans = entityMtransMap.entrySet();

        List<SagEvent> listSagEvent = new ArrayList<>();
        List<EventAssObj> listEventAssObj = new ArrayList<>();

        Map<String, Map<String, Integer>> nodeMap = (Map<String, Map<String, Integer>>)redisUtil.getObjectByKey(redisSortKey);
        Set<Map.Entry<String, Map<String, Integer>>> nodeSort = nodeMap.entrySet();


        DictData dictData = dicDataFeignClient.getDicDataByNameAndTypeName(DicDataTypeEnum.EVENT_REASON.getName(), DicDataEnum.SHORT_TROUBLE.getName()).getData();
        if (Objects.isNull(dictData)) {
            throw new BusinessException(SystemResponseEnum.ADVANCE_REASON);
        }

        for (Map.Entry<String, Map<String, Integer>> m : nodeSort) {
            List<EntityGroupEvtData> list = new ArrayList<EntityGroupEvtData>();
            Set<Map.Entry<String, Integer>> mapValue = m.getValue().entrySet();
            FinalData.NODE_NUM = m.getValue().size();

            for (Map.Entry<String, Integer> mm : mapValue) {
                for (EntityGroupEvtData groupEvtData : baseList) {
                    if (groupEvtData.getNodePhysics().equals(mm.getKey()) && dictData.getId().equals(groupEvtData.getSagReason())) {
                        groupEvtData.setNode(mm.getValue());
                        list.add(groupEvtData);
                    }
                }

                // 筛选不在矩阵中的事件id
                list3.removeIf(entityGroupEvtData -> entityGroupEvtData.getNodePhysics().equals(mm.getKey()) && dictData.getId().equals(entityGroupEvtData.getSagReason()));
            }

            EntityGroupEvtData[] entityGroupEvtData = new EntityGroupEvtData[list.size()];
            Collections.sort(list);
            list.toArray(entityGroupEvtData);

            for (Map.Entry<String, EntityMtrans> mEntry : setMtrans) {
                if (mEntry.getKey().equals(m.getKey())) {

                    //算法最多处理1000条数据，超过限制需分批处理 先将数据根据某种方式进行升序/降序排序，然后分段处理 加入循环处理

                    int circulation = entityGroupEvtData.length % FinalData.MAX_EVT_NUM == 0
                            ? entityGroupEvtData.length / FinalData.MAX_EVT_NUM
                            : entityGroupEvtData.length / FinalData.MAX_EVT_NUM + 1;

                    for (int i = 0; i < circulation; i++) {
                        int to = 0;

                        if (i == circulation - 1) {
                            to = entityGroupEvtData.length % FinalData.MAX_EVT_NUM > 0
                                    ? entityGroupEvtData.length
                                    : (i + 1) * FinalData.MAX_EVT_NUM - 1;
                        } else {
                            to = (i + 1) * FinalData.MAX_EVT_NUM - 1;
                        }

                        EntityGroupEvtData[] arrayObj = Arrays.copyOfRange(entityGroupEvtData,
                                i * FinalData.MAX_EVT_NUM, to);
                        EntityMtrans entityMtrans = mEntry.getValue();
                        EntityGroupData entityGroupData = handleEvent.translate(arrayObj, entityMtrans);
                        // 处理分析结果
                        handleEvent.show_group_info(entityGroupData, listSagEvent, listEventAssObj, date);
                    }
                }
            }
        }


        disposeNonStandardData(handleEvent, baseList, listEventAssObj, listSagEvent, date);


        int listSize = listEventAssObj.size();
        int toIndex = 1000;
        for (int i = 0; i < listSize; i += 1000) {
            //作用为toIndex最后没有toIndex条数据则剩余几条newList中就装几条
            if (i + 1000 > listSize) {
                toIndex = listSize - i;
            }
            //分割lst
            List<EventAssObj> newList = listEventAssObj.subList(i, i + toIndex);
            //写入添加方法,需要写你的新增方法，把newList分切后的数据新增进入数据库。
            rmpEventDetailAssMapper.insertEventAssData(newList);
        }

        List<RmpEventDetailPO> eventUpdateList = new ArrayList<>();
        for (int i = 0; i < listSagEvent.size(); i++) {
            RmpEventDetailPO rmp = new RmpEventDetailPO();
            rmp.setEventId(listSagEvent.get(i).getIndexEventDetail());
            rmp.setEventassIndex(listSagEvent.get(i).getIndexEventAss());
            rmp.setDealTime(listSagEvent.get(i).getDealTime());
            eventUpdateList.add(rmp);
            if ((i + 1) % 1000 == 0) {
                this.updateBatchById(eventUpdateList);
                eventUpdateList.clear();
            } else if (i == listSagEvent.size() - 1) {
                this.updateBatchById(eventUpdateList);
            }
        }

        // 增加策略记录
        String describe = "用户" + RequestUtil.getUserNickname() + "进行了关联分析";
        PqsRelevanceLog entityPqsRelevance = new PqsRelevanceLog();
        entityPqsRelevance.setContentDes(describe);
        entityPqsRelevance.setState(DataStateEnum.ENABLE.getCode());
        entityPqsRelevance.setTimeId(date);
        relevantLogMapper.insert(entityPqsRelevance);


        log.info("事件关联分析用时：" + timeInterval.interval() / 1000 + "秒");
    }




    @Override
    public Page<AdvanceEventDetailVO> querySagEventsPage(BaseParam baseParam) {
        List<String> lineIds = generalDeviceInfoClient.deptGetRunLineEvent(RequestUtil.getDeptIndex()).getData();
        if (CollUtil.isEmpty(lineIds)) {
            throw new BusinessException("当前部门下不存在监测点");
        }
        List<LocalDateTime> vTime = PubUtils.checkLocalDate(baseParam.getSearchBeginTime(), baseParam.getSearchEndTime());
        LambdaQueryWrapper<RmpEventDetailPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.and(i -> i.isNull(RmpEventDetailPO::getEventassIndex).or().eq(RmpEventDetailPO::getEventassIndex, ""))
                .between(RmpEventDetailPO::getStartTime, vTime.get(0), vTime.get(1)).orderByAsc(RmpEventDetailPO::getStartTime);

        Page<RmpEventDetailPO> poPage = eventAdvanceMapper.selectPage(new Page<>(PageFactory.getPageNum(baseParam), PageFactory.getPageSize(baseParam)), lambdaQueryWrapper);
        List<RmpEventDetailPO> rmpEventDetailPOList = poPage.getRecords();

        if (CollectionUtil.isEmpty(rmpEventDetailPOList)) {
            return new Page<>();
        }

        List<String> tempLineIds = rmpEventDetailPOList.stream().map(RmpEventDetailPO::getLineId).distinct().collect(Collectors.toList());

        List<AreaLineInfoVO> temLine = lineFeignClient.getBaseLineAreaInfo(tempLineIds).getData();
        Map<String, AreaLineInfoVO> map = temLine.stream().collect(Collectors.toMap(AreaLineInfoVO::getLineId, Function.identity()));

        List<AdvanceEventDetailVO> advanceEventDetailVOList = BeanUtil.copyToList(rmpEventDetailPOList, AdvanceEventDetailVO.class);
        advanceEventDetailVOList = advanceEventDetailVOList.stream().peek(item -> {
            item.setFeatureAmplitude(roundHalfUp(item.getFeatureAmplitude() * 100));

            if (map.containsKey(item.getLineId())) {
                AreaLineInfoVO areaLineInfoVO = map.get(item.getLineId());
                item.setGdName(areaLineInfoVO.getGdName());
                item.setSubName(areaLineInfoVO.getSubName());
                item.setLineName(areaLineInfoVO.getLineName());
                item.setNum(areaLineInfoVO.getNum());
                item.setVoltageId(areaLineInfoVO.getVoltageId());
            }
        }).collect(Collectors.toList());


        Page<AdvanceEventDetailVO> page = new Page<>(poPage.getCurrent(), poPage.getSize());
        page.setTotal(poPage.getTotal());
        page.setRecords(advanceEventDetailVOList);
        return page;


    }

    /**
     * 四舍五入保留两位小数
     */
    private Double roundHalfUp(double num) {
        if (num == 3.14159) {
            return num;
        }
        BigDecimal b = new BigDecimal(num);
        //保留2位小数
        return com.njcn.harmonic.utils.PubUtils.dataLimits(b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue());
    }

    @Override
    public Page<RmpEventDetailAssPO> queryEventsAssPage(BaseParam baseParam) {
        List<LocalDateTime> timeV = PubUtils.checkLocalDate(baseParam.getSearchBeginTime(), baseParam.getSearchEndTime());
        LambdaQueryWrapper<RmpEventDetailAssPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        if (StrUtil.isNotBlank(baseParam.getSearchValue())) {
            lambdaQueryWrapper.like(RmpEventDetailAssPO::getContentDes, baseParam.getSearchValue());
        }
        lambdaQueryWrapper.between(RmpEventDetailAssPO::getTimeId, timeV.get(0), timeV.get(1))
                .orderByDesc(RmpEventDetailAssPO::getTimeId);
        return rmpEventDetailAssMapper.selectPage(new Page<>(PageFactory.getPageNum(baseParam), PageFactory.getPageSize(baseParam)), lambdaQueryWrapper);
    }

    @Override
    public Page<AdvanceEventDetailVO> queryEventDetailByAssId(String assId, Integer pageNum, Integer pageSize) {
        Page<AdvanceEventDetailVO> pageResult = new Page<>(pageNum, pageSize);

        LambdaQueryWrapper<RmpEventDetailPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(RmpEventDetailPO::getEventassIndex, assId)
                .orderByAsc(RmpEventDetailPO::getStartTime);
        Page<RmpEventDetailPO> page = eventAdvanceMapper.selectPage(new Page<>(pageNum, pageSize), lambdaQueryWrapper);
        List<RmpEventDetailPO> pos = page.getRecords();
        if (CollectionUtil.isEmpty(pos)) {
            return pageResult;
        }

        List<String> lineIds = pos.stream().map(RmpEventDetailPO::getMeasurementPointId).distinct().collect(Collectors.toList());
        List<AreaLineInfoVO> lineAres = lineFeignClient.getBaseLineAreaInfo(lineIds).getData();
        Map<String, AreaLineInfoVO> map = lineAres.stream().collect(Collectors.toMap(AreaLineInfoVO::getLineId, Function.identity()));


        List<AdvanceEventDetailVO> advanceEventDetailVOList = BeanUtil.copyToList(pos, AdvanceEventDetailVO.class);
        advanceEventDetailVOList = advanceEventDetailVOList.stream().peek(item -> {
            if (map.containsKey(item.getMeasurementPointId())) {
                AreaLineInfoVO areaLineInfoVO = map.get(item.getMeasurementPointId());
                item.setGdName(areaLineInfoVO.getGdName());
                item.setSubName(areaLineInfoVO.getSubName());
                item.setLineName(areaLineInfoVO.getLineName());
                item.setVoltageId(areaLineInfoVO.getVoltageScale());
            }
        }).collect(Collectors.toList());
        pageResult.setRecords(advanceEventDetailVOList);
        pageResult.setTotal(page.getTotal());
        return pageResult;
    }

    @Override
    public Page<AdvanceEventDetailVO> queryEventByTimeRange(BaseParam baseParam) {
        Page<AdvanceEventDetailVO> page = new Page<>(PageFactory.getPageNum(baseParam), PageFactory.getPageSize(baseParam));

        PubUtils.checkDateTime(baseParam.getSearchBeginTime());
        PubUtils.checkDateTime(baseParam.getSearchEndTime());

        LambdaQueryWrapper<RmpEventDetailPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.and(item -> item.eq(RmpEventDetailPO::getEventassIndex, "")
                .or().isNull(RmpEventDetailPO::getEventassIndex)).between(RmpEventDetailPO::getStartTime, baseParam.getSearchBeginTime(), baseParam.getSearchEndTime());
        Page<RmpEventDetailPO> poPage = eventAdvanceMapper.selectPage(new Page<>(PageFactory.getPageNum(baseParam), PageFactory.getPageSize(baseParam)), lambdaQueryWrapper);

        List<RmpEventDetailPO> detailPOList = poPage.getRecords();
        if (CollectionUtil.isEmpty(detailPOList)) {
            return page;
        }
        List<String> lineIds = detailPOList.stream().map(RmpEventDetailPO::getMeasurementPointId).distinct().collect(Collectors.toList());
        List<AreaLineInfoVO> lineAres = lineFeignClient.getBaseLineAreaInfo(lineIds).getData();
        Map<String, AreaLineInfoVO> map = lineAres.stream().collect(Collectors.toMap(AreaLineInfoVO::getLineId, Function.identity()));

        List<AdvanceEventDetailVO> aList = BeanUtil.copyToList(detailPOList, AdvanceEventDetailVO.class);
        aList = aList.stream().peek(item -> {
            if (map.containsKey(item.getMeasurementPointId())) {
                AreaLineInfoVO areaLineInfoVO = map.get(item.getMeasurementPointId());
                item.setGdName(areaLineInfoVO.getGdName());
                item.setSubName(areaLineInfoVO.getSubName());
                item.setLineName(areaLineInfoVO.getLineName());
                item.setVoltageId(areaLineInfoVO.getVoltageScale());
            }
        }).collect(Collectors.toList());

        page.setRecords(aList);
        page.setTotal(poPage.getTotal());
        return page;
    }

    @Override
    public List<AdvanceEventDetailVO> queryEventList(List<String> eventId) {
        LambdaQueryWrapper<RmpEventDetailPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.in(RmpEventDetailPO::getEventId, eventId);
        List<RmpEventDetailPO> rmpEventDetailPOList = eventAdvanceMapper.selectList(lambdaQueryWrapper);
        if (CollectionUtil.isEmpty(rmpEventDetailPOList)) {
            throw new BusinessException(AdvanceResponseEnum.EVENT_EMPTY);
        }
        List<String> tempLineIds = rmpEventDetailPOList.stream().map(RmpEventDetailPO::getLineId).distinct().collect(Collectors.toList());

        List<AreaLineInfoVO> temLine = lineFeignClient.getBaseLineAreaInfo(tempLineIds).getData();
        Map<String, AreaLineInfoVO> map = temLine.stream().collect(Collectors.toMap(AreaLineInfoVO::getLineId, Function.identity()));

        List<AdvanceEventDetailVO> advanceEventDetailVOList = BeanUtil.copyToList(rmpEventDetailPOList, AdvanceEventDetailVO.class);
        advanceEventDetailVOList = advanceEventDetailVOList.stream().peek(item -> {
            if (map.containsKey(item.getLineId())) {
                AreaLineInfoVO areaLineInfoVO = map.get(item.getLineId());
                item.setGdName(areaLineInfoVO.getGdName());
                item.setSubName(areaLineInfoVO.getSubName());
                item.setNum(areaLineInfoVO.getNum());
                item.setLineName(areaLineInfoVO.getLineName());
                item.setVoltageId(areaLineInfoVO.getVoltageScale());
            }
        }).collect(Collectors.toList());

        return advanceEventDetailVOList;
    }

    @Override
    public boolean updateEventToAss(List<String> eventId, String assId) {
        LambdaUpdateWrapper<RmpEventDetailPO> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.and(item -> item.eq(RmpEventDetailPO::getEventassIndex, "").or().isNotNull(RmpEventDetailPO::getEventassIndex))
                .in(RmpEventDetailPO::getEventId, eventId);
        RmpEventDetailPO rmpEventDetailPO = new RmpEventDetailPO();
        rmpEventDetailPO.setEventassIndex(assId);
        rmpEventDetailPO.setDealTime(LocalDateTime.now());
        eventAdvanceMapper.update(rmpEventDetailPO, lambdaUpdateWrapper);
        return true;
    }

    @Override
    public boolean delEventToAss(List<String> eventId) {
        LambdaUpdateWrapper<RmpEventDetailPO> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.in(RmpEventDetailPO::getEventId, eventId);
        RmpEventDetailPO rmpEventDetailPO = new RmpEventDetailPO();
        rmpEventDetailPO.setEventassIndex("");
        eventAdvanceMapper.update(rmpEventDetailPO, lambdaUpdateWrapper);
        return true;
    }

    @Override
    public Page<PqsRelevanceLog> queryRelevantLogPage(BaseParam baseParam) {
        LambdaQueryWrapper<PqsRelevanceLog> logLambdaQueryWrapper = new LambdaQueryWrapper<>();
        logLambdaQueryWrapper.orderByAsc(PqsRelevanceLog::getTimeId);
        Page<PqsRelevanceLog> page = relevantLogMapper.selectPage(new Page<>(PageFactory.getPageNum(baseParam), PageFactory.getPageSize(baseParam)), logLambdaQueryWrapper);
        List<PqsRelevanceLog> temList = page.getRecords();
        if (CollectionUtil.isEmpty(temList)) {
            return page;
        }
        List<String> userIds = temList.stream().map(PqsRelevanceLog::getCreateBy).distinct().collect(Collectors.toList());
        List<User> userTem = userFeignClient.getUserByIdList(userIds).getData();
        Map<String, User> map = userTem.stream().collect(Collectors.toMap(User::getId, Function.identity()));
        temList = temList.stream().peek(item -> {
            if (map.containsKey(item.getCreateBy())) {
                item.setCreateName(map.get(item.getCreateBy()).getName());
            }
        }).collect(Collectors.toList());
        page.setRecords(temList);
        return page;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean delRelevantLog(String id) {
        PqsRelevanceLog pqsRelevanceLog = relevantLogMapper.selectById(id);
        if (Objects.nonNull(pqsRelevanceLog)) {

            LambdaQueryWrapper<RmpEventDetailAssPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.eq(RmpEventDetailAssPO::getCreateTime, pqsRelevanceLog.getTimeId()).select(RmpEventDetailAssPO::getEventAssId);
            List<RmpEventDetailAssPO> rmpEventDetailAssPOList = rmpEventDetailAssMapper.selectList(lambdaQueryWrapper);
            List<String> temAssIds = rmpEventDetailAssPOList.stream().map(RmpEventDetailAssPO::getEventAssId).collect(Collectors.toList());
            if (CollectionUtil.isNotEmpty(temAssIds)) {

                rmpEventDetailAssMapper.deleteBatchIds(temAssIds);


                LambdaUpdateWrapper<RmpEventDetailPO> updateWrapper = new LambdaUpdateWrapper<>();
                updateWrapper.in(RmpEventDetailPO::getEventassIndex, temAssIds);


                RmpEventDetailPO update = new RmpEventDetailPO();
                update.setEventassIndex("");
                eventAdvanceMapper.update(update, updateWrapper);
            }

        }
        relevantLogMapper.deleteById(id);


        return true;
    }


    /**********************************************************************
     * 归集结果与非矩阵事件进行比对
     **********************************************************************/
    public void disposeNonStandardData(HandleEvent handleEvent, List<EntityGroupEvtData> noDealList, List<EventAssObj> list, List<SagEvent> list2, LocalDateTime date) {
        // 如果还有未归集的数据则单独拎为单一事件处理
        for (EntityGroupEvtData entityGroupEvtData : noDealList) {
            String strUUID = IdUtil.simpleUUID();
            entityGroupEvtData.getSagEvent().setIndexEventAss(strUUID);
            entityGroupEvtData.getSagEvent().setDealTime(date);

            List<SagEvent> dealList = new ArrayList<>();
            dealList.add(entityGroupEvtData.getSagEvent());
            handleEvent.processing(dealList, list, date);
            list2.add(entityGroupEvtData.getSagEvent());
        }
    }


    class HandleEvent {
        public EntityGroupData translate(EntityGroupEvtData[] entityGroupEvtData, EntityMtrans entityMtrans) {
            // 获取测试数据的数组长度
            int testLogNum = entityGroupEvtData.length;

            // 实例化EntityGroupData，给其中的数组分配空间
            EntityGroupData groupBuf = new EntityGroupData();

            // 填入日志
            setMatrixcata(groupBuf, entityMtrans);
            create_evt_buf(entityGroupEvtData, groupBuf, testLogNum);

            UtilNormalization.sort_Tstart(groupBuf); // 根据时标进行划分
            // 根据暂降类型进行划分
            for (int i = 0; i < groupBuf.getGrp_all_num(); i++) {
                UtilNormalization.sort_cata(groupBuf, i);
            }

            return groupBuf;
        }

        public List<EntityGroupEvtData> getData(LocalDateTime startTime, LocalDateTime endTime) {
            List<EntityGroupEvtData> entityGroupEvtDataList = new ArrayList<>();

            List<DictData> advanceType = dicDataFeignClient.getDicDataByTypeCode(DicDataTypeEnum.EVENT_TYPE.getCode()).getData();
            Map<String, DictData> advanceMap = advanceType.stream().collect(Collectors.toMap(DictData::getId, Function.identity()));

            List<AdvanceEventDetailVO> advanceEventDetailVOLsit = querySagEventsAll(startTime, endTime);

            advanceEventDetailVOLsit = advanceEventDetailVOLsit.stream().filter(temp -> StringUtils.isNotEmpty(temp.getAdvanceType())).collect(Collectors.toList());
            for (AdvanceEventDetailVO advanceEventDetailVO : advanceEventDetailVOLsit) { // 获取监测点线路序号
                //母线id
                String nodePhysics = advanceEventDetailVO.getVoltageId();

                // 根据暂降类型获取高级算法对应的编号
                int cata;
                long ll;
                int startTimeTemp;

                if (Objects.isNull(advanceEventDetailVO.getFirstType())) {
                    cata = advanceMap.get(advanceEventDetailVO.getAdvanceType()).getAlgoDescribe();
                    ll = (long) (Timestamp.valueOf(advanceEventDetailVO.getStartTime()).getTime()
                            + (advanceEventDetailVO.getDuration() * 1000));
                    startTimeTemp = (int) (ll / 1000);
                } else {
                    cata = advanceMap.get(advanceEventDetailVO.getAdvanceType()).getAlgoDescribe(); // 获取类型
                    ll = (long) (Timestamp.valueOf(advanceEventDetailVO.getFirstTime()).getTime()
                            + (advanceEventDetailVO.getFirstMs()));
                    startTimeTemp = (int) (ll / 1000);
                }

                // 填充SagEvent对象数据
                SagEvent sagEvent = new SagEvent();

                sagEvent.setIndexEventDetail(advanceEventDetailVO.getEventId());
                sagEvent.setSagTime(advanceEventDetailVO.getStartTime());
                sagEvent.setFirstTime(PubUtils.ms2Date(ll));// 必须增加，否则序列化出错
                sagEvent.setTime(Timestamp.valueOf(advanceEventDetailVO.getStartTime()).getTime());
                sagEvent.setFirstTimeMills(ll);
                sagEvent.setMsec(advanceEventDetailVO.getDuration().intValue());
                PlantInfo plantInfo = new PlantInfo();
                plantInfo.setNameBD(advanceEventDetailVO.getSubName());
                plantInfo.setNameGD(advanceEventDetailVO.getGdName());
                plantInfo.setNamePoint(advanceEventDetailVO.getLineId());
                sagEvent.setPlantInfo(plantInfo);
                sagEvent.setIndexPoint(advanceEventDetailVO.getLineId());
                sagEvent.setCata(cata);


                EntityGroupEvtData entityGroupEvtData = new EntityGroupEvtData(nodePhysics, startTimeTemp, cata, -1, sagEvent, advanceEventDetailVO.getAdvanceReason());
                entityGroupEvtDataList.add(entityGroupEvtData);
            }

            return entityGroupEvtDataList;
        }

        public void create_evt_buf(EntityGroupEvtData[] arr, EntityGroupData obj, int len) {
            System.arraycopy(arr, 0, obj.getIn_buf(), 0, arr.length);
            obj.setEvt_in_num(len);
        }

        public void create_matrixcata(List<EntityLogic> list, EntityMtrans entityMtrans) {
            EntityLogic[] node_data = new EntityLogic[list.size()];

            for (int i = 0; i < list.size(); i++) {
                node_data[i] = list.get(i);
            }

            int len = node_data.length;

            UtilNormalization.matrixcata_pro(node_data, entityMtrans, len);
        }

        public void setMatrixcata(EntityGroupData obj, EntityMtrans entityMtrans) {
            int i, j;

            for (i = 0; i < (FinalData.MAX_CATA_NUM - 1); i++) {
                for (j = 0; j < FinalData.NODE_NUM; j++) {
                    obj.getMatrixcata()[i][j] = entityMtrans.getMatrixcata1()[i][j];
                }
            }
        }

        public void show_group_info(EntityGroupData obj, List<SagEvent> list, List<EventAssObj> assEvent, LocalDateTime date) {
            int i, j, k;
            for (i = 0; i < obj.getGrp_all_num(); i++) {
                String strUUID = IdUtil.simpleUUID();
                List<SagEvent> listTem = new ArrayList<>();

                for (j = 0; j < FinalData.MAX_CATA_NUM + 2; j++) {
                    if (obj.getGrp_cata_num()[i][j] != 0) {
                        for (k = 0; k < obj.getGrp_cata_num()[i][j]; k++) {
                            obj.getGrp_cata_buf()[i][j][k].getSagEvent().setIndexEventAss(strUUID);
                            obj.getGrp_cata_buf()[i][j][k].getSagEvent().setDealTime(date);
                            listTem.add(obj.getGrp_cata_buf()[i][j][k].getSagEvent());
                            list.add(obj.getGrp_cata_buf()[i][j][k].getSagEvent());
                        }
                    }
                }

                if (!listTem.isEmpty()) {
                    processing(listTem, assEvent, date);
                }
            }
        }

        public void processing(List<SagEvent> list, List<EventAssObj> lists, LocalDateTime date) {
            // 根据暂降事件发生时间进行排序
            Collections.sort(list);
            EventAssObj eventAssObj = new EventAssObj();
            String strUUID = list.get(0).getIndexEventAss();

            // 归一化处理数据填充
            eventAssObj.setIndexEventAss(strUUID);

            // 事件发生时间
            eventAssObj.setTime(list.get(0).getSagTime());


            // 获取当前用户GUID
            eventAssObj.setIndexUser(RequestUtil.getUserIndex());

            // 是否进行范围分析 默认未分析
            eventAssObj.setbRange(1);

            // 更新时间
            eventAssObj.setUpdateTime(date);


            // 暂降事件描述
            String codeName = LocalDateTimeUtil.format(eventAssObj.getTime(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
            String describe = "事件关联分析编号" + codeName + "共包含" + list.size() + "个事件";
            eventAssObj.setDescribe(describe);

            eventAssObj.setList(list);
            lists.add(eventAssObj);
        }
    }


    /*************************************************************************************
     * 获取变压器信息并生成矩阵
     *************************************************************************************/
    public Map<String, Map<String, Integer>> getNodeBefore() {
        Map<String, EntityMtrans> entityMtranMap = new HashMap<>(32);

        HandleEvent handleEvent = new HandleEvent();
        List<EntityLogic> list = relevantLogMapper.getLogic();
        Map<String, Map<String, Integer>> setNodeSort = new HashMap<>();
        if (CollectionUtil.isNotEmpty(list)) {
            Map<String, List<String>> map = getLogicInfo(list);
            setNodeSort = nodeSort(map);
        }

        return setNodeSort;
    }


    public Map<String, EntityMtrans> getNodeInfo() {
        Map<String, EntityMtrans> entityMtranMap = new HashMap<>(32);

        HandleEvent handleEvent = new HandleEvent();
        List<EntityLogic> list = relevantLogMapper.getLogic();

        if (CollectionUtil.isNotEmpty(list)) {

            Map<String, List<String>> map = getLogicInfo(list);
            Map<String, Map<String, Integer>> setNodeSort = nodeSort(map);
            redisUtil.saveByKeyWithExpire(redisSortKey, setNodeSort, -1L);

            setNodeSort.forEach((key, val) -> {
                FinalData.NODE_NUM = val.size();
                List<EntityLogic> listNew = new ArrayList<>();

                for (EntityLogic entityLogic : list) {
                    if (entityLogic.getTPIndex().equals(key)) {
                        entityLogic.setNode_h(val.get(entityLogic.getNodeBefore()));
                        entityLogic.setNode_l(val.get(entityLogic.getNodeNext()));
                        listNew.add(entityLogic);
                    }
                }

                EntityMtrans entityMtrans = new EntityMtrans();
                handleEvent.create_matrixcata(listNew, entityMtrans);
                entityMtranMap.put(key, entityMtrans);
            });
        }
        return entityMtranMap;
    }


    /*******************************************
     * 增加排序功能并缓存进redis
     *******************************************/
    public Map<String, Map<String, Integer>> nodeSort(Map<String, List<String>> mapList) {
        Set<Map.Entry<String, List<String>>> sets = mapList.entrySet();
        Map<String, Map<String, Integer>> map = new HashMap<>();

        for (Map.Entry<String, List<String>> m : sets) {
            int index = 1;
            Map<String, Integer> map2 = new HashMap<>();

            for (String item : m.getValue()) {
                map2.put(item, index++);
            }

            map.put(m.getKey(), map2);
        }


        return map;
    }


    /**
     * 抽取物理隔绝信息与母线的关系并放入map集合中
     * 与getTflgPloyInfo()方法功能类似
     */
    public Map<String, List<String>> getLogicInfo(List<EntityLogic> list) {
        if (list.size() > 0) {
            Iterator<String> iterator = getAreaInfo(list).iterator();
            Map<String, List<String>> map = new HashMap<>();

            while (iterator.hasNext()) {
                List<String> listLogic = new ArrayList<>();
                String areaString = iterator.next();

                for (EntityLogic entityLogic : list) {
                    if (entityLogic.getTPIndex().equals(areaString)) {
                        listLogic.add(entityLogic.getNodeBefore());
                        listLogic.add(entityLogic.getNodeNext());
                    }
                }

                //去除list中重复数据
                Set<String> set = new TreeSet<>(listLogic);
                map.put(areaString, new ArrayList<>(set));
            }

            return map;
        }

        return null;
    }


    /**
     * 获取物理隔绝编码信息
     * 供getInfo()、getLogicInfo()方法使用
     * 先从list数组中去重，然后获取物理隔绝编码
     */
    public <T> Set<String> getAreaInfo(List<T> list) {
        Set<T> set = new HashSet<T>(list);
        Iterator<T> iterator = set.iterator();
        Set<String> setReturn = new HashSet<String>();

        while (iterator.hasNext()) {
            Object object = iterator.next();

            if (object instanceof PqsTflgployass) {
                setReturn.add(((PqsTflgployass) object).getTpIndex());
                continue;
            }

            setReturn.add(((EntityLogic) object).getTPIndex());
        }

        return setReturn;
    }


    public List<AdvanceEventDetailVO> querySagEventsAll(LocalDateTime startTime, LocalDateTime endTime) {
        List<String> lineIds = generalDeviceInfoClient.deptGetRunLineEvent(RequestUtil.getDeptIndex()).getData();
        if (CollUtil.isNotEmpty(lineIds)) {

            LambdaQueryWrapper<RmpEventDetailPO> lambdaQueryWrapper = new LambdaQueryWrapper<>();
            lambdaQueryWrapper.and(i -> i.isNull(RmpEventDetailPO::getEventassIndex).or().eq(RmpEventDetailPO::getEventassIndex, ""))
                    .between(RmpEventDetailPO::getStartTime, startTime, endTime);


            List<RmpEventDetailPO> rmpEventDetailPOList = eventAdvanceMapper.selectList(lambdaQueryWrapper);
            if (CollectionUtil.isEmpty(rmpEventDetailPOList)) {
                throw new BusinessException(AdvanceResponseEnum.EVENT_EMPTY);
            }
            List<String> tempLineIds = rmpEventDetailPOList.stream().map(RmpEventDetailPO::getLineId).distinct().collect(Collectors.toList());

            List<AreaLineInfoVO> temLine = lineFeignClient.getBaseLineAreaInfo(tempLineIds).getData();
            Map<String, AreaLineInfoVO> map = temLine.stream().collect(Collectors.toMap(AreaLineInfoVO::getLineId, Function.identity()));

            List<AdvanceEventDetailVO> advanceEventDetailVOList = BeanUtil.copyToList(rmpEventDetailPOList, AdvanceEventDetailVO.class);
            advanceEventDetailVOList = advanceEventDetailVOList.stream().peek(item -> {
                if (map.containsKey(item.getLineId())) {
                    AreaLineInfoVO areaLineInfoVO = map.get(item.getLineId());
                    item.setGdName(areaLineInfoVO.getGdName());
                    item.setSubName(areaLineInfoVO.getSubName());
                    item.setNum(areaLineInfoVO.getNum());
                    item.setVoltageId(areaLineInfoVO.getVoltageId());
                }
            }).collect(Collectors.toList());

            return advanceEventDetailVOList;
        }
        return new ArrayList<>();
    }
}

