package com.base.plan.controller;

import com.alibaba.fastjson.JSONArray;
import com.base.api.client.FzTaskRpcService;
import com.base.api.client.InstanceRpcService;
import com.base.api.client.PayloadRpcService;
import com.base.api.client.SatelliteRpcService;
import com.base.api.model.FzTaskRpcDTO;
import com.base.api.model.InstanceRpcDTO;
import com.base.api.model.PayloadRpcDTO;
import com.base.api.model.PayloadWorkModeRpcDTO;
import com.base.api.model.request.FzTaskInfoRpcReqDTO;
import com.base.api.model.request.PayloadRpcReqDTO;
import com.base.core.StripExecuteInitialize;
import com.base.orbit.domain.AjaxResult;
import com.base.orbit.utils.DateUtils;
import com.base.orbit.web.Result;
import com.base.plan.model.dto.CapacityDTO;
import com.base.plan.model.dto.QuerySelectedStripUpdateDTO;
import com.base.plan.model.dto.StripReqDTO;
import com.base.plan.model.dto.request.AreOptimizationReqDTO;
import com.base.plan.model.dto.request.CapacityReqDTO;
import com.base.plan.model.dto.request.StripDTOListAddDTO;
import com.base.plan.model.dto.request.StripDTOListReqDTO;
import com.base.plan.service.ArcService;
import com.base.plan.service.EphTrackService;
import com.base.plan.service.RegionService;
import com.base.plan.service.StripService;
import com.base.plan.service.biz.StripBiz;
import com.base.task.core.taskUtils;
import com.base.task.model.input.SubEphInput;
import com.google.common.collect.Lists;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.io.*;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@RestController
@RequestMapping("/api/strip")
@Slf4j
@Api(value = "条带")
public class StripController {

    @Value("${exe.filePath}")
    private String filePath;

    @Value("${exe.exeFileName}")
    private String exeFileName;

    @Value("${exe.matFileName}")
    private String matFileName;

    @Value("${exe.batFile}")
    private String batFile;

    @Value("${exe.inputdataFileName}")
    private String inputdataFileName;

    @Resource
    FzTaskRpcService fzTaskRpcService;

    @Resource
    PayloadRpcService payloadRpcService;

    @Resource
    StripBiz stripBiz;

    @Resource
    StripService stripService;

    @Resource
    SatelliteRpcService satelliteService;

    @Resource
    ArcService arcService;

    @Resource
    RegionService regionService;

    @Resource
    EphTrackService ephTrackService;

    @Resource
    InstanceRpcService instanceService;

    @Resource
    StripExecuteInitialize stripExecuteInitialize;


    @ApiOperation(value = "条带查询", response = StripReqDTO.class)
    @PostMapping("/list")
    public Object selStripDTOList(@RequestBody StripDTOListReqDTO req) {
        return Result.success(stripService.selStripDTOList(req));
    }

    @ApiOperation(value = "条带计算")
    @PostMapping("/count")
    public Object countAndGetStripDTOList(@RequestBody List<StripDTOListAddDTO> req) {
        try {
            for (StripDTOListAddDTO stripDTOListAddDTO : req) {
                getPayloadIdByReqId(stripDTOListAddDTO);
            }
            return Result.success();

        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("exec NUAA_SmartX_VT.exe fail,msg is " + e.getMessage());
        }
    }


    @ApiOperation(value = "根据不同载荷进行条带计算")
    @PostMapping("/countStripDTOListByPayload")
    public Object countStripDTOListByPayload(@RequestBody StripDTOListAddDTO req) {
        try {
            FzTaskInfoRpcReqDTO fzTaskInfoRpcReqDTO = new FzTaskInfoRpcReqDTO();
            fzTaskInfoRpcReqDTO.setReqIds(req.getReqIds());
            List<FzTaskRpcDTO> fzTaskDTOList = fzTaskRpcService.getFzTaskDTOList(fzTaskInfoRpcReqDTO);
            if (!CollectionUtils.isEmpty(fzTaskDTOList)) {
                FzTaskRpcDTO fzTaskRpcDTO = fzTaskDTOList.get(0);
                if (!fzTaskRpcDTO.getFzTaskState().equals("0")){
                    return Result.error(201,"操作失败");
                }
            }
            stripService.stripExecute(req);
            return Result.success();
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("count strip by payload is error,msg is " + e.getMessage());
        }
    }


