package com.base.core;

import com.alibaba.fastjson.JSON;
import com.base.api.model.PayloadRpcDTO;
import com.base.core.config.StripAccessConfig;
import com.base.core.model.enity.StripDTO;

import com.base.core.model.enity.*;
import com.base.core.operator.AccessWindowService;
import com.base.core.operator.StripRollCalc;
import com.base.core.utiles.DateUtilsCore;
import com.base.orbit.utils.DateUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.awt.geom.Point2D;
import java.util.*;
import java.util.concurrent.Callable;
import java.util.concurrent.Future;

@Slf4j
@Component
public class StripTemplate {

    @Resource
    BizService bizService;

    @Resource
    AccessWindowService accessWindowService;

    @Resource
    StripAccessConfig stripAccessConfig;

    @Resource
    StripRollCalc stripRollCalc;

    @Resource
    ThreadToolTemplate<List<StripDTO>> threadToolTemplate;


    public List<StripDTO> compute(List<BizReq> bizReqs) {
        List<Future<List<StripDTO>>> futures = new ArrayList<>();
        for (BizReq bizReq : bizReqs) {
            Region region = bizReq.getRegion();
            // 根据时长要求截断成像范围
            try {
                List<EphTrackCoreDTO> ephTrackCoreDTOS = formatEphTrack(bizReq.getEphTrackCoreDTOs(), region);
                for (EphTrackCoreDTO ephTrackCoreDTO : ephTrackCoreDTOS) {
                    for (int i = 0; i < ephTrackCoreDTO.getPayloadLMT().getPayloads().size(); i++) {
                        StripAccessCall stripAccessCall = new StripAccessCall(ephTrackCoreDTO, region,ephTrackCoreDTO.getPayloadLMT().getPayloads().get(i));
                        Future<List<StripDTO>> taskFuture = threadToolTemplate.submitTask(stripAccessCall);
                        futures.add(taskFuture);
                    }
                }
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        return (List<StripDTO>) threadToolTemplate.synAndListGet(futures);
    }

    private List<EphTrackCoreDTO> formatEphTrack(List<EphTrackCoreDTO> exEphData, Region region) throws Exception {

        ReportPoint rp = region.getReportPoint();
        double cen_lon = (rp.getE_node_lon() + rp.getW_node_lon()) / 2;
        double m1, m2;

        // 根据时长要求截断成像范围
        for (Iterator<EphTrackCoreDTO> iterator = exEphData.iterator(); iterator.hasNext(); ) {
            EphTrackCoreDTO ephTrack = iterator.next();
            if (ephTrack.getPayloadLMT() == null) {
                iterator.remove();
                continue;
            }

            int ephcount = (int) ephTrack.getPayloadLMT().getMax_duration();
            if (ephTrack.getPayloadLMT().getMaxInfoBasisPayload().getSwathWidth().intValue() > 1000 * 1000)
                ephcount = 40 * 60;
            if (ephTrack.getSubPointlist().size() > ephcount) {
                int n1 = ephcount / 2;
                m1 = Math.abs(ephTrack.getSubPointlist().get(n1).getLon() - cen_lon);
                int num = ephTrack.getSubPointlist().size() - ephcount;
                int n2 = ephTrack.getSubPointlist().size() - n1;
                m2 = Math.abs(ephTrack.getSubPointlist().get(n2).getLon() - cen_lon);
                List<SubPoint> temptrack = new ArrayList<>();
                if (m1 < m2) {
                    for (int j = 0; j < ephcount; j++) {
                        temptrack.add(ephTrack.getSubPointlist().get(j));
                    }
                } else {
                    for (int j = num; j < ephTrack.getSubPointlist().size(); j++) {
                        temptrack.add(ephTrack.getSubPointlist().get(j));
                    }
                }
                ephTrack.setSubPointlist(temptrack);
            }
            ephTrack.setFlag(true);
            int minephcount = (int) ephTrack.getPayloadLMT().getMin_duration() + 1 + 2;// 20171007
            if (ephTrack.getPayloadLMT().getMaxInfoBasisPayload().getSwathWidth().intValue() > 1000 * 1000)
                minephcount = 40 * 60;
            if (ephTrack.getSubPointlist().size() < minephcount) {

                int count = ephTrack.getSubPointlist().size() / 2;
                Date center_time = ephTrack.getSubPointlist().get(count).getDate();
                // 计算球面上两点间距离，找到离pointA最近的pointB,找cos(alpha) 最大的
                double tempAngle = 0;
                for (int i = 0; i < ephTrack.getSubPointlist().size(); i++) {
                    SubPoint satTrack = ephTrack.getSubPointlist().get(i);
                    // 计算cos(alpha)值
                    double value = Math.sin(satTrack.getLat() * Math.PI / 180)
                            * Math.sin(region.getCenNode().getLat() * Math.PI / 180)
                            + Math.cos(satTrack.getLat() * Math.PI / 180)
                            * Math.cos(region.getCenNode().getLat() * Math.PI / 180)
                            * (Math.cos((satTrack.getLon() - region.getCenNode().getLon()) * Math.PI / 180));
                    if (value > tempAngle) {
                        tempAngle = value;
                        center_time = satTrack.getDate();
                    }
                }

                Date centerTime = center_time;
                Date startTime = new Date(centerTime.getTime() - minephcount * 500L);
                Date entTime = new Date(centerTime.getTime() + minephcount * 500L);
                List<SubPoint> tempTrack =new ArrayList<>();
                String payloadType = ephTrack.getPayloadLMT().getMaxInfoBasisPayload().getPayloadType();
                if(!payloadType.equals("SAR")){
                    /*tempTrack= bizService.getBizSubPointList(ephTrack.getSatallitCode(), startTime, entTime,"1");*/
                    tempTrack = bizService.getBizSubPointList(ephTrack.getSatallitCode(), startTime, entTime);
                }else {
                    tempTrack = bizService.getBizSubPointList(ephTrack.getSatallitCode(), startTime, entTime);
                }
                /*List<SubPoint> tempTrack = bizService.getBizSubPointList(ephTrack.getSatallitCode(), startTime, entTime);*/

                if (CollectionUtils.isEmpty(tempTrack)) {
                    throw new Exception("no suitable eph data for missionstrip!");
                }
                ephTrack.setSubPointlist(tempTrack);
                System.out.println("====");
            }

        }

        LinkedList<EphTrackCoreDTO> resultList = new LinkedList<>();
        LinkedList<EphTrackCoreDTO> workList = new LinkedList<>(exEphData);

        while (!workList.isEmpty()) {
            EphTrackCoreDTO head_track = workList.getFirst();
            String target_start_str = DateUtils.DateToString(head_track.getSubPointlist().get(0).getDate());
            String target_end_str = DateUtils.DateToString(head_track.getSubPointlist().get(head_track.getSubPointlist().size() - 1).getDate());
            Calendar tw1S = DateUtils.stringToCalendar(target_start_str);
            Calendar tw1E = DateUtils.stringToCalendar(target_end_str);
            boolean found_conflict = false;
            EphTrackCoreDTO ephtrack_conflict = null;
            for (EphTrackCoreDTO ephtrack_current : workList) {
                if (head_track != ephtrack_current) {

                    String start_str_cur = DateUtils.DateToString(ephtrack_current.getSubPointlist().get(0).getDate());
                    String end_str_cur = DateUtils.DateToString(ephtrack_current.getSubPointlist()
                            .get(ephtrack_current.getSubPointlist().size() - 1).getDate());
                    Calendar tw2S = DateUtils.stringToCalendar(start_str_cur);
                    Calendar tw2E = DateUtils.stringToCalendar(end_str_cur);
                    if (!((tw1E.before(tw2S)) || (tw1S.after(tw2E)))) {
                        found_conflict = true;
                        ephtrack_conflict = ephtrack_current;
                    }
                }
            }
            if (found_conflict) {

                workList.remove(ephtrack_conflict);
            } else {
                resultList.add(head_track);
                workList.remove(head_track);
            }
        }
        exEphData.clear();
        exEphData.addAll(resultList);
        return exEphData;
    }

    /**
     * 获取网格编码List<String>
     */
    public List<String> calGridList(List<SubPoint> TrackPointlist, Region region, Map<Integer, Integer> regionvalue) throws Exception {
        List<String> tempgrid = new ArrayList<>();
        int size = TrackPointlist.size();
        double temp;
        String updown = TrackPointlist.get(0).getUpdown();
        String updown_end = TrackPointlist.get(size - 1).getUpdown();

        //降轨时左上右下（左点幅宽纬度大于右点幅宽纬度）
        //升轨时左下右上（左点幅宽纬度小于右点幅宽纬度）
        if (updown.equals(updown_end)) {
            if (regionvalue == null || regionvalue.isEmpty()) {
                throw new Exception("calc regionvalue error!");
            }
            for (Map.Entry<Integer, Integer> entry : regionvalue.entrySet()) {
                int i = entry.getKey();
                int count = entry.getValue();
                for (int k = 0; k < region.getOriginArea().get(i).getGridlist().size(); k++) {
                    float c_lon = (float) region.getOriginArea().get(i).getGridlist().get(k).getCLon();
                    if (TrackPointlist.get(count).getLsLon() < c_lon && TrackPointlist.get(count).getRsLon() > c_lon) {
                        tempgrid.add(region.getOriginArea().get(i).getGridlist().get(k).getId());
                    }
                }
            }
        } else {
            //升降軌变轨了
            double dis = 1000;
            int count = 0;
            for (int i = 0; i < region.getOriginArea().size(); i++) {
                float c_lat = (float) region.getOriginArea().get(i).getGridlist().get(0).getCLat();
                for (int j = 0; j < region.getOriginArea().get(i).getGridlist().size(); j++) {
                    float c_lon = (float) region.getOriginArea().get(i).getGridlist().get(j).getCLon();
                    for (int k = 0; k < TrackPointlist.size(); k++) {
                        temp = Math.abs(TrackPointlist.get(k).getLat() - c_lat) + Math.abs(TrackPointlist.get(k).getLon() - c_lon);
                        if (temp < dis) {
                            dis = temp;
                            count = k;
                        }
                    }
                    if (TrackPointlist.get(count).getLsLon() < c_lon && TrackPointlist.get(count).getRsLon() > c_lon) {
                        tempgrid.add(region.getOriginArea().get(i).getGridlist().get(j).getId());
                    }
                }
            }
        }
        if (tempgrid.size() > 0) {
            log.debug("involved gridcode number is:	");
        }
        return tempgrid;
    }

    class StripAccessCall implements Callable<List<StripDTO>> {
        EphTrackCoreDTO ephTrackCoreDTO;
        Region region;
        PayloadRpcDTO payloadRpcDTO;
        StripRollCalc striprollcalc;

        public StripAccessCall(EphTrackCoreDTO ephTrackCoreDTO, Region region,PayloadRpcDTO payloadRpcDTO) {
            this.ephTrackCoreDTO = ephTrackCoreDTO;
            this.region = region;
            this.payloadRpcDTO =payloadRpcDTO;
        }

        @Override
        public List<StripDTO> call() throws Exception {
            try {
                List<?> stripExecute = region.getStripExecuteHandler().stripExecute(region, ephTrackCoreDTO,payloadRpcDTO);
                if (CollectionUtils.isEmpty(stripExecute)){
                    return null;
                }
                if (payloadRpcDTO.getPayloadType().equals("ELECTRON")){
                    List<StripDTO> stripDTOList=new ArrayList<>();
                    for (Object t : stripExecute) {
                        ObjectMapper objectMapper=new ObjectMapper();
                        StripDTO stripDTO=objectMapper.convertValue(t,StripDTO.class);
                        stripDTOList.add(stripDTO);
                    }
                    return stripDTOList;
                }else {
                    //计算太阳高度角
                    double sunAngle = stripRollCalc.calcSunAngle(ephTrackCoreDTO.getSubPointlist());
                    if(region.getAreaorpoint() == 0){
                        List<StripDTO> stripDTOList;
                        if(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(0).getPayloadType().equals("SAR")){
                            //这里计算SAR星对于点目标的条带计算
                            List<StripDTO> list = handlePointComputeTask((List<ImageAccessData>) stripExecute, region, ephTrackCoreDTO, sunAngle);
                            stripDTOList = accessWindowService.accessWindowCombine(list);
                        }else{
                            //这里计算光学星对于点目标的条带计算
                            List<StripDTO> list = handleCcdPointComputeTask(stripExecute, region, ephTrackCoreDTO, sunAngle);
                            stripDTOList = accessWindowService.accessWindowCombine(list);
                        }
                        log.info("-------查询到的条带数据量为:#{}------", stripDTOList.size());
                        return getStripDTOS(stripDTOList);
                    }
                    Map<Integer, Integer> regionValue = new HashMap<>();
                    List<StripDTO> list = new ArrayList<>();
                    for (Object t : stripExecute) {
                        StripDTO stripDTO= handleComputeTask(sunAngle, t, ephTrackCoreDTO, regionValue, region);
                        if (stripDTO!=null){
                            list.add(stripDTO);
                        }
                    }
                    List<StripDTO> stripDTOList=new ArrayList<>();
                    if(null!=list && list.size()>0){
                        stripDTOList= accessWindowService.accessWindowCombine(list);
                    }
                    return stripDTOList;
                }
            }catch (Exception e){
                log.error(e.toString(),e);

                throw e;
            }
        }

        private StripDTO handleComputeTask(double sunAngle, Object t, EphTrackCoreDTO ephTrackCoreDTO, Map<Integer, Integer> regionValue, Region region) throws Exception {
            try{
                StripDTO stripInstance = region.getStripExecuteHandler().formatStripInstance(t);


                stripInstance.setSunAngle(sunAngle);
                //最大幅宽载荷相关信息
                MaxPayload maxPayload = new MaxPayload();
                stripInstance.setSatelliteCode(ephTrackCoreDTO.getSatallitCode());
                SubPoint startpoint = new SubPoint();
                SubPoint endpoint = new SubPoint();
                int duration = 0;
                Map<String, Strip2grid> strip2gridrelation = new HashMap<>();
                for (int j = 0; j < ephTrackCoreDTO.getPayloadLMT().getPayloads().size(); j++) {
                    float maxoverlapwidth = Float
                            .parseFloat(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(j).getOverLap().toString());
                    float maxswathwidth = Float
                            .parseFloat(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(j).getSwathWidth().toString());
                    //计算最大幅宽情况下的条带星下点
                    List<SubPoint> sublist = accessWindowService.calSubPoint(stripInstance.getRollAngle(), ephTrackCoreDTO, maxswathwidth, maxoverlapwidth);
                    if (sublist.isEmpty()) {
                        throw new Exception("Strip sublist is empty!");
                    }
                    if (regionValue.isEmpty()) {
                        regionValue = accessWindowService.calcSublistPosition(sublist, region);
                        if (regionValue.isEmpty()) {
                            continue;
                        }
                    }
                    //计算最大幅宽情况下的包含的网格编码
                    List<String> gridlist = calGridList(sublist, region, regionValue);
                    if (gridlist != null && gridlist.size() > 0) {
                        //计算覆盖率
/*                        gridlist.retainAll(region.getGridlistRegion());
                        stripInstance.setCoverageRate((double) gridlist.size() / (double) region.getGridlistRegion().size());*/
                        stripInstance.setCoverageRate(getStripGroupCoverage(gridlist,region.getGridlistRegion()));

                        stripInstance.setGridcodelist(gridlist);
                        Strip2grid strip2grid = new Strip2grid();
                        strip2grid.setPayload(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(j).getId());
                        strip2grid.setGridcodelist(gridlist);
                        strip2grid.setSublist(sublist);
                        stripInstance.setVertex_points(sublist);
                        //计算目标区域点整对应星历的最短距离时刻
                        /*distence(stripInstance);*/
                        strip2gridrelation.put(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(j).getPayloadType(), strip2grid);
                        if (ephTrackCoreDTO.getPayloadLMT().getMaxInfoBasisPayload().getId().equalsIgnoreCase(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(j).getId())) {
                            maxPayload.setGridcount(gridlist.size());
                            maxPayload.setId(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(j).getId());
                            maxPayload.setSwathWidth(maxswathwidth);
                            maxPayload.setOverlap(maxoverlapwidth);
                            maxPayload.setTrackPointlist(sublist);
                            maxPayload.setSensorname(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(j).getPayloadType());//gaoyue 20190715
                            maxPayload.setResolution(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(j).getGroundResolution());//gaoyue 20190715
                            duration = sublist.size();
                            startpoint = sublist.get(0);
                            endpoint = sublist.get(duration - 1);
                        }
                    }
                }
                stripInstance.setMaxPayload(maxPayload);
                stripInstance.setStartpoint(startpoint);
                stripInstance.setEndpoint(endpoint);
                stripInstance.setObservationStartTime(startpoint.getDate());
                stripInstance.setObservationEndTime(endpoint.getDate());
                stripInstance.setDuration(duration - 1);//chenhy 20170930 做减1处理
                stripInstance.setUpDown(ephTrackCoreDTO.getUpdown());
                stripInstance.setStrip2grid(strip2gridrelation);
                if (maxPayload.getTrackPointlist().size() > 0 && maxPayload.getGridcount() > stripAccessConfig.getMinGridCount()) {
                    return stripInstance;
                }
                return null;
            }catch (Exception e){
                log.error(e.toString(),e);
                return null;
            }

        }
        /**
         * 计算条带覆盖率
         *
         * @param targetGirdSet
         * @param stripDTOList
         * @return
         */
        private Double getStripGroupCoverage(List<String> gridlist, List<String> gridlistRegion) {
            List<String> gridlistnew=new ArrayList<>();
            gridlistnew.addAll(gridlist);
            gridlistnew.retainAll(gridlistRegion);
            double co=(double) gridlistnew.size() / (double) gridlistRegion.size();
            return co;
        }
        private void distence(StripDTO stripInstance){
            List<SphericalPoint> target=stripInstance.getPointInArea();
            List<SubPoint> ephDatas=stripInstance.getVertex_points();
            List<Date> dates=new ArrayList<>();
            for (SphericalPoint sphericalPoint_one : target) {
                int id = 0;

                SubPoint ephdata1, ephdata2, ephdata3;

                SphericalPoint s1 = new SphericalPoint(), s2 = new SphericalPoint(), s3 = new SphericalPoint();

                PositionLLA pos1 = new PositionLLA(), pos2 = new PositionLLA(), pos3 = new PositionLLA();

                double dis1, dis2, dis3;

                double RollAngle;

                while (id < ephDatas.size() - 2) {
                    ephdata1 = new SubPoint();
                    ephdata2 = new SubPoint();

                    String ephdata1str = JSON.toJSONString(ephDatas.get(id));
                    ephdata1 = JSON.parseObject(ephdata1str, SubPoint.class);

                    String ephdata2str = JSON.toJSONString(ephDatas.get(id + 1));
                    ephdata2 = JSON.parseObject(ephdata2str, SubPoint.class);

                    String ephdata3str = JSON.toJSONString(ephDatas.get(id + 2));
                    ephdata3 = JSON.parseObject(ephdata3str, SubPoint.class);

                    /*s1.setLon(ephdata1.getLon());
                    s1.setLat(ephdata1.getLat());
                    s2.setLon(ephdata2.getLon());
                    s2.setLat(ephdata2.getLat());

                    pos1.setLon(ephdata1.getLon());
                    pos1.setLat(ephdata1.getLat());
                    pos1.setHigh(ephdata1.getAlt());
                    pos2.setLon(ephdata2.getLon());
                    pos2.setLat(ephdata2.getLat());
                    pos2.setHigh(ephdata2.getAlt());*/

                    s1.setLon((ephdata1.getLsLon()+ephdata1.getRsLon())/2);
                    s1.setLat((ephdata1.getLsLat()+ephdata1.getRsLat())/2);

                    s2.setLon((ephdata2.getLsLon()+ephdata2.getRsLon())/2);
                    s2.setLat((ephdata2.getLsLat()+ephdata2.getRsLat())/2);

                    s3.setLon((ephdata3.getLsLon()+ephdata3.getRsLon())/2);
                    s3.setLat((ephdata3.getLsLat()+ephdata3.getRsLat())/2);

                    dis1 = SphericalAngle(s1, sphericalPoint_one);// 角度
                    dis2 = SphericalAngle(s2, sphericalPoint_one);// 角度

                    dis3 = SphericalAngle(s3, sphericalPoint_one);// 角度

                    Calendar time2 = Calendar.getInstance();
                    time2.setTime(ephdata2.getDate());

                    if ((dis2 <= dis1) && (dis2 <= dis3) && (dis2 <= 90.0)) {

                        Calendar calendar = Calendar.getInstance();
                        calendar.setTimeInMillis(time2.getTimeInMillis());
                        calendar.add(Calendar.SECOND, -(int) 0);
                        dates.add(calendar.getTime());
                    }
                    id++;
                }

            }
            DateUtilsCore.DateListSort(dates,"asc");
            //时间前后 延长5秒
            if (!CollectionUtils.isEmpty(dates)){
                Date startdate=new Date(dates.get(0).getTime()-10*1000);
                Date endtdate=new Date(dates.get(dates.size()-1).getTime()+10*1000);
                dates.set(0,startdate);
                dates.set(dates.size()-1,endtdate);
            }
            stripInstance.setDates(dates);

        }



        private double SphericalAngle(SphericalPoint source, SphericalPoint target) {
            // double pi=3.14159265358979323846;
            double back;
            SphericalPoint source1 = new SphericalPoint();
            SphericalPoint target1 = new SphericalPoint();
            source1.setLon(source.getLon() * Math.PI / 180.0);
            source1.setLat(source.getLat() * Math.PI / 180.0);
            target1.setLon(target.getLon() * Math.PI / 180.0);
            target1.setLat(target.getLat() * Math.PI / 180.0);

            back = Math.cos(Math.PI / 2 - source1.getLat()) * Math.cos(Math.PI / 2 - target1.getLat())
                    + Math.sin(Math.PI / 2 - source1.getLat()) * Math.sin(Math.PI / 2 - target1.getLat())
                    * Math.cos(Math.abs(source1.getLon() - target1.getLon()));

            return Math.acos(back) * 180.0 / Math.PI;
        }

        /**
         * 计算SAR点目标条带数据
         * @param imageAccessDatas：成像卫星访问计算结果集合
         * @param region：观测区域
         * @param ephTrack：卫星星下点数据
         * @return
         * @throws Exception
         */
        private List<StripDTO> handlePointComputeTask(List<ImageAccessData> imageAccessDatas, Region region, EphTrackCoreDTO ephTrack,double sunAngle) throws Exception {

            log.debug("debug", "begin to PointstripServiceImpl.calcStrip", "");

            if (imageAccessDatas == null || imageAccessDatas.size() == 0) {
                throw new Exception("no suitable rollangle for strip!");
            }
            List<String> gridlist = new ArrayList<>();
            for (int i = 0; i < region.getOriginArea().size(); i++) {
                gridlist.addAll(region.getOriginArea().get(i).getGridListCode());
            }
            if (gridlist == null || gridlist.isEmpty()) {
                throw new Exception("no gridcode for strip!");
            } else {
                List<StripDTO> striplist = new ArrayList<StripDTO>();
                for (int i = 0; i < imageAccessDatas.size(); i++) {
                    double rollAngle = imageAccessDatas.get(i).getRollAngle();
                    StripDTO stripInstance = region.getStripExecuteHandler().formatStripInstance(imageAccessDatas.get(i));;

                    stripInstance.setRollAngle(rollAngle);
                    stripInstance.setSunAngle(sunAngle);
                    stripInstance.setAccessTime(imageAccessDatas.get(i).getAccessTime());
                    stripInstance.setSatelliteId(ephTrack.getSatalliteid());
                    Map<String, Strip2grid> strip2gridrelation = new HashMap<String, Strip2grid>();
                    MaxPayload maxPayload = new MaxPayload();
                    SubPoint startpoint = new SubPoint();
                    SubPoint endpoint = new SubPoint();
                    int duration = 0;
                    for (int j = 0; j < ephTrack.getPayloadLMT().getPayloads().size(); j++) {
                        float maxOverLapWidth = Float
                                .parseFloat(ephTrack.getPayloadLMT().getPayloads().get(j).getOverLap().toString());
                        float maxSwathWidth = Float
                                .parseFloat(ephTrack.getPayloadLMT().getPayloads().get(j).getSwathWidth().toString());
                        List<SubPoint> sublist = new ArrayList<>();

                        // 计算星下点
                        int count = ephTrack.getSubPointlist().size() / 2;
                        int duration_lmt = (int) ephTrack.getPayloadLMT().getMin_duration() + 1;
                        Date center_time = ephTrack.getSubPointlist().get(count).getDate();
                        Date starttime = new Date(center_time.getTime() - duration_lmt * 500);
                        Date enttime = new Date(center_time.getTime() + duration_lmt * 500);
                        List<SubPoint> subPoints =new ArrayList<>();
                        if(!ephTrack.getPayloadLMT().getMaxInfoBasisPayload().getPayloadType().equals("SAR")){
                            subPoints= bizService.getBizSubPointList(ephTrack.getSatallitCode(), starttime, enttime,"1");
                        }else {
                            subPoints = bizService.getBizSubPointList(ephTrack.getSatallitCode(), starttime, enttime);
                        }
                        /*List<SubPoint> subPoints = bizService.getBizSubPointList(ephTrack.getSatallitCode(), starttime, enttime);
                         */
                        Date accessTime = imageAccessDatas.get(i).getAccessTime();
                        sublist = accessWindowService.calSubPointForSarPoint(stripInstance.getRollAngle(), accessTime, ephTrackCoreDTO, maxSwathWidth, maxOverLapWidth,region);
                        if (sublist == null || sublist.isEmpty()) {
                            // Log.getInstance().getLogger().error("execute.fail",
                            // "calcStrip","sublist is empty");
                            throw new Exception("Strip sublist is empty!");
                        } else {
                            Strip2grid strip2grid = new Strip2grid();
                            strip2grid.setPayload(ephTrack.getPayloadLMT().getPayloads().get(j).getId());
                            strip2grid.setGridcodelist(gridlist);
                            strip2grid.setSublist(sublist);
                            stripInstance.setVertex_points(sublist);
                            //计算目标区域点整对应星历的最短距离时刻
                            //条带截取
                            /*distence(stripInstance);*/
                            strip2gridrelation.put(ephTrack.getPayloadLMT().getPayloads().get(j).getId(), strip2grid);
                            if (ephTrack.getPayloadLMT().getMaxInfoBasisPayload().getId()
                                    .equalsIgnoreCase(ephTrack.getPayloadLMT().getPayloads().get(j).getId())) {
                                maxPayload.setGridcount(gridlist.size());
                                maxPayload.setId(ephTrack.getPayloadLMT().getPayloads().get(j).getId());
                                maxPayload.setSwathWidth(maxSwathWidth);
                                maxPayload.setOverlap(maxOverLapWidth);
                                maxPayload.setTrackPointlist(sublist);
                                maxPayload.setSensorname(ephTrack.getPayloadLMT().getPayloads().get(j).getId());
                                maxPayload.setResolution(ephTrack.getPayloadLMT().getPayloads().get(j).getGroundResolution());
                                duration = sublist.size();
                                startpoint = sublist.get(0);
                                endpoint = sublist.get(duration - 1);
                            }

                        }

                    }
                    stripInstance.setMaxPayload(maxPayload);
                    stripInstance.setStartpoint(startpoint);
                    stripInstance.setEndpoint(endpoint);
                    stripInstance.setObservationStartTime(startpoint.getDate());
                    stripInstance.setObservationEndTime(endpoint.getDate());
                    stripInstance.setDuration(duration - 1);// chenhy
                    // 20170930
                    // 做减1处理
                    stripInstance.setUpDown(ephTrack.getUpdown());
                    if (strip2gridrelation == null || strip2gridrelation.isEmpty()) {
                        log.error("error", "strip.getStrip2grid() == null!");
                        throw new Exception("calculate Strip of gridcode error!");
                        // System.out.println("Strip has no gridlist!");
                    }
                    stripInstance.setStrip2grid(strip2gridrelation);

                    if (maxPayload.getTrackPointlist().size() > 0 && maxPayload.getGridcount() > 0) {
                        striplist.add(stripInstance);
                    }
                }
                log.debug("debug", "PointstripServiceImpl.calcStrip finished", "");
                return striplist;
            }
        }

        /**
         * 光学星条带处理方法
         * @param stripExecute
         * @param region
         * @param ephTrackCoreDTO
         * @return
         */
        private List<StripDTO> handleCcdPointComputeTask(List<?> stripExecute, Region region, EphTrackCoreDTO ephTrackCoreDTO,double sunAngle) throws Exception {
            List<CcdPoint> ccdPoints=(List<CcdPoint>) stripExecute;
            if (CollectionUtils.isEmpty(ccdPoints)){
                return null;
            }
            List<Double> rollAngleList =ccdPoints.get(0).getRollAngleList();
            List<StripDTO> striplist = new ArrayList<StripDTO>();
            SubPoint nearPoint = ccdPoints.get(0).getNearPoint();

            Date newVisitTime = nearPoint.getDate();
            striplist = calcCcdPointStrip(rollAngleList, region, ephTrackCoreDTO, newVisitTime,sunAngle);
            if ((striplist!=null)&&(striplist.size()>0)) {
                striplist.get(0).setAccessTime(newVisitTime);
            }
            return striplist;
        }

        /**
         * 光学星点目标条带计算
         * @param rollAngleList
         * @param region
         * @param ephTrackCoreDTO
         * @param newVisitTime
         * @return
         */
        private List<StripDTO> calcCcdPointStrip(List<Double> rollAngleList, Region region, EphTrackCoreDTO ephTrackCoreDTO, Date newVisitTime,double sunangle) throws Exception {
            log.debug("debug", "begin to PointstripServiceImpl.calcStrip", "");

            if (rollAngleList == null || rollAngleList.size() == 0) {
                throw new Exception("no suitable rollangle for strip!");
            }
            List<String> gridlist = new ArrayList<>();
            for (int i = 0; i < region.getOriginArea().size(); i++) {
                gridlist.addAll(region.getOriginArea().get(i).getGridListCode());
            }
            if (gridlist == null || gridlist.isEmpty()) {
                throw new Exception("no gridcode for strip!");
            } else {
                List<StripDTO> striplist = new ArrayList<StripDTO>();

                for (Iterator iterator = rollAngleList.iterator(); iterator.hasNext(); ) {
                    double rollangle = (double) iterator.next();
                    StripDTO stripinstance = new StripDTO();
                    List<SphericalPoint> pointInArea = regionToListSphericalPoint(region);
                    stripinstance.setPointInArea(pointInArea);
                    double roll_lmt = ephTrackCoreDTO.getPayloadLMT().getLmt_rollangle();
                    if (Math.abs(rollangle) <= Math.abs(roll_lmt)) {
                        roll_lmt = rollangle;
                    } else {
                        if (rollangle < 0) {
                            roll_lmt = roll_lmt * (-1);
                        }
                    }
                    stripinstance.setRollAngle(roll_lmt);
                    stripinstance.setSunAngle(sunangle);

                    stripinstance.setSatelliteId(ephTrackCoreDTO.getSatalliteid());
                    Map<String, Strip2grid> strip2gridrelation = new HashMap<String, Strip2grid>();
                    MaxPayload maxPayload = new MaxPayload();
                    SubPoint startpoint = new SubPoint();
                    SubPoint endpoint = new SubPoint();
                    int duration = 0;
                    for (int j = 0; j < ephTrackCoreDTO.getPayloadLMT().getPayloads().size(); j++) {
                        float maxoverlapwidth = Float
                                .parseFloat(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(j).getOverLap().toString());
                        float maxswathwidth = Float
                                .parseFloat(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(j).getSwathWidth().toString());
                        List<SubPoint> sublist = new ArrayList<>();
                        // 计算星下点
                        sublist = accessWindowService.calSubPointForCcdPoint(rollangle, ephTrackCoreDTO, maxswathwidth, maxoverlapwidth, region);
                        if (sublist == null || sublist.isEmpty()) {
                            throw new Exception("Strip sublist is empty!");
                        } else {
                            Strip2grid strip2grid = new Strip2grid();
                            strip2grid.setPayload(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(j).getId());
                            strip2grid.setGridcodelist(gridlist);
                            strip2grid.setSublist(sublist);
                            if (!CollectionUtils.isEmpty(sublist)){
                                stripinstance.setVertex_points(sublist);
                            }
                            strip2gridrelation.put(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(j).getSatelliteId(), strip2grid);
                            if (ephTrackCoreDTO.getPayloadLMT().getMaxInfoBasisPayload().getId()
                                    .equalsIgnoreCase(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(j).getId())) {
                                maxPayload.setGridcount(gridlist.size());
                                maxPayload.setId(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(j).getId());
                                maxPayload.setSwathWidth(maxswathwidth);
                                maxPayload.setOverlap(maxoverlapwidth);
                                maxPayload.setTrackPointlist(sublist);
                                maxPayload.setSensorname(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(j).getSatelliteId());//gaoyue 20190715
                                maxPayload.setResolution(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(j).getGroundResolution());//gaoyue 20190715
                                duration = sublist.size();
                                startpoint = sublist.get(0);
                                endpoint = sublist.get(duration - 1);
                            }

                        }

                    }
                    stripinstance.setMaxPayload(maxPayload);
                    stripinstance.setStartpoint(startpoint);
                    stripinstance.setEndpoint(endpoint);
                    stripinstance.setObservationStartTime(startpoint.getDate());
                    stripinstance.setObservationEndTime(endpoint.getDate());
                    stripinstance.setDuration(duration - 1);// chenhy20170930做减1处理
                    stripinstance.setUpDown(ephTrackCoreDTO.getUpdown());
                    if (strip2gridrelation == null || strip2gridrelation.isEmpty()) {
                        throw new Exception("calculate Strip of gridcode error!");
                    }
                    stripinstance.setStrip2grid(strip2gridrelation);

                    if (maxPayload.getTrackPointlist().size() > 0 && maxPayload.getGridcount() > 0) {
                        striplist.add(stripinstance);
                    }
                }
                log.debug("debug", "PointstripServiceImpl.calcStrip finished", "");
                return striplist;
            }
        }
        private List<SphericalPoint> regionToListSphericalPoint(Region region) {
            List<SphericalPoint> pointInArea = new ArrayList<>();
            SphericalPoint sphericalPoint = new SphericalPoint();
            sphericalPoint.setLat(region.getCenNode().getLat());
            sphericalPoint.setLon(region.getCenNode().getLon());
            pointInArea.add(sphericalPoint);

            return pointInArea;
        }
        /**
         * 获取准确的条带数据
         * @param stripDTOList
         * @return
         */
        private List<StripDTO> getStripDTOS(List<StripDTO> stripDTOList) {
            List<StripDTO> stripList = new ArrayList<StripDTO>();
            for (int i = 0; i < stripDTOList.size(); i++) {
                StripDTO stripDTO = stripDTOList.get(i);
                SubPoint subPointStart = new SubPoint();
                SubPoint subPointEnd = new SubPoint();
                for (int j = 0; j < stripDTO.getVertex_points().size() ; j++) {
                    SubPoint subPoint = stripDTO.getVertex_points().get(j);
                  /*  if (subPoint.getDate().getTime() == stripDTO.getDates().get(0).getTime()) {*/
                        subPointStart = subPoint;
                        subPointEnd = stripDTO.getVertex_points().get((stripDTO.getVertex_points().size() - 1));
                        break;
                    /*}*/
                }

                Point2D.Double pointOne = new Point2D.Double(subPointStart.getLsLon(),subPointStart.getLsLat());
                Point2D.Double pointTwo = new Point2D.Double(subPointStart.getRsLon(),subPointStart.getRsLat());
                Point2D.Double pointThree = new Point2D.Double(subPointEnd.getRsLon(),subPointEnd.getRsLat());
                Point2D.Double pointFour = new Point2D.Double(subPointEnd.getLsLon(),subPointEnd.getLsLat());
                Point2D.Double pointTarget = new Point2D.Double(stripDTO.getPointInArea().get(0).getLon(),stripDTO.getPointInArea().get(0).getLat());

                ArrayList<Point2D.Double> points = new ArrayList<Point2D.Double>();
                points.add(pointOne);
                points.add(pointTwo);
                points.add(pointThree);
                points.add(pointFour);

                //利用射线法判断目标点是否落在条带区域上
                Boolean contains = isPointInPolygon(pointTarget, points);
                if(contains){
                    stripList.add(stripDTO);
                }

            }
            log.info("-------处理后条带数据量为:#{}------", stripList.size());
            return stripList;
        }

        private Boolean isPointInPolygon(Point2D.Double pointTarget, ArrayList<Point2D.Double> points) {
            int count = 0;
            int size = points.size();
            double dLon1 = 0, dLat1 = 0, dLon2 = 0, dLat2 = 0, dLon;
            double pointLon = pointTarget.x;
            double pointLat = pointTarget.y;

            for (int i = 0; i < size; i++) {
                if (i == size - 1) {
                    dLon1 = points.get(i).x;
                    dLat1 = points.get(i).y;
                    dLon2 = points.get(0).x;
                    dLat2 = points.get(0).y;
                } else {
                    dLon1 = points.get(i).x;
                    dLat1 = points.get(i).y;
                    dLon2 = points.get(i + 1).x;
                    dLat2 = points.get(i + 1).y;
                }

                //以下语句判断目标点是否在边的两端点的水平平行线之间，在则可能有交点，开始判断交点是否在左射线上
                if(((pointLat >= dLat1) && (pointLat < dLat2)) || ((pointLat >= dLat2) && (pointLat < dLat1))){
                    if(Math.abs(dLat1 - dLat2) > 0){
                        //得到A点向左射线与边交点的x坐标
                        dLon = dLon1 - ((dLon1 - dLon2) * (dLat1 - pointLat)) / (dLat1 - dLat2);
                        if(dLon <= pointLon){
                            count++;
                        }
                    }
                }

            }
            if((count % 2) != 0){
                return true;
            }else{
                return false;
            }
        }
    }
}