package com.base.track.thread;

import com.base.api.model.SatelliteAndInstanceRpcDTO;
import com.base.api.model.YxInfoBasisInstanceRpcDTO;
import com.base.api.model.YxInfoBasisSatelliteRpcDTO;

import com.base.api.client.PayloadRpcService;
import com.base.api.model.PayloadRpcDTO;
import com.base.api.model.request.PayloadRpcReqDTO;
import com.base.orbit.log.ServerNameEnum;
import com.base.orbit.utils.FileUtil;
import com.base.orbit.utils.TimeUtil;
import com.base.track.mapper.OrbitNumMapper;
import com.base.track.model.entity.OrbitNum;
import com.base.track.model.entity.SatellitePara;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.*;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
public class OrbitNumThread {

    @Resource
    OrbitNumMapper orbitNumMapper;
    @Resource
    PayloadRpcService yxInfoSatellitePayloadService;

    @Async("orbitNumExecutor")
    public void run(String filePath, SatelliteAndInstanceRpcDTO satelliteAndInstance, String startTime, String endTime) {
        try {
            String code = satelliteAndInstance.getYxInfoBasisSatelliteDTO().getSatelliteCode();
            log.info("卫星" + code + "开始圈号计算", ServerNameEnum.TRACK_SERVER);
            boolean isFileWrite = writeDependFile(filePath, startTime, endTime, satelliteAndInstance);
            if (isFileWrite) {
                //文件写入成功，开始执行exe文件
                runExeFile(filePath, satelliteAndInstance.getYxInfoBasisSatelliteDTO());
            } else {
                //文件写入失败
                log.error("卫星" + code + "写入圈号计算条件文件失败",ServerNameEnum.TRACK_SERVER);
            }
            log.info("卫星" + code + "结束圈号计算",ServerNameEnum.TRACK_SERVER);
        } catch (Exception e) {
            log.error(e.getMessage());
        }
    }

    private boolean writeDependFile(String filePath, String startTime, String endTime, SatelliteAndInstanceRpcDTO satelliteAndInstance) throws IOException {
        YxInfoBasisSatelliteRpcDTO infoBasisSatelliteDO = satelliteAndInstance.getYxInfoBasisSatelliteDTO();
        YxInfoBasisInstanceRpcDTO infoBasisInstanceDO = satelliteAndInstance.getYxInfoBasisInstanceDTO();
        StringBuilder sb = new StringBuilder();
        //卫星详细信息 卫星质量 迎风面 光面 地球重力场系数1 地球重力场系数2
        sb.append("1 ").append(infoBasisSatelliteDO.getSatelliteName()).append(" ").append(infoBasisSatelliteDO.getMass()).append(" ").append(infoBasisSatelliteDO.getWindArea()).append(" ").append(infoBasisSatelliteDO.getShineArea()).append(" ").append(infoBasisSatelliteDO.getEarthGravityFieldModeOrde1() != null ? infoBasisSatelliteDO.getEarthGravityFieldModeOrde1() : "32.0").append(" ").append(infoBasisSatelliteDO.getEarthGravityFieldModeOrde2() != null ? infoBasisSatelliteDO.getEarthGravityFieldModeOrde2() : "32.0").append("\n");
        //预报开始时间
        sb.append("2 ").append(startTime).append(" ").append(endTime).append(" 1.0\n");
        //地面站信息 地面站经度 地面站纬度 地面站高度 天线最小跟踪仰角（度）默认1度 天线最小接收仰角（度）默认1度 日凌角（度）默认1度
        sb.append("3 0 0 0 0 0 0\n");
        //星历类型
        sb.append("4 3\n");
        //星历文件目录
        sb.append("5 ").append(filePath + Thread.currentThread().getName().split("-")[2]).append("\n");
        //星历预报时间
        sb.append("6 ").append(startTime).append(" ").append(endTime).append(" 1.0 60.0\n");
        //星历轨道类型 输入轨道类型，输出轨道类型
        sb.append("7 1 1\n");
        //六根数对应的时间
        sb.append("8 ").append(infoBasisInstanceDO.getOrbitNum()).append(" ").append(TimeUtil.format(infoBasisInstanceDO.getEpochTime())).append(" ").append(TimeUtil.format(infoBasisInstanceDO.getEpochTime())).append("\n");
        //瞬根数据 半长轴（m） 偏心率 轨道倾角（度） 升交点赤经（度） 近地点俯角（度） 平近点角（度）
        sb.append("9 ").append(infoBasisInstanceDO.getSemiMajorAxis()).append(" ").append(infoBasisInstanceDO.getEccentricity()).append(" ").append(infoBasisInstanceDO.getInclination()).append(" ").append(infoBasisInstanceDO.getRaan()).append(" ").append(infoBasisInstanceDO.getArgumentOfPerigee()).append(" ").append(infoBasisInstanceDO.getMeanAnoMaly()).append("\n");
        //GPS数据
        sb.append("10 0 0 0 0 0 0\n");
        //两行数据
        sb.append("11 1 0 0 0 0 0 0 0 0\n");
        //两行数据
        sb.append("12 2 0 0 0 0 0 0 0 0");
        File file = new File(filePath + Thread.currentThread().getName().split("-")[2] + "/orbdata/orbnum.inp");
        boolean isDelete = true;
        if (file.exists()) {
            isDelete = file.delete();
        }
        if (isDelete) {
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true)));
            bufferedWriter.write(sb.toString());
            bufferedWriter.flush();
            bufferedWriter.close();
        } else {
            return false;
        }
        return true;
    }


    private void runExeFile(String filePath, YxInfoBasisSatelliteRpcDTO yxInfoBasisSatellite) throws Exception {
        //星下点的处理方法 根据ID获取卫星的数据和卫星的载荷
        SatellitePara satellitePara = findThisEphData(yxInfoBasisSatellite);
        if (satellitePara != null) {
            String port = Thread.currentThread().getName().split("-")[2];
            File oldFile = new File(filePath + port + "/orbdata/orbnum.dat");
            boolean isOldFileDelete = true;
            if (oldFile.exists()) {
                isOldFileDelete = oldFile.delete();
            }
            File okFile = new File(filePath + port + "/orbdata/orbnum.ok");
            boolean isOkFileDelete = true;
            if (okFile.exists()) {
                isOkFileDelete = okFile.delete();
            }
            if (isOldFileDelete && isOkFileDelete) {
                Process exec = Runtime.getRuntime().exec(filePath + port + "/bin/orbNum.exe", null, new File(filePath + port + "/bin/"));
                if (FileUtil.checkFileStatus(okFile, "卫星" + yxInfoBasisSatellite.getSatelliteCode() + "星下点计算", log)) {
                    DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS");
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
                    exec.destroy();
                    FileInputStream fileInputStream;
                    InputStreamReader inputStreamReader;
                    BufferedReader bufferedReader;
                    fileInputStream = new FileInputStream(oldFile);
                    inputStreamReader = new InputStreamReader(fileInputStream);
                    bufferedReader = new BufferedReader(inputStreamReader);
                    String result;
                    int line = 0;
                    while ((result = bufferedReader.readLine()) != null) {
                        if (line != 0 && line != 1) {
                            List<String> r = FileUtil.getLineArray(result);
                            String StartDateStr = r.get(0) + " " + r.get(1);
                            String EndDateStr = r.get(0) + " " + r.get(1);
                            LocalDateTime startTime = LocalDateTime.parse(StartDateStr, df);
                            LocalDateTime endTime = LocalDateTime.parse(EndDateStr, df);
                            OrbitNum orbitNum = new OrbitNum();
                            orbitNum.setId(UUID.randomUUID().toString());
                            orbitNum.setStartTime(startTime);
                            orbitNum.setEndTime(endTime);
                            orbitNum.setSatelliteId(yxInfoBasisSatellite.getId());
                            orbitNum.setNum(Integer.parseInt(r.get(5)));
                            orbitNum.setLastTime(r.get(4));
                            orbitNumMapper.insert(orbitNum);
                        }
                        line++;
                    }
                    fileInputStream.close();
                    inputStreamReader.close();
                    bufferedReader.close();
                }
            }
        }
    }

    private SatellitePara findThisEphData(YxInfoBasisSatelliteRpcDTO satelliteDO) {
        SatellitePara satellitePara = new SatellitePara();
        //寻找到了卫星ID
        //开始判断侧摆角
        String maxRollAngle = satelliteDO.getMaxRollAngle();
        String satelliteDOId = satelliteDO.getId();
        if (!maxRollAngle.equalsIgnoreCase("")) {
            satellitePara.setMaxrollangle(Float.parseFloat(maxRollAngle));
            PayloadRpcReqDTO rpcReqDTO=new PayloadRpcReqDTO();
            rpcReqDTO.setSatelliteIds(Lists.newArrayList(satelliteDOId));
            List<PayloadRpcDTO> payloadDOList = yxInfoSatellitePayloadService.getPayloadRpcDTOList(rpcReqDTO);
            if (payloadDOList != null) {
                float max_USUAL_BANDWIDTH = -1;
                float max_OVER_LAP = -1;
                for (PayloadRpcDTO payloadDO : payloadDOList) {
                    float tempSWATH_WIDTH = payloadDO.getSwathWidth().floatValue();
                    float temp_OVER_LAP = payloadDO.getOverLap().floatValue();
                    if (tempSWATH_WIDTH > max_USUAL_BANDWIDTH) {
                        max_USUAL_BANDWIDTH = tempSWATH_WIDTH;
                        max_OVER_LAP = temp_OVER_LAP;
                    }
                }
                satellitePara.setSWATH_WIDTH(max_USUAL_BANDWIDTH);
                satellitePara.setOVER_LAP(max_OVER_LAP);
            } else {
                return null;
            }
        } else {
            return null;
        }
        return satellitePara;
    }
}