    public void getPayloadIdByReqId(StripDTOListAddDTO req) {
        //  根据需求id查询载荷类型
        FzTaskInfoRpcReqDTO fzTaskInfoRpcReqDTO = new FzTaskInfoRpcReqDTO();
        fzTaskInfoRpcReqDTO.setReqIds(Lists.newArrayList(req.getReqIds().get(0)));
        List<FzTaskRpcDTO> fzTaskInfos = fzTaskRpcService.getFzTaskDTOList(fzTaskInfoRpcReqDTO);
        fzTaskInfos.forEach(fzTaskInfo -> {
            List<PayloadRpcDTO> payloadInfos = null;
            if (CollectionUtils.isEmpty(fzTaskInfo.getPayloadIdList())) {
                payloadInfos = payloadRpcService.getAllList();
            } else {
                PayloadRpcReqDTO payloadRpcReqDTO = new PayloadRpcReqDTO();
                payloadRpcReqDTO.setPayloadIds(fzTaskInfo.getPayloadIdList());
                payloadInfos = payloadRpcService.getPayloadRpcDTOList(payloadRpcReqDTO);

            }
            payloadInfos.forEach(payloadInfo -> {
                        if (payloadInfo.getPayloadType().equals("SAR")) {
                            List<PayloadWorkModeRpcDTO> payloadWorkModeRpcDTOS = new ArrayList<>();
                            if (payloadInfo.getPayloadWorkModes() != null) {
                                payloadWorkModeRpcDTOS = JSONArray.parseArray(payloadInfo.getPayloadWorkModes(), PayloadWorkModeRpcDTO.class);
                            }
                            payloadInfo.setPayloadWorkModeRpcDTOS(payloadWorkModeRpcDTOS);

                            //写计算星历星下点的配置文件 生产mat文件
                            //轨道信息
                            List<String> satelliteCodes = new ArrayList<>();
                            satelliteCodes.add(payloadInfo.getSatelliteCode());
                            List<InstanceRpcDTO> listBySatelliteCodes = instanceService.getListBySatelliteCode(satelliteCodes);
                            try {
                                boolean isFileWrite = writeDependFile(listBySatelliteCodes, req);
                                if (isFileWrite) {
                                    //文件写入成功，开始执行exe文件
                                    if (getFileNameMat()) {
                                        Thread.sleep(6000);
                                        for (PayloadWorkModeRpcDTO payloadWorkModeRpcDTO : payloadWorkModeRpcDTOS) {
                                            req.setWorkMode(payloadWorkModeRpcDTO.getWorkMode());
                                            BigDecimal SwathWidthb = new BigDecimal(payloadWorkModeRpcDTO.getSwathWidth());
                                            req.setSwathWidth(SwathWidthb.toPlainString());
                                            req.setPayloadId(payloadInfo.getId());
                                            req.setSatelliteCode(payloadInfo.getSatelliteCode());
                                            req.setSatelliteId(payloadInfo.getSatelliteId());
                                            req.setTargetId(fzTaskInfo.getTargetCode());
                                            stripService.createSarInput(req);
                                        }
                                    }

                                } else {
                                    //文件写入失败
                                    log.error("写入星下点计算条件文件失败");
                                }

                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }
            );

        });
    }

    public boolean writeDependFile(List<InstanceRpcDTO> listBySatelliteCodes, StripDTOListAddDTO req) throws IOException {
        SubEphInput subEphInput = new SubEphInput();
        Date epochTime = listBySatelliteCodes.get(0).getEpochTime();
        String epochTimestr = DateUtils.DateToStringBypa(epochTime, DateUtils.DISPERSE);
        subEphInput.setEpotime(epochTimestr);

        String startTime = req.getStartTime();
        Date startTimed = DateUtils.StringToDate(startTime);
        String startTimestr = DateUtils.DateToStringBypa(startTimed, DateUtils.DISPERSE);
        subEphInput.setStarttime(startTimestr);

        String endTime = req.getEndTime();
        Date endTimed = DateUtils.StringToDate(endTime);
        String endTimestr = DateUtils.DateToStringBypa(endTimed, DateUtils.DISPERSE);
        subEphInput.setEndtime(endTimestr);

        BeanUtils.copyProperties(listBySatelliteCodes.get(0), subEphInput);
        String data = taskUtils.getTaskInputString(subEphInput.getClass(), subEphInput);

        File file = new File(filePath + inputdataFileName);
        boolean isDelete = true;
        if (file.exists()) {
            isDelete = file.delete();
        }
        if (isDelete) {
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file, true)));
            bufferedWriter.write(data);
            bufferedWriter.flush();
            bufferedWriter.close();
        } else {
            return false;
        }
        return true;

    }

    /**
     * 生成fileNameMat
     */
    public boolean getFileNameMat() throws IOException {
        boolean isCreateMatFile = false;
        // mat文件
        File matFile = new File(filePath + matFileName);
        // 初始数据
        boolean isMatFileDelete = true;
        // 文件是否存在
        if (matFile.exists()) {
            // 删除该文件
            isMatFileDelete = matFile.delete();
        }
        // 文件是否删除成功
        if (isMatFileDelete) {
            Process exec = Runtime.getRuntime().exec(filePath + batFile, null, new File(filePath));
            if (checkFileStatus(matFile)) {
                exec.destroy();
                isCreateMatFile = true;
            }
        }
        return isCreateMatFile;
    }

    /**
     * 判断文件是否更新超过时间之后就返回false
     *
     * @param matFile 是否写入成功文件
     * @return boolean
     */
    public static boolean checkFileStatus(File matFile) {
        boolean flag = false;
        boolean exists;
        do {
            exists = matFile.exists();
        } while (!exists);
        return true;
    }


    @PostMapping("/satellite/optimization/list")
    public Object getSatelliteStripDTOList(@RequestBody StripDTOListReqDTO req) {
//        return Result.success(stripService.getSatelliteStripDTOList(req));
        if (CollectionUtils.isEmpty(req.getReqIds())) {
            Result.error("需求id不能为空！");
        }
        return Result.success(stripService.getAreaOptimizaPlan(req));
    }

    @ApiOperation(value = "区域优选")
    @PostMapping("/optimization")
    public Object areaOptimization(@RequestBody AreOptimizationReqDTO req) {
        return Result.success(stripService.areaOptimization(req));
    }

    @ApiOperation(value = "任务规划结果上报")
    @PostMapping("/optimizationup")
    public Object areaOptimizationup(@RequestBody AreOptimizationReqDTO req) {
        return Result.success(stripService.areaOptimizationup(req));
    }

    @ApiOperation(value = "固存占用计算")
    @PostMapping("/capacity")
    @ApiResponses({
            @ApiResponse(code = 200, message = "OK", response = CapacityDTO.class)
    })
    public Object capacityCount(@RequestBody CapacityReqDTO req) {
        log.info("capacity count req param is " + req.toString());
        return Result.success(stripService.capacityCount(req));
    }

    @ApiOperation(value = "修改条带优先选中字段")
    @PostMapping("/post/selected")
    public AjaxResult batchSelectedStrip(@RequestBody List<QuerySelectedStripUpdateDTO> list){
        stripService.batchSelectedStrip(list);
        return AjaxResult.success();
    }


}