package com.base.plan.deal.impl;


import com.alibaba.cloud.commons.lang.StringUtils;
import com.base.api.model.PointRpcDTO;
import com.base.core.model.enity.ArcCoreDTO;
import com.base.core.model.enity.GridInfoCoreDTO;
import com.base.orbit.utils.BizUtils;
import com.base.orbit.utils.IdGenerator;
import com.base.plan.aysc.AsyncTask;
import com.base.plan.constant.Constants;
import com.base.plan.deal.NuaaFileHandler;
import com.base.plan.mapper.StripMapper;
import com.base.plan.model.dto.OptimizationStripDTO;
import com.base.plan.model.dto.PlanBizInfo;
import com.base.plan.model.dto.PointDTO;
import com.base.plan.model.entity.GridInfo;
import com.base.plan.model.entity.StripInfo;
import com.base.plan.service.ArcService;
import com.base.task.model.Task;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Service
@Slf4j
public class PointNuaaFileHandler implements NuaaFileHandler {

    @Resource
    ArcService arcService;
    @Resource
    StripMapper stripMapper;
    @Resource
    AsyncTask asyncTask;

    @Override
    public void saveData(String pointStr, String stripId, String rollAngle, Task task) {
        if (!StringUtils.isBlank(pointStr)) {
            Pattern r = Pattern.compile(Constants.PATTERN);

            Matcher matcher = r.matcher(pointStr);
            List str = new ArrayList();

            while (matcher.find()) {
                str.add(matcher.group());
            }

            String lons = String.valueOf(str.get(0));
            String lats = String.valueOf(str.get(1));
            //  按照空格分隔经纬度存入集合
            List<String> lonlist = Arrays.asList(lons.substring(1, lons.length() - 1).replace(";", " ").split(Constants.BLANK_SPACE));
            List<String> latlist = Arrays.asList(lats.substring(1, lats.length() - 1).replace(";", " ").split(Constants.BLANK_SPACE));
            List<PointRpcDTO> pointInfos = new ArrayList<>();

            if (latlist.size() == Constants.POINT_NUM && lonlist.size() == Constants.POINT_NUM) {
                for (int i = 0; i < Constants.POINT_NUM; i++) {
                    PointRpcDTO pointRpcDTO = new PointRpcDTO();
                    pointRpcDTO.setId(String.valueOf(IdGenerator.getId()));
                    pointRpcDTO.setLatitude(latlist.get(i));
                    pointRpcDTO.setLongitude(lonlist.get(i));
                    pointRpcDTO.setParentId(stripId);
                    pointRpcDTO.setSort("1");
                    pointRpcDTO.setPointType("STRIP");
                    pointInfos.add(pointRpcDTO);
                }
            }
            List<PointRpcDTO> pointInfolist= sort(pointInfos);
            //  异步调用基础服务对点入库
            asyncTask.addPointList(pointInfolist);
            //排序
            //  计算条带网格
            List<String> girds = totalGird(pointInfolist);
            //  根据条带id更新网格和计算覆盖率
            StripInfo stripInfo = new StripInfo();
            stripInfo.setId(stripId);
            stripInfo.setGridIds(org.apache.commons.lang3.StringUtils.join(girds, ","));
            //  通过任务中获取
            PlanBizInfo planBizInfo = (PlanBizInfo) task.getBaseBizInfo();
            stripInfo.setCoverageRate(String.valueOf(coverageRate(girds, planBizInfo.getPointRpcDTOS())));

            stripMapper.updateById(stripInfo);
        }
    }

    /**
     * 根据区域网格和条带网格计算覆盖率
     *
     * @param stripGirds   条带网格
     * @param pointRpcDTOS 区域点
     * @return coverageRate 覆盖率
     */
    public Double coverageRate(List<String> stripGirds, List<PointRpcDTO> pointRpcDTOS) {
        try {
            //  区域网格
            List<String> targetGirds = totalGird(pointRpcDTOS);
            stripGirds.retainAll(targetGirds);

            return (double) stripGirds.size() / (double) targetGirds.size();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据点经纬度查询网格
     *
     * @param pointInfos 点对象
     */
    public List<String> totalGird(List<PointRpcDTO> pointInfos) {
        List<ArcCoreDTO> pointListArcList = arcService.getPointListArcList(pointInfos);
        List<String> gridIds = new ArrayList<>();
        pointListArcList.stream().forEach(pointListArc -> {
                    List<String> ids = pointListArc.getGridlist().stream().map(GridInfoCoreDTO::getId).collect(Collectors.toList());
                    gridIds.addAll(ids);
                }
        );
        return gridIds;
    }
    public  List<PointRpcDTO> sort(List<PointRpcDTO> pointInfos){
        List<PointRpcDTO> pointInfoList=new ArrayList<>();
        for (int i=0;i<pointInfos.size()-1;i++){
            for (int j=0;j<pointInfos.size()-1-i;j++){
                if (Double.valueOf(pointInfos.get(j).getLongitude())>Double.valueOf(pointInfos.get(j+1).getLongitude())){
                    PointRpcDTO pointInfo=new PointRpcDTO();
                    BeanUtils.copyProperties(pointInfos.get(j), pointInfo);
                    BeanUtils.copyProperties(pointInfos.get(j+1), pointInfos.get(j));
                    BeanUtils.copyProperties(pointInfo, pointInfos.get(j+1));
                }
            }
        }
        //经度最小的 最左边的点
        PointRpcDTO pointRpcDTOZ=pointInfos.get(0);
        pointRpcDTOZ.setSerial("0");
        //经度第二小的 也在左边 现在判断上下 写入序号
        PointRpcDTO pointRpcDTOZ2=pointInfos.get(1);
        //右边两个点
        PointRpcDTO pointRpcDTOY1=pointInfos.get(2);
        PointRpcDTO pointRpcDTOY2=pointInfos.get(3);

        if (Double.valueOf(pointRpcDTOZ.getLatitude())>Double.valueOf(pointRpcDTOZ2.getLatitude())){
            //初始点纬度大 就在左上
            pointRpcDTOZ2.setSerial("3");
            if (Double.valueOf(pointRpcDTOY1.getLatitude())>Double.valueOf(pointRpcDTOY2.getLatitude())){
                //右边两个点纬度大
                pointRpcDTOY1.setSerial("1");
                pointRpcDTOY2.setSerial("2");
            }else {
                pointRpcDTOY1.setSerial("2");
                pointRpcDTOY2.setSerial("1");
            }
        }else {
            //初始点纬度小 就在左下
            pointRpcDTOZ2.setSerial("1");
            if (Double.valueOf(pointRpcDTOY1.getLatitude())>Double.valueOf(pointRpcDTOY2.getLatitude())){
                //右边两个点纬度大
                pointRpcDTOY1.setSerial("2");
                pointRpcDTOY2.setSerial("3");
            }else {
                pointRpcDTOY1.setSerial("3");
                pointRpcDTOY2.setSerial("2");
            }
        }
        pointRpcDTOZ.setCreateTime(new Date());
        pointRpcDTOZ2.setCreateTime(new Date());
        pointRpcDTOY1.setCreateTime(new Date());
        pointRpcDTOY2.setCreateTime(new Date());
        pointInfoList.add(pointRpcDTOZ);
        pointInfoList.add(pointRpcDTOZ2);
        pointInfoList.add(pointRpcDTOY1);
        pointInfoList.add(pointRpcDTOY2);
        return pointInfoList;
    }
}
