package com.base.core.handler;

import com.base.api.model.PayloadRpcDTO;
import com.base.api.model.SubPointDataRpcDTO;
import com.base.core.config.ElectronImageLimitation;
import com.base.core.config.ImageLimitation;
import com.base.core.model.enity.*;
import com.base.core.model.enums.StripAccessTypeEnums;
import com.base.core.service.AccessWindowsService;
import com.base.core.service.ElectronAccessService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;

@Service
@Slf4j
@MappingCore(stripAccessTypeEnums =  StripAccessTypeEnums.AREA_ELECTRONIC)
public class ElectronAreaStripAccessHandler implements StripExecuteHandler<StripDTO>{
    @Resource
    private ImageLimitation rLimit;

    @Override
    public List<StripDTO> stripExecute(Region region, EphTrackCoreDTO ephTrackCoreDTO, PayloadRpcDTO payloadRpcDTO) throws Exception {
        List<SphericalPoint> point_inarea=regionToListSphericalPoint(region);

        AccessWindowsService electronAccessWindow = new ElectronAccessService();


        //accessWindowsService.setTimeStep();
        initSatelliteInfo(electronAccessWindow,ephTrackCoreDTO);
        List<EphData> ephdataList = convertSubspToEPH(ephTrackCoreDTO.getSubPointlist());
        //电子星 固定十分钟，小于十分钟的将不被输出
        List<AccessData> test_result  = electronAccessWindow.imageAccessAll(point_inarea,ephdataList,0);
        return electronAccessDataToStrip(test_result, ephTrackCoreDTO.getPayloadLMT());
    }

    public List<StripDTO> electronAccessDataToStrip(List<AccessData> electronDatas, PayloadLMTCoreDTO payloadLMT) {
        List<StripDTO> striplist = new ArrayList<>();
        List<PayloadRpcDTO> payloads = payloadLMT.getPayloads();
        PayloadRpcDTO infoBasisPayload = payloads.get(0);

        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        formatter.setTimeZone(TimeZone.getTimeZone("UTC"));

        for (AccessData electronData : electronDatas) {
            StripDTO strip = new StripDTO();
            strip.setObservationStartTime(electronData.getBeginTime());
            strip.setObservationEndTime(electronData.getEndTime());
            strip.setPitchAngle(Double.valueOf(electronData.getPitchAngle()));
            long duration = (electronData.getEndTime().getTime() - electronData.getBeginTime().getTime()) / 1000;
            strip.setDuration(Math.toIntExact(duration));
            MaxPayload maxPayload = new MaxPayload();
            maxPayload.setId(infoBasisPayload.getId());
            maxPayload.setSwathWidth(infoBasisPayload.getSwathWidth());
            maxPayload.setOverlap(infoBasisPayload.getOverLap());
            maxPayload.setSensorname("ELECTRON");//gaoyue 20190715
            maxPayload.setResolution(0);//gaoyue 20190715
            strip.setMaxPayload(maxPayload);
            strip.setCoverageRate(electronData.getCoverage_percentage());

            if (electronData.getVertex_Points().size() >= 36) {
                SubPoint subPoint_s = new SubPoint();
                subPoint_s.setLon(electronData.getVertex_Points().get(8).getLon());
                subPoint_s.setLat(electronData.getVertex_Points().get(8).getLat());
                subPoint_s.setLsLon(electronData.getVertex_Points().get(0).getLon());
                subPoint_s.setLsLat(electronData.getVertex_Points().get(0).getLat());
                subPoint_s.setRsLon(electronData.getVertex_Points().get(17).getLon());
                subPoint_s.setRsLat(electronData.getVertex_Points().get(17).getLat());
                SubPoint subPoint_e = new SubPoint();
                subPoint_e.setLon(electronData.getVertex_Points().get(26).getLon());
                subPoint_e.setLat(electronData.getVertex_Points().get(26).getLat());
                subPoint_e.setLsLon(electronData.getVertex_Points().get(35).getLon());
                subPoint_e.setLsLat(electronData.getVertex_Points().get(35).getLat());
                subPoint_e.setRsLon(electronData.getVertex_Points().get(18).getLon());
                subPoint_e.setRsLat(electronData.getVertex_Points().get(18).getLat());
                strip.setStartpoint(subPoint_s);
                strip.setEndpoint(subPoint_e);
                List<SubPoint> listSubpoints_vertex = new ArrayList<>();
                for (SphericalPoint sphericalPoint : electronData.getVertex_Points()) {
                    SubPoint subPoint = new SubPoint();
                    subPoint.setLon(sphericalPoint.getLon());
                    subPoint.setLat(sphericalPoint.getLat());
                    listSubpoints_vertex.add(subPoint);

                }
                strip.setVertex_points(listSubpoints_vertex);

                //电子星由于覆盖范围 比较大 ，原 全局网格模式性能较差 ，这里改为 局部 网格 。
                //形式 如：
                //6;1,2,3,
                //分号分割 为两段，前面 为目标区域 编码的数量（从0开始的连续编码） ，后面为 当前 条带 覆盖的编码以“，”分割
                String strip2grid = null;
                int biggest_code_num = 0;
                for (Integer code : electronData.getTargetAreaGridsCodeSet()) {

                    if (biggest_code_num < code) {
                        biggest_code_num = code;
                    }
                }

                strip2grid = Integer.toString(biggest_code_num + 1);

                strip2grid += ";";
                String stripCodestr = null;
                for (Integer code : electronData.getAccessDataGridsCodeSet()) {
                    if (stripCodestr == null) {
                        stripCodestr = code.toString();
                    } else {
                        stripCodestr += "," + code;
                    }
                }
                strip2grid += stripCodestr;
                Map<String, Strip2grid> mapGrid = new HashMap();
                Strip2grid s2g = new Strip2grid();
                s2g.setPayload("ele");
                List list = new ArrayList<String>();
                list.add(strip2grid);
                s2g.setGridcodelist(list);
                mapGrid.put("ele", s2g);
                strip.setStrip2grid(mapGrid);
            }

            striplist.add(strip);
        }

        return striplist;
    }

    @Override
    public StripDTO formatStripInstance(StripDTO stripDTO) {
        return null;
    }

    public List<EphData> convertSubspToEPH(List<SubPoint> ephList){
        List<EphData> listEph = null;
        if(ephList!=null){
            if(ephList.size()>0){
                listEph = new ArrayList<>(ephList.size());
                for(SubPoint subPoint:ephList){
                    EphData ephData = new EphData();
                    ephData.setHigh(subPoint.getAlt());
                    ephData.setLat(subPoint.getLat());
                    ephData.setLon(subPoint.getLon());
                    ephData.setPassNum(Integer.parseInt(subPoint.getOrbit()));
                    ephData.setSatName(subPoint.getSatelliteId());
                    ephData.setEpochTime(subPoint.getDate());
                    listEph.add(ephData);
                }

            }
        }
        return listEph;
    }

    public void initSatelliteInfo(AccessWindowsService accessWindowsService, EphTrackCoreDTO ephTrackCoreDTO) {
        ElectronImageLimitation eLimitation = ElectronImageLimitation.getSample18ImageLimit();//getSample8ImageLimit();//
        double swathWidth = ephTrackCoreDTO.getPayloadLMT().getPayloads().get(0).getSwathWidth();//直径
        //地面最大覆盖距离
        eLimitation.setMaxDistance_to_shot(swathWidth / 1000 / 2);//半径
        eLimitation.setSwathInKM((float) swathWidth / 1000);
        //轨道高度 公里
        eLimitation.setAltitude(ephTrackCoreDTO.getSubPointlist().get(0).getAlt());
        //轨道倾角，用不到，暂不设置
        //最大视场角
        double MaxConeangle = Double.parseDouble(ephTrackCoreDTO.getPayloadLMT().getPayloads().get(0).getFox());
        eLimitation.setMaxConeAngle(MaxConeangle);
        //单次开机限制 30分钟
        eLimitation.setMaxAccessDuration(rLimit.getMaxEleDuration());
        accessWindowsService.setup(eLimitation);
    }

    public List<SphericalPoint> regionToListSphericalPoint(Region region)
    {

        List<SphericalPoint> point_inarea= new ArrayList<>();
        if (region.getAreaorpoint()==0){
            SphericalPoint sphericalPoint= new SphericalPoint();
            sphericalPoint.setLat(region.getCenNode().getLat());
            sphericalPoint.setLon(region.getCenNode().getLon());
            point_inarea.add(sphericalPoint);
        }else {

            SphericalPoint sphericalPointNW= new SphericalPoint();
            sphericalPointNW.setLat(region.getNwNode().getLat());
            sphericalPointNW.setLon(region.getNwNode().getLon());
            point_inarea.add(sphericalPointNW);

            SphericalPoint sphericalPointNE= new SphericalPoint();
            sphericalPointNE.setLat(region.getNeNode().getLat());
            sphericalPointNE.setLon(region.getNeNode().getLon());
            point_inarea.add(sphericalPointNE);

            SphericalPoint sphericalPointSW= new SphericalPoint();
            sphericalPointSW.setLat(region.getSwNode().getLat());
            sphericalPointSW.setLon(region.getSwNode().getLon());
            point_inarea.add(sphericalPointSW);

            SphericalPoint sphericalPointSE= new SphericalPoint();
            sphericalPointSE.setLat(region.getSeNode().getLat());
            sphericalPointSE.setLon(region.getSeNode().getLon());
            point_inarea.add(sphericalPointSE);
        }

        return point_inarea;
    }


}
