package com.base.core.handler;

import com.base.api.model.PayloadRpcDTO;
import com.base.core.config.StripAccessConfig;
import com.base.core.model.enity.EphRelation;
import com.base.core.model.enity.EphTrackCoreDTO;
import com.base.core.model.enity.Region;
import com.base.core.model.enity.StripDTO;
import com.base.core.model.enums.StripAccessTypeEnums;
import com.base.core.operator.StripRollCalc;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

@MappingCore(stripAccessTypeEnums = StripAccessTypeEnums.AREA_CCD_COMMON)
@Service
@Slf4j
public class CcdAreaStripHandler implements StripExecuteHandler<Double> {

    @Resource
    private StripRollCalc striprollcalc;

    @Resource
    StripAccessConfig stripAccessConfig;

    @Override
    public List<Double> stripExecute(Region region, EphTrackCoreDTO ephtrack, PayloadRpcDTO payloadRpcDTO) throws Exception {
        try{
            EphRelation ephrelation = calcEphrelation(region,ephtrack);
            String relation = ephrelation.getRollrelation();
            if(relation.equalsIgnoreCase("separate")){
                return null;
            }
            float maxrollangle = ephtrack.getPayloadLMT().getMax_rollangle();
            double[] roll = striprollcalc.calrollangle(relation, region, ephtrack,maxrollangle);
            if(Math.abs(roll[0]) > 180){
                log.error("calculate max left rollAngle error!"+region.getBizSerial());
                throw new Exception("calculate max left rollangle error!");
            }
            if(Math.abs(roll[1]) > 180){
                log.error("calculate max right rollAngle error! "+region.getBizSerial());
                throw new Exception("calculate max right rollangle error!");
            }

            String method = stripAccessConfig.getRollAngleMethod();
            double degree_split = stripAccessConfig.getDegreeSplit();
            int piece_count = stripAccessConfig.getPieceCount();
            List<Double> rollanglelist;
            if(method.equalsIgnoreCase("degree_mothod")){
                rollanglelist = striprollcalc.calRoll(roll[0],roll[1],
                        ephtrack.getPayloadLMT().getLmt_rollangle(),degree_split);
            }else{
                rollanglelist = striprollcalc.calRollbyPiece(roll[0],roll[1],
                        ephtrack.getPayloadLMT().getLmt_rollangle(),piece_count);
            }
            return rollanglelist;
        }catch (Exception e){
            log.error(e.toString(),e);
            return null;
        }
    }

    /**
     * 计算星下点轨迹与观测区域的关系
     * @param region
     * @param ephtrack
     * @return
     */

    public EphRelation calcEphrelation(Region region, EphTrackCoreDTO ephtrack) throws Exception{
        EphRelation ephrelation = new EphRelation();
        int toppoint,bottlepoint;
        //如果轨迹是降轨
        if(ephtrack.getUpdown().equalsIgnoreCase("1")){
            toppoint = 0;
            bottlepoint = ephtrack.getSubPointlist().size() - 1;
        }//如果轨迹是升轨
        else if(ephtrack.getUpdown().equalsIgnoreCase("0")){
            toppoint = ephtrack.getSubPointlist().size() - 1;
            bottlepoint = 0;
        }else{

            throw new Exception("the ephtrack updown is error!");

        }

        //zhanghy20170418
        //为了判断夸逆子午线的特殊情况，需要将侧摆和观测区域的边界值为不同正负的情况特殊处理，需要修改ephtrack.getSubPointlist()的经度值，为了不改变ephtrack对象的状态，要把用来做判断的数值提取出来。
        double ephToppointRrLon = ephtrack.getSubPointlist().get(toppoint).getRrLon();
        double ephBottlepointLrLon = ephtrack.getSubPointlist().get(bottlepoint).getLrLon();
        double ephToppointRsLon = ephtrack.getSubPointlist().get(toppoint).getRsLon();
        double ephBottlepointLsLon = ephtrack.getSubPointlist().get(bottlepoint).getLsLon();
        double regionSWnodeLon = region.getSwNode().getLon();
        double regionNEnodeLon = region.getNeNode().getLon();
        double regionNWnodeLon = region.getNwNode().getLon();
        double regionSEnodeLon = region.getSeNode().getLon();

        if((!(ephToppointRrLon>=0&&regionNEnodeLon>=0))&&(!(ephToppointRrLon<0&&regionNEnodeLon<0))){
            ephToppointRrLon=regionNEnodeLon;
        }
        if((!(ephBottlepointLrLon>=0&&regionSWnodeLon>=0))&&(!(ephBottlepointLrLon<0&&regionSWnodeLon<0))){
            ephBottlepointLrLon=regionSWnodeLon;
        }

        if((!(ephToppointRsLon>=0&&regionNEnodeLon>=0))&&(!(ephToppointRsLon<0&&regionNEnodeLon<0))){
            ephToppointRsLon=regionNEnodeLon;
        }
        if((!(ephBottlepointLsLon>=0&&regionSWnodeLon>=0))&&(!(ephBottlepointLsLon<0&&regionSWnodeLon<0))){
            ephBottlepointLsLon=regionSWnodeLon;
        }


        //状态为侧摆包含观测区域
        if(ephToppointRrLon >= regionNEnodeLon &&
                ephBottlepointLrLon <= regionSWnodeLon){
            //ephrelation.setRollrelation("roll involved grid");
            //状态为幅宽包含网格
            if(ephToppointRsLon >= regionNEnodeLon &&
                    ephBottlepointLsLon <= regionSWnodeLon){
                ephrelation.setRollrelation("strip_involved_grid");
            }
            else{
                //状态为幅宽不包含网格
                ephrelation.setRollrelation("roll_involved_grid");
                //ephrelation.setStriprelation("strip didn't involve grid");
            }
        }
        //状态为网格包含侧摆
        else if(ephToppointRrLon <= regionNEnodeLon &&
                ephBottlepointLrLon >= regionSWnodeLon){

            ephrelation.setRollrelation("grid_involved_roll");
            //ephrelation.setStriprelation("grid involved strip");
        }
        //状态为网格只包含右侧摆
        else if(ephBottlepointLrLon <= regionSWnodeLon
                && ephToppointRrLon >= regionNWnodeLon
        ){
            ephrelation.setRollrelation("right_roll_involved");
        }
        //状态为网格只包含左侧摆
        else if(ephToppointRrLon >= regionNEnodeLon
                && ephBottlepointLrLon <= regionSEnodeLon
        ){
            ephrelation.setRollrelation("left_roll_involved");
        }
        else{
            ephrelation.setRollrelation("separate");
        }

        return ephrelation;
    }

    @Override
    public StripDTO formatStripInstance(Double aDouble) {
        StripDTO stripDTO = new StripDTO();
        stripDTO.setRollAngle(aDouble);
        return stripDTO;
    }
}