package com.base.plan.service.biz;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.base.api.client.FzTaskRpcService;
import com.base.api.client.PointRpcService;
import com.base.api.client.SatelliteRpcService;
import com.base.api.model.BizTaskStepEnum;
import com.base.api.model.FzTaskRpcDTO;
import com.base.api.model.PointRpcDTO;
import com.base.api.model.SatelliteRpcDTO;
import com.base.api.model.request.FzTaskInfoRpcReqDTO;
import com.base.api.model.request.PointListRpcReqDTO;
import com.base.api.model.request.TaskStateNotice;
import com.base.api.model.request.UpdateSatelliteRpcDTO;
import com.base.core.model.enity.ArcCoreDTO;
import com.base.orbit.utils.BizUtils;
import com.base.orbit.utils.IdGenerator;
import com.base.plan.mapper.AreaOptimizationResultInfoMapper;
import com.base.plan.mapper.FzIndicatorInfoMapper;
import com.base.plan.mapper.StripMapper;
import com.base.plan.model.dto.*;
import com.base.plan.model.dto.request.AreaOptimizationResultReqDTO;
import com.base.plan.model.dto.request.CapacityReqDTO;
import com.base.plan.model.dto.request.StripDTOListReqDTO;
import com.base.plan.model.entity.AreaOptimizationResultInfo;
import com.base.plan.model.entity.FzIndicatorInfo;
import com.base.plan.model.entity.StripInfo;
import com.base.plan.model.entity.WindowResource;
import com.base.plan.service.ArcService;
import com.base.plan.service.StripService;
import com.base.plan.service.WindowResourceService;
import com.base.plan.utils.DateTool;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Component
@Slf4j
public class StripBiz {

    @Resource
    AreaOptimizationResultInfoMapper areaOptimizationResultInfoMapper;

    @Resource
    FzTaskRpcService fzTaskService;

    @Resource
    StripService stripService;

    @Resource
    PointRpcService pointRpcService;

    @Resource
    ArcService arcService;

    @Resource
    WindowResourceService windowResourceService;

    @Resource
    FzIndicatorInfoMapper fzIndicatorInfoMapper;

    @Resource
    StripMapper stripMapper;

    @Resource
    SatelliteRpcService satelliteRpcService;

    private final Integer beforeTime = 120;

    private final Integer afterTime = 120;

    public void taskStepStateNotice(String reqId, BizTaskStepEnum bizTaskStepEnum, Integer state) {
        TaskStateNotice taskStateNotice = new TaskStateNotice();
        taskStateNotice.setBizTaskId(reqId);
        taskStateNotice.setStep(bizTaskStepEnum);
        taskStateNotice.setState(state);
        fzTaskService.taskStepStateUpdate(taskStateNotice);

    }

    public List<AreaOptimizationResultInfo> getOptimizationStripIds(List<String> reqIds) {
        AreaOptimizationResultReqDTO areaOptimizationResultReqDTO = new AreaOptimizationResultReqDTO();
        areaOptimizationResultReqDTO.setReqIds(reqIds);
        return areaOptimizationResultInfoMapper.selectAreaOptimizationResultInfoList(areaOptimizationResultReqDTO);
    }

    public List<StripInfo> getOptimizationStripDTOS(List<String> reqIds) {
        List<AreaOptimizationResultInfo> areaOptimizationResultInfoList = getOptimizationStripIds(reqIds);
        List<String> stripIds = new ArrayList<>();
        for (AreaOptimizationResultInfo areaOptimizationResultInfo : areaOptimizationResultInfoList) {
            areaOptimizationResultInfo.setStripIds(Arrays.asList(areaOptimizationResultInfo.getStripId().split(",")));
            stripIds.addAll(areaOptimizationResultInfo.getStripIds());
        }
        StripDTOListReqDTO stripDTOListReqDTO = new StripDTOListReqDTO();
        stripDTOListReqDTO.setIds(stripIds);
        return stripMapper.getStripInfoList(stripDTOListReqDTO);
    }

    public List<WindowResource> getOptimizationTrbutIds(List<String> stripIds) {
        //查询条带绑定的地面站
        QueryWrapper<WindowResource> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("window_id", stripIds);
        return windowResourceService.list(queryWrapper);
    }

    public Boolean executeAreaOptimization(List<StripDTO> stripDTOList, List<FzTaskRpcDTO> fzTaskDTOList) {
        try {
            //将条带按照任务:目标分组

            Map<String, List<StripDTO>> stringListMap = stripDTOList.stream().collect(Collectors.groupingBy(e -> e.getReqId() + ":" + e.getParentId() + ":" + e.getTargetName()));

            //直接删除任务已经存在的优选方案 进行重新规划  并删除指标
            getFinishTaskStripOptimizationResListnew(fzTaskDTOList);

            //根据条带id查询本次正在进行优选的条带，并设置本次所有需求的方案
            FzTaskInfoRpcReqDTO fzTaskInfoReqDTO = new FzTaskInfoRpcReqDTO();
            fzTaskInfoReqDTO.setReqIds(stripDTOList.stream().map(StripDTO::getReqId).distinct().collect(Collectors.toList()));
            List<FzTaskRpcDTO> taskList = fzTaskService.getFzTaskDTOList(fzTaskInfoReqDTO);
            //  存优选结果前先清空相同任务的数据
            areaOptimizationResultInfoMapper.deleteByReqIds(fzTaskInfoReqDTO.getReqIds());

            List<TaskStripOptimizationRes> executingTaskStripOptimizationResList = new ArrayList<>();
            //当前所有任务所有目标 方案的条带map 以便进行冲突判断 目前按照遍历顺序进行优先级判断
            Map<String, List<StripDTO>> stringListMapnew = new HashMap<>();
            List<StripDTO> stripDTOSnew = new ArrayList<>();
            for (FzTaskRpcDTO fzTaskDTO : taskList) {
                Map<String, List<StripDTO>> stringListMapOld = selectoldstrip(fzTaskDTO);

                PointListRpcReqDTO pointListRpcReqDTO = new PointListRpcReqDTO();
                pointListRpcReqDTO.setPointType("TARGET");
                pointListRpcReqDTO.setParentIds(Arrays.asList(fzTaskDTO.getTargetCode().split(",")));
                Map<String, List<String>> targetGirdMap = getGirdMap(pointListRpcReqDTO);
                //同任务不同目标
                for (Map.Entry<String, List<String>> entry : targetGirdMap.entrySet()) {

                    List<StripDTO> stripDTOS = stringListMap.get(fzTaskDTO.getReqId() + ":" + entry.getKey());
                    if (!CollectionUtils.isEmpty(stripDTOS)) {
                        TaskStripOptimizationRes taskStripOptimizationRes = getStripsSinglePlanListnew(stripDTOS, entry.getValue(), fzTaskDTO, entry.getKey(), stringListMapOld, stringListMapnew);
                        executingTaskStripOptimizationResList.add(taskStripOptimizationRes);
                        stripDTOSnew.addAll(taskStripOptimizationRes.getSinglePlanList().get(0).getStripDTOLists());
                        if (!CollectionUtils.isEmpty(stripDTOSnew)) {
                            stringListMapnew = stripDTOSnew.stream().collect(Collectors.groupingBy(e -> e.getSatelliteCode() + ":" + e.getCircle()));
                        }
                    }

                }

            }
            /*  List<TaskStripOptimizationRes> executingTaskStripOptimizationResList = getExecutingTaskStripOptimizationResList(stripDTOList);
             */

            //冲突判断（本次冲突，本次和以往的冲突）
   /*         executingTaskStripOptimizationResList.forEach(e -> e.getSinglePlanList().sort(Comparator.comparing(k -> k.getStripDTOList().size())));

            markDeleteSinglePlamarkn(finishTaskStripOptimizationResList, executingTaskStripOptimizationResList);
            for (TaskStripOptimizationRes taskStripOptimizationRes : executingTaskStripOptimizationResList) {
                taskStripOptimizationRes.getSinglePlanList().removeIf(singlePlan -> singlePlan.getIsDelete() == 1);
                //  todo 如果方案均有删除标识，则直接返回
                if (taskStripOptimizationRes.getSinglePlanList().size() <= 0) {
                    return Boolean.TRUE;
                }
                //选出覆盖率最大的方案
                taskStripOptimizationRes.getSinglePlanList().sort(Comparator.comparing(SinglePlan::getCoverage));
                taskStripOptimizationRes.setSinglePlanList(taskStripOptimizationRes.getSinglePlanList().subList(taskStripOptimizationRes.getSinglePlanList().size() - 1, taskStripOptimizationRes.getSinglePlanList().size()));
            }*/
            //区域优选入库
            saveAreaOptimizationRes(executingTaskStripOptimizationResList);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }

    public Map<String, List<StripDTO>> selectoldstrip(FzTaskRpcDTO fzTaskDTO) {
        //查询已完成的优选方案 获取所有条带 后续进行冲突判断
        Map<String, List<StripDTO>> stringListMap = new HashMap<>();
        AreaOptimizationResultReqDTO areaOptimizationResultReqDTO = new AreaOptimizationResultReqDTO();
        areaOptimizationResultReqDTO.setStartTime(fzTaskDTO.getStartTime());
        areaOptimizationResultReqDTO.setEndTime(fzTaskDTO.getEndTime());
        List<AreaOptimizationResultInfo> areaOptimizationResultInfos = areaOptimizationResultInfoMapper.selectAreaOptimizationResultInfoList(areaOptimizationResultReqDTO);
        if (CollectionUtils.isEmpty(areaOptimizationResultInfos)) {
            return stringListMap;
        }
        List<String> stripIds = new ArrayList<>();
        for (AreaOptimizationResultInfo areaOptimizationResultInfo : areaOptimizationResultInfos) {
            areaOptimizationResultInfo.setStripIds(Arrays.asList(areaOptimizationResultInfo.getStripId().split(",")));
            stripIds.addAll(areaOptimizationResultInfo.getStripIds());
        }

        StripDTOListReqDTO stripDTOListReqDTO = new StripDTOListReqDTO();
        stripDTOListReqDTO.setIds(stripIds);
        List<StripDTO> stripDTOList = stripService.getStripDTOList(stripDTOListReqDTO);
        stringListMap = stripDTOList.stream().collect(Collectors.groupingBy(e -> e.getSatelliteCode() + ":" + e.getCircle()));
        return stringListMap;
    }

    private List<TaskStripOptimizationRes> getFinishTaskStripOptimizationResListnew(List<FzTaskRpcDTO> fzTaskDTOList) {
        List<TaskStripOptimizationRes> taskStripOptimizationRes = new ArrayList<>();
        if (!CollectionUtils.isEmpty(fzTaskDTOList)) {
            List<String> reqIds = fzTaskDTOList.stream().map(FzTaskRpcDTO::getReqId).collect(Collectors.toList());
            areaOptimizationResultInfoMapper.deleteByReqIds(reqIds);
            fzIndicatorInfoMapper.deleteByReqIds(reqIds);
    /*
            AreaOptimizationResultReqDTO areaOptimizationResultReqDTO = new AreaOptimizationResultReqDTO();
            areaOptimizationResultReqDTO.setReqIds(reqIds);
            List<AreaOptimizationResultInfo> areaOptimizationResultInfos = areaOptimizationResultInfoMapper.selectAreaOptimizationResultInfoList(areaOptimizationResultReqDTO);
            if (CollectionUtils.isEmpty(areaOptimizationResultInfos)) {
                return taskStripOptimizationRes;
            }
            List<String> stripIds=new ArrayList<>();
            for (AreaOptimizationResultInfo areaOptimizationResultInfo:areaOptimizationResultInfos){
                areaOptimizationResultInfo.setStripIds(Arrays.asList(areaOptimizationResultInfo.getStripId().split(",")));
                stripIds.addAll(areaOptimizationResultInfo.getStripIds());
            }

            StripDTOListReqDTO stripDTOListReqDTO = new StripDTOListReqDTO();
            stripDTOListReqDTO.setIds(stripIds);
            List<StripDTO> stripDTOList = stripService.getStripDTOList(stripDTOListReqDTO);
            //这就是之前已经规划好的结果
            Map<String, List<StripDTO>> StripDTOListReqMap = stripDTOList.stream().collect(Collectors.groupingBy(StripDTO::getReqId));
            for (Map.Entry<String, List<StripDTO>> entry : StripDTOListReqMap.entrySet()) {
                TaskStripOptimizationRes taskStripOptimizationRes1 = new TaskStripOptimizationRes();
                taskStripOptimizationRes1.setReqId(entry.getKey());
                taskStripOptimizationRes1.setAreaOptimizationState(0);
                List<SinglePlan> stripDTOLists = new ArrayList<>();
                SinglePlan singlePlan = new SinglePlan();
                singlePlan.setReqId(entry.getKey());
                singlePlan.setStripDTOList(BizUtils.copyEntityToDto(OptimizationStripDTO.class, entry.getValue()));
                stripDTOLists.add(singlePlan);
                taskStripOptimizationRes1.setSinglePlanList(stripDTOLists);
                taskStripOptimizationRes.add(taskStripOptimizationRes1);
            }*/
        }
        return taskStripOptimizationRes;
    }

    private TaskStripOptimizationRes getStripsSinglePlanListnew(List<StripDTO> list, List<String> targetlist, FzTaskRpcDTO fzTaskDTO, String targetCodeandName, Map<String, List<StripDTO>> stringListMapOld, Map<String, List<StripDTO>> stringListMapnew) {
        String[] targetCodenames = targetCodeandName.split(":");
        String targetCode = targetCodenames[0];
        String targetName = targetCodenames[1];

        TaskStripOptimizationRes taskStripOptimizationRes = new TaskStripOptimizationRes();
        //v是单圈多个侧摆的条带
        Map<String, List<StripDTO>> lists = list.stream().collect(Collectors.groupingBy(e -> e.getSatelliteCode() + ":" + e.getCircle()));
        List<List<StripDTO>> StripDTOslist = new ArrayList<>();
        for (Map.Entry<String, List<StripDTO>> entry : lists.entrySet()) {
            List<StripDTO> stripDTOS = entry.getValue();
            StripDTOslist.add(stripDTOS);
        }
        List<List<StripDTO>> StripDTOslistreturn = new ArrayList<>();
        //进行排序组合
        descartesRecursive(StripDTOslist, 0, StripDTOslistreturn, new ArrayList<StripDTO>(), fzTaskDTO, stringListMapOld, stringListMapnew);

        List<SinglePlan> singlePlanList = new ArrayList<>();
        for (List<StripDTO> stripDTOS : StripDTOslistreturn) {
            SinglePlan singlePlan = new SinglePlan();
            singlePlan.setReqId(fzTaskDTO.getReqId());
            if (CollectionUtils.isEmpty(targetlist)) {
                singlePlan.setCoverage(1.0d);
                List<StripDTO> stripDTOone = new ArrayList<>();
                stripDTOone.add(stripDTOS.get(0));
                singlePlan.setStripDTOLists(new ArrayList<>(stripDTOone));
            } else {
                singlePlan.setCoverage(getStripGroupCoveragenew(new HashSet<>(targetlist), new ArrayList<>(stripDTOS)));
                singlePlan.setStripDTOLists(new ArrayList<>(stripDTOS));
            }
            singlePlanList.add(singlePlan);
        }
        //在所有方案中选出覆盖率最大的方案
        SinglePlan singlePlanmax = singlePlanList.stream().max(Comparator.comparingDouble(SinglePlan::getCoverage)).get();
        List<SinglePlan> singlePlanListnew = new ArrayList<>();
        singlePlanListnew.add(singlePlanmax);
        taskStripOptimizationRes.setReqId(fzTaskDTO.getReqId());
        taskStripOptimizationRes.setTargetName(targetName);
        taskStripOptimizationRes.setTargetCode(targetCode);
        taskStripOptimizationRes.setAreaOptimizationState(0);
        taskStripOptimizationRes.setPriority(Integer.valueOf(fzTaskDTO.getPriority()));
        taskStripOptimizationRes.setTargetGirdCodeList(new HashSet<>(targetlist));
        taskStripOptimizationRes.setSinglePlanList(singlePlanListnew);
        taskStripOptimizationRes.setStartTime(fzTaskDTO.getStartTime());
        taskStripOptimizationRes.setEndTime(fzTaskDTO.getEndTime());

        List<StripDTO> stripDTOList = singlePlanmax.getStripDTOLists();
        List<String> satelliteCodes = stripDTOList.stream().map(StripDTO::getSatelliteCode).distinct().collect(Collectors.toList());
        taskStripOptimizationRes.setSatelliteCode(StringUtils.join(satelliteCodes.toArray(), ","));
        return taskStripOptimizationRes;
    }

    private Double getStripGroupCoveragenew(Set<String> targetGirdSet, List<StripDTO> stripDTOList) {
        double all = targetGirdSet.size();
        double coverageall = 0.0;
        for (StripDTO stripDTO : stripDTOList) {
            Set<String> stripGirdSet = new HashSet<>(stripDTO.getGirdCodeList());
            stripGirdSet.retainAll(targetGirdSet);
            double coverage = (double) stripGirdSet.size() / all;
            targetGirdSet.removeAll(stripGirdSet);
            coverageall += coverage;
        }
        return coverageall;
    }

    public void descartesRecursive(List<List<StripDTO>> originalList, int position, List<List<StripDTO>> returnList, List<StripDTO> cacheList, FzTaskRpcDTO fzTaskDTO, Map<String, List<StripDTO>> stringListMapOld, Map<String, List<StripDTO>> stringListMapnew) {
        List<StripDTO> originalItemList = originalList.get(position);
        for (int i = 0; i < originalItemList.size(); i++) {
            List<StripDTO> childCacheList = (i == originalItemList.size() - 1) ? cacheList : new ArrayList<>(cacheList);

            //根据任务开始和结束时间查询 完成优选的方案和当前优选计划完成的 进行同卫星同轨道的条带时间对比 是否有冲突
            if (contraststrip(originalItemList.get(i), fzTaskDTO, stringListMapOld) && contraststrip(originalItemList.get(i), fzTaskDTO, stringListMapnew)) {
                childCacheList.add(originalItemList.get(i));
            }
            if (position == originalList.size() - 1) {
                returnList.add(childCacheList);
                continue;
            }
            descartesRecursive(originalList, position + 1, returnList, childCacheList, fzTaskDTO, stringListMapOld, stringListMapnew);
        }
    }

    public boolean contraststrip(StripDTO stripDTO, FzTaskRpcDTO fzTaskDTO, Map<String, List<StripDTO>> stringListMap) {
        String key = stripDTO.getSatelliteCode() + ":" + stripDTO.getCircle();
        if (CollectionUtils.isEmpty(stringListMap)) {
            return true;
        }
        List<StripDTO> stripDTOSOld = stringListMap.get(key);
        if (CollectionUtils.isEmpty(stripDTOSOld)) {
            return true;
        }
        for (StripDTO s : stripDTOSOld) {
            //判断交集
            Long finishStartTime = s.getObservationStartTime().getTime() - beforeTime * 1000;
            Long finishEndTime = s.getObservationEndTime().getTime() + afterTime * 1000;

            Long executeStartTime = stripDTO.getObservationStartTime().getTime();
            Long executeEndTime = stripDTO.getObservationEndTime().getTime();
            if (DateTool.isIntersectionnew(finishStartTime, finishEndTime, executeStartTime, executeEndTime)) {
                return false;
            }
        }
        return true;
    }

    /**
     * 入库
     *
     * @param taskStripOptimizationResList 优选结果
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveAreaOptimizationRes(List<TaskStripOptimizationRes> taskStripOptimizationResList) {
        for (TaskStripOptimizationRes taskStripOptimizationRes : taskStripOptimizationResList) {

            if (!CollectionUtils.isEmpty(taskStripOptimizationRes.getSinglePlanList().get(0).getStripDTOLists())) {
                //这里先把目标指标保存
                FzIndicatorInfo fzIndicatorInfo = new FzIndicatorInfo();
                fzIndicatorInfo.setId(IdGenerator.getStrId());
                fzIndicatorInfo.setCoverageInfo(taskStripOptimizationRes.getSinglePlanList().get(0).getCoverage().toString());
                fzIndicatorInfo.setCoverageAresNumberInfo(taskStripOptimizationRes.getSinglePlanList().stream().map(e -> e.getStripDTOLists().size()).reduce(Integer::sum).get().toString());
                fzIndicatorInfo.setCoverageAresTimeInfo(taskStripOptimizationRes.getSinglePlanList().get(0).getStripDTOLists().stream().map(e -> (e.getObservationEndTime().getTime() - e.getObservationStartTime().getTime()) / 1000).reduce(Long::sum).get().toString());
                fzIndicatorInfo.setReqId(taskStripOptimizationRes.getReqId());
                fzIndicatorInfo.setTargetCode(taskStripOptimizationRes.getTargetCode());
                fzIndicatorInfo.setCreateTime(new Date());
                fzIndicatorInfo.setTargetName(taskStripOptimizationRes.getTargetName());
                fzIndicatorInfo.setSatelliteCode(taskStripOptimizationRes.getSatelliteCode());
                fzIndicatorInfoMapper.insert(fzIndicatorInfo);

                for (SinglePlan singlePlan : taskStripOptimizationRes.getSinglePlanList()) {
                    List<StripDTO> StripDTOs = singlePlan.getStripDTOLists();
                    List<String> StripDTOIds = StripDTOs.stream().map(StripDTO::getId).collect(Collectors.toList());
                    String StripDTOId = StripDTOIds.stream().map(String::valueOf).collect(Collectors.joining(","));
                    AreaOptimizationResultInfo areaOptimizationResultInfo = new AreaOptimizationResultInfo();
                    areaOptimizationResultInfo.setId(IdGenerator.getStrId());
                    areaOptimizationResultInfo.setReqId(taskStripOptimizationRes.getReqId());
                    areaOptimizationResultInfo.setStripId(StripDTOId);
                    /* areaOptimizationResultInfo.setPayloadId(StripDTOs.get(0).getPayloadId());*/
                    areaOptimizationResultInfo.setCreateDate(new Date());
                    areaOptimizationResultInfo.setParentId(taskStripOptimizationRes.getTargetCode());
                    areaOptimizationResultInfo.setCoverage(singlePlan.getCoverage());
                    areaOptimizationResultInfo.setStartTime(taskStripOptimizationRes.getStartTime());
                    areaOptimizationResultInfo.setEndTime(taskStripOptimizationRes.getEndTime());
                    areaOptimizationResultInfo.setParentName(taskStripOptimizationRes.getTargetName());
                    areaOptimizationResultInfoMapper.insert(areaOptimizationResultInfo);

                    /*固存占用计算入库*/
                    capacityCount(singlePlan.getStripDTOLists(), singlePlan);
                }
            }
        }
    }

    public void capacityCount(List<StripDTO> stripDTOS, SinglePlan singlePlan) {

        Map<String, List<StripDTO>> stripMap = stripDTOS.stream().collect(Collectors.groupingBy(StripDTO::getSatelliteCode));

        for (Map.Entry<String, List<StripDTO>> entry : stripMap.entrySet()) {

            String satelliteCode = entry.getKey();

            List<String> satellitecodes = Lists.newArrayList(satelliteCode);
            List<SatelliteRpcDTO> satelliteRpcDTOList = satelliteRpcService.listByIds(satellitecodes);
            if (!CollectionUtils.isEmpty(satelliteRpcDTOList)) {
                SatelliteRpcDTO satelliteRpcDTO = satelliteRpcDTOList.get(0);
                List<StripDTO> stripDTOList = entry.getValue();
                double totalSize = 0.0;
                for (StripDTO o : stripDTOList) {
                    double count = (o.getObservationEndTime().getTime() - o.getObservationEndTime().getTime()) / 1000;
                    double Size = (count * Integer.parseInt(satelliteRpcDTO.getDataPassSpeed())) / 1024;
                    totalSize += Size;
                }
                double total = Double.parseDouble(StringUtils.isEmpty(satelliteRpcDTO.getBaseMemory()) ? "0.0" : satelliteRpcDTO.getBaseMemory()) + totalSize;
                satelliteRpcDTO.setBaseMemory(String.valueOf(total));
                UpdateSatelliteRpcDTO updateSatelliteRpcDTO = new UpdateSatelliteRpcDTO();
                updateSatelliteRpcDTO.setBaseMemory(satelliteRpcDTO.getBaseMemory());
                updateSatelliteRpcDTO.setId(satelliteRpcDTO.getId());
                satelliteRpcService.update(updateSatelliteRpcDTO);
            }

        }

    }

    /**
     * 按照优先级删除标记冲突方案
     *
     * @param finishTaskStripOptimizationResList    入库方案
     * @param executingTaskStripOptimizationResList 进行方案
     */
    private void markDeleteSinglePlamarkn(List<TaskStripOptimizationRes> finishTaskStripOptimizationResList, List<TaskStripOptimizationRes> executingTaskStripOptimizationResList) {
        try {
            //和已经完成方案对比
            if (!CollectionUtils.isEmpty(finishTaskStripOptimizationResList)) {
                for (TaskStripOptimizationRes executingTaskStripOptimizationRes : executingTaskStripOptimizationResList) {
                    Iterator<SinglePlan> iterator = executingTaskStripOptimizationRes.getSinglePlanList().iterator();
                    while (iterator.hasNext()) {
                        for (TaskStripOptimizationRes finishTaskStripOptimizationRes : finishTaskStripOptimizationResList) {
                            SinglePlan singlePlan = iterator.next();
                            if (checkFinishPlan(singlePlan, finishTaskStripOptimizationRes.getSinglePlanList()) != null) {
                                singlePlan.setIsDelete(1);
                                break;
                            }
                        }
                    }
                }
            }
            //和本次优选方案对比
            for (TaskStripOptimizationRes taskStripOptimizationRes : executingTaskStripOptimizationResList) {
                List<SinglePlan> singlePlanList = taskStripOptimizationRes.getSinglePlanList();
                for (SinglePlan singlePlan : singlePlanList) {
                    if (singlePlan.getIsDelete() == 1) {
                        continue;
                    }
                    //  进行中的方案循环对比
                    for (TaskStripOptimizationRes taskStripOptimization : executingTaskStripOptimizationResList) {
                        if (taskStripOptimizationRes.getReqId().equals(taskStripOptimization.getReqId())) {
                            continue;
                        }
                        //  根据任务时间冲突和优先级\覆盖率对方案进行取舍
                        SinglePlan singlePlan1 = checkFinishPlan(singlePlan, taskStripOptimization.getSinglePlanList());
                        if (singlePlan1 != null) {
                            if (taskStripOptimizationRes.getPriority() >= taskStripOptimization.getPriority()) {
                                singlePlan1.setIsDelete(1);
                            } else if (taskStripOptimizationRes.getPriority().equals(taskStripOptimization.getPriority()) && singlePlan.getCoverage() >= singlePlan1.getCoverage()) {
                                singlePlan1.setIsDelete(1);
                            } else {
                                log.info("其他冲突情况");
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    /**
     * 卫星前后拍摄时间冲突判断
     *
     * @param next
     * @param singlePlanList
     */
    private SinglePlan checkFinishPlan(SinglePlan next, List<SinglePlan> singlePlanList) {
        for (OptimizationStripDTO optimizationStripDTO : next.getStripDTOList()) {
            for (SinglePlan singlePlan : singlePlanList) {
                for (OptimizationStripDTO stripDTO : singlePlan.getStripDTOList()) {
                    //判断交集
                    Long finishStartTime = stripDTO.getObservationStartTime().getTime() - beforeTime * 1000;
                    Long finishEndTime = stripDTO.getObservationEndTime().getTime() + afterTime * 1000;

                    Long executeStartTime = optimizationStripDTO.getObservationStartTime().getTime();
                    Long executeEndTime = optimizationStripDTO.getObservationEndTime().getTime();
                    if (DateTool.isIntersectionnew(finishStartTime, finishEndTime, executeStartTime, executeEndTime)) {
                        return singlePlan;
                    }
                }
            }
        }
        return null;
    }


    /**
     * 获取已经完成区域优选的结果
     *
     * @param fzTaskDTOList 已经区域优选的任务
     * @return res
     */
    private List<TaskStripOptimizationRes> getFinishTaskStripOptimizationResList(List<FzTaskRpcDTO> fzTaskDTOList) {
        List<TaskStripOptimizationRes> taskStripOptimizationRes = new ArrayList<>();
        if (!CollectionUtils.isEmpty(fzTaskDTOList)) {
            List<String> reqIds = fzTaskDTOList.stream().map(FzTaskRpcDTO::getReqId).collect(Collectors.toList());
            AreaOptimizationResultReqDTO areaOptimizationResultReqDTO = new AreaOptimizationResultReqDTO();
            areaOptimizationResultReqDTO.setReqIds(reqIds);
            List<AreaOptimizationResultInfo> areaOptimizationResultInfos = areaOptimizationResultInfoMapper.selectAreaOptimizationResultInfoList(areaOptimizationResultReqDTO);
            if (CollectionUtils.isEmpty(areaOptimizationResultInfos)) {
                return taskStripOptimizationRes;
            }
            List<String> stripIds = new ArrayList<>();
            for (AreaOptimizationResultInfo areaOptimizationResultInfo : areaOptimizationResultInfos) {
                areaOptimizationResultInfo.setStripIds(Arrays.asList(areaOptimizationResultInfo.getStripId().split(",")));
                stripIds.addAll(areaOptimizationResultInfo.getStripIds());
            }
            StripDTOListReqDTO stripDTOListReqDTO = new StripDTOListReqDTO();
            stripDTOListReqDTO.setIds(stripIds);
            List<StripDTO> stripDTOList = stripService.getStripDTOList(stripDTOListReqDTO);
            //这就是之前已经规划好的结果
            Map<String, List<StripDTO>> StripDTOListReqMap = stripDTOList.stream().collect(Collectors.groupingBy(StripDTO::getReqId));
            for (Map.Entry<String, List<StripDTO>> entry : StripDTOListReqMap.entrySet()) {
                TaskStripOptimizationRes taskStripOptimizationRes1 = new TaskStripOptimizationRes();
                taskStripOptimizationRes1.setReqId(entry.getKey());
                taskStripOptimizationRes1.setAreaOptimizationState(0);
                List<SinglePlan> stripDTOLists = new ArrayList<>();
                SinglePlan singlePlan = new SinglePlan();
                singlePlan.setReqId(entry.getKey());
                singlePlan.setStripDTOList(BizUtils.copyEntityToDto(OptimizationStripDTO.class, entry.getValue()));
                stripDTOLists.add(singlePlan);
                taskStripOptimizationRes1.setSinglePlanList(stripDTOLists);
                taskStripOptimizationRes.add(taskStripOptimizationRes1);
            }
        }
        return taskStripOptimizationRes;
    }

    /**
     * 获取正在进行区域优选的结果集
     *
     * @param stripDTOList 本次条带
     * @return 优选的所有方案
     */
    public List<TaskStripOptimizationRes> getExecutingTaskStripOptimizationResList(List<StripDTO> stripDTOList) {
        FzTaskInfoRpcReqDTO fzTaskInfoReqDTO = new FzTaskInfoRpcReqDTO();
        fzTaskInfoReqDTO.setReqIds(stripDTOList.stream().map(StripDTO::getReqId).distinct().collect(Collectors.toList()));
        List<FzTaskRpcDTO> taskList = fzTaskService.getFzTaskDTOList(fzTaskInfoReqDTO);
        PointListRpcReqDTO pointListRpcReqDTO = new PointListRpcReqDTO();
        pointListRpcReqDTO.setPointType("TARGET");
        pointListRpcReqDTO.setParentIds(taskList.stream().map(FzTaskRpcDTO::getTargetCode).distinct().collect(Collectors.toList()));
        Map<String, List<String>> targetGirdMap = getGirdMap(pointListRpcReqDTO);       //  观测目标网格信息
        Map<FzTaskRpcDTO, List<StripDTO>> reqStripDTOListMap = new HashMap<>();
        for (FzTaskRpcDTO fzTaskDTO : taskList) {
            List<StripDTO> stripDTOS = new ArrayList<>();
            for (StripDTO stripDTO : stripDTOList) {
                if (stripDTO.getReqId().equals(fzTaskDTO.getReqId())) {
                    stripDTOS.add(stripDTO);
                }
            }
            reqStripDTOListMap.put(fzTaskDTO, stripDTOS);
        }
        //获取单星单圈单个条带的方案（这里集合的长度就已经确定了）
        List<TaskStripOptimizationRes> stripTaskStripOptimizationResList = getSingleStripTaskStripOptimizationResList(reqStripDTOListMap, targetGirdMap);
        //设置方案
        for (TaskStripOptimizationRes taskStripOptimizationRes : stripTaskStripOptimizationResList) {
            getStripsSinglePlanList(taskStripOptimizationRes.getStripDTOList(), taskStripOptimizationRes);
        }
        return stripTaskStripOptimizationResList;
    }

    /**
     * 查询网格集合
     *
     * @param req 目标点请求
     * @return k.目标 v.网格集合
     */
    private Map<String, List<String>> getGirdMap(PointListRpcReqDTO req) {
        Map<String, List<PointRpcDTO>> listMap = pointRpcService.getPointDTOList(req).stream().collect(Collectors.groupingBy(PointRpcDTO::getParentId));
        Map<String, List<String>> girdMap = new HashMap<>();
        //这里是性能瓶颈，后面有问题的话，要么任务入库的时候把网格存好，这里直接用，要么就加索引查。
        for (Map.Entry<String, List<PointRpcDTO>> entry : listMap.entrySet()) {
            List<String> girdIds = new ArrayList<>();
            if (entry.getValue().size() == 1) {
                girdMap.put(entry.getKey() + ":" + entry.getValue().get(0).getParentName(), girdIds);
            } else {
                List<ArcCoreDTO> list = arcService.getPointListArcList(entry.getValue());
                for (ArcCoreDTO arc : list) {
                    girdIds.addAll(arc.getGridListCode());
                }
                girdMap.put(entry.getKey() + ":" + entry.getValue().get(0).getParentName(), girdIds);
            }
        }
        return girdMap;
    }

    /**
     * 获取单星单圈单个条带的方案
     *
     * @param reqStripDTOListMap 任务条带集合
     * @param pointRpcDTOMap     观测目标网格
     * @return 新建需求方案，set单星单条带方案
     */
    private List<TaskStripOptimizationRes> getSingleStripTaskStripOptimizationResList(Map<FzTaskRpcDTO, List<StripDTO>> reqStripDTOListMap, Map<String, List<String>> pointRpcDTOMap) {
        List<TaskStripOptimizationRes> resList = new ArrayList<>();
        for (Map.Entry<FzTaskRpcDTO, List<StripDTO>> entry : reqStripDTOListMap.entrySet()) {
            Map<String, List<StripDTO>> stringListMap = entry.getValue().stream().collect(Collectors.groupingBy(StripDTO::getSatelliteCode));
            stringListMap.forEach((k, v) -> {
                TaskStripOptimizationRes taskStripOptimizationRes = new TaskStripOptimizationRes();
                taskStripOptimizationRes.setReqId(entry.getKey().getReqId());
                taskStripOptimizationRes.setTargetName(entry.getKey().getTargetName());
                taskStripOptimizationRes.setAreaOptimizationState(0);
                taskStripOptimizationRes.setTargetCode(entry.getKey().getTargetCode());
                taskStripOptimizationRes.setStripDTOList(v);
                taskStripOptimizationRes.setSatelliteCode(k);
                taskStripOptimizationRes.setPriority(Integer.parseInt(entry.getKey().getPriority()));
                //根据目标信息获取网格
                taskStripOptimizationRes.setTargetGirdCodeList(new HashSet<>(pointRpcDTOMap.get(entry.getKey().getTargetCode())));
                List<SinglePlan> singlePlans = new ArrayList<>();
                taskStripOptimizationRes.setSinglePlanList(singlePlans);
                resList.add(taskStripOptimizationRes);
            });
        }
        return resList;
    }

    /**
     * 调用有两种情况，单星多圈，和多星多圈
     *
     * @param list 条带入参
     */
    private void getStripsSinglePlanList(List<StripDTO> list, TaskStripOptimizationRes taskStripOptimizationRes) {
        //v是单圈多个侧摆的条带
        Map<String, List<StripDTO>> lists = list.stream().collect(Collectors.groupingBy(e -> e.getSatelliteCode() + ":" + e.getCircle()));
        List<OptimizationStripDTO> optimizationStripDTOList = new ArrayList<>();
        for (Map.Entry<String, List<StripDTO>> entry : lists.entrySet()) {
            for (StripDTO stripDTO : entry.getValue()) {
                OptimizationStripDTO optimizationStripDTO = new OptimizationStripDTO();
                BeanUtils.copyProperties(stripDTO, optimizationStripDTO);
                optimizationStripDTO.setSatelliteCirCleKey(entry.getKey());
                optimizationStripDTOList.add(optimizationStripDTO);
            }
        }

        /*Set<Set<OptimizationStripDTO>> resTemp = new HashSet<>();
        //开始组合
        dfsStripPlan(optimizationStripDTOList, new ArrayList<>(), resTemp);*/
        List<List<OptimizationStripDTO>> resTemp = dfsStripPlan2(optimizationStripDTOList);
        for (List<OptimizationStripDTO> optimizationStripDTOList1 : resTemp) {
            SinglePlan singlePlan = new SinglePlan();
            singlePlan.setReqId(new ArrayList<>(optimizationStripDTOList1).get(0).getReqId());
            singlePlan.setCoverage(getStripGroupCoverage(taskStripOptimizationRes.getTargetGirdCodeList(), new ArrayList<>(optimizationStripDTOList1)));
            singlePlan.setStripDTOList(new ArrayList<>(optimizationStripDTOList1));
            taskStripOptimizationRes.getSinglePlanList().add(singlePlan);
        }
    }

    /**
     * 计算条带覆盖率
     *
     * @param targetGirdSet
     * @param stripDTOList
     * @return
     */
    private Double getStripGroupCoverage(Set<String> targetGirdSet, List<OptimizationStripDTO> stripDTOList) {
        Set<String> stripGirdSet = new HashSet<>();
        for (OptimizationStripDTO optimizationStripDTO : stripDTOList) {
            //  todo 电子星直接返回覆盖率
            if (optimizationStripDTO.getPayloadType().equals("ELECTRON")) {
                return Double.valueOf(optimizationStripDTO.getCoverageRate());
            }
            stripGirdSet.addAll(optimizationStripDTO.getGirdCodeList());
        }
        stripGirdSet.retainAll(targetGirdSet);
        return (double) stripGirdSet.size() / (double) targetGirdSet.size();
    }

    /**
     * 递归搜索（深度优先算法）
     *
     * @param optimizationStripDTOList    该需求所有条带
     * @param addOptimizationStripDTOList 中间结果
     * @param resTemp                     结果集
     */
    public void dfsStripPlan(List<OptimizationStripDTO> optimizationStripDTOList, List<OptimizationStripDTO> addOptimizationStripDTOList, Set<Set<OptimizationStripDTO>> resTemp) {

        if (!addOptimizationStripDTOList.isEmpty())
            resTemp.add(new HashSet<>(addOptimizationStripDTOList));
        for (int i = 0; i < optimizationStripDTOList.size(); i++) {
            List<OptimizationStripDTO> temp = new LinkedList<>(optimizationStripDTOList);
            if (check(addOptimizationStripDTOList, optimizationStripDTOList.get(i))) {
                addOptimizationStripDTOList.add(temp.remove(i));
                dfsStripPlan(temp, addOptimizationStripDTOList, resTemp);
            }
        }
        addOptimizationStripDTOList.clear();
    }

    private static boolean check(List<OptimizationStripDTO> list, OptimizationStripDTO optimizationStripDTO) {
        return list.stream().noneMatch(e -> e.getSatelliteCirCleKey().equals(optimizationStripDTO.getSatelliteCirCleKey()));
    }

    public List<List<OptimizationStripDTO>> dfsStripPlan2(List<OptimizationStripDTO> optimizationStripDTOList) {
        List<List<OptimizationStripDTO>> resTemp = new ArrayList<>();
        resTemp.add(new ArrayList<>());
        for (OptimizationStripDTO optimizationStripDTO : optimizationStripDTOList) {
            //获取当前子集个数
            int size = resTemp.size();
            for (int j = 0; j < size; j++) {
                if (check(resTemp.get(j), optimizationStripDTO)) {
                    List<OptimizationStripDTO> clone = new ArrayList<>(resTemp.get(j));
                    clone.add(optimizationStripDTO);
                    resTemp.add(clone);
                }
            }
        }
        return resTemp.stream().filter(e -> e.size() != 0).collect(Collectors.toList());
    }
}