package com.shkj.wms.third.rcs;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.shkj.common.constant.RedisConstant;
import com.shkj.common.core.domain.Result;
import com.shkj.common.enums.HttpStatus;
import com.shkj.common.utils.DateUtils;
import com.shkj.common.utils.SecurityUtils;
import com.shkj.common.utils.StringUtils;
import com.shkj.plc.sdk.device.PLCReadAndWrite;
import com.shkj.plc.sdk.device.PlcOperate;
import com.shkj.system.service.ISysParameterService;
import com.shkj.wms.bo.*;
import com.shkj.wms.domain.*;
import com.shkj.wms.enums.TaskStatusEnum;
import com.shkj.wms.mapper.*;
import com.shkj.wms.plc.PlcInit;
import com.shkj.wms.service.*;
import com.shkj.wms.third.rcs.dto.RcsCancelTaskDto;
import com.shkj.wms.third.rcs.dto.RcsCreateTaskDto;
import com.shkj.wms.third.rcs.dto.RcsIdList;
import com.shkj.wms.third.rcs.dto.RcsThirdResult;
import com.shkj.wms.constants.ParameterConstants;
import com.shkj.wms.enums.TaskTypeEnum;
import com.shkj.wms.third.rcs.enums.RCSTaskTypeEnum;
import com.shkj.wms.utils.JsonUtil;
import com.shkj.wms.vo.BasePointDeviceVo;
import com.shkj.wms.vo.BusinDataTaskGoodsVo;
import com.shkj.wms.vo.BusinDataTaskVo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * AGV 接口文档
 *
 * @author zjx
 * @date 2023/04/08
 */
@Slf4j
@Component
public class RCSUtil {

    @Value("${third.agvCreateTaskUrl}")
    private String agvCreateTaskUrl;

    @Value("${third.agvCancelTaskUrl}")
    private String agvCancelTaskUrl;

    @Value("${third.agvStatesUrl}")
    private String agvStatesUrl;

    @Value("${third.queryAckByTaskUrl}")
    private String queryAckByTaskUrl;

    @Value("${third.deleteShelfUrl}")
    private String deleteShielfUrl;

    @Value("${third.updateTaskUrl}")
    private String updateTaskUrl;

    @Resource
    ISysParameterService sysParameterService;
    @Resource
    BasePointDeviceMapper basePointDeviceMapper;
    @Autowired
    IBusinEnptyContainerService iBusinEnptyContainerService;
    @Autowired
    IBusinDataTaskDetailService iBusinDataTaskDetailService;
    @Resource
    IBasePunchRecordService iBasePunchRecordService;

    @Resource
    BaseLocationPlcMapper baseLocationPlcMapper;

    @Resource
    BusinDataTaskMapper businDataTaskMapper;

    @Resource
    RedisTemplate redisTemplate;

    @Autowired
    IWcsPlcPropertyService iWcsPlcPropertyService;

    @Autowired
    PLCReadAndWrite plcReadAndWrite;

    @Autowired
    ISysParameterService isysParameterService;

    @Autowired
    IWcsPlcConnectService iWcsPlcConnectService;

    @Autowired
    IBusinDataTaskService iBusinDataTaskService;

    @Resource
    BusinPickupMapper businPickupMapper;

    @Autowired
    IBasePointService iBasePointService;

    @Resource
    BusinDpsContainerRecordMapper businDpsContainerRecordMapper;

    @Resource
    BusinDataTaskGoodsMapper businDataTaskGoodsMapper;
    @Resource
    IBusinPickupService iBusinPickupService;

    @Resource
    PlcInit plcInit;


    /**
     * 设置头部信息
     *
     * @return {@code Map<String, String>}
     */
    public Map<String, String> getHeaderMap() {
        Map<String, String> headerMap = new HashMap<>(1);
        headerMap.put("authorization", "mrbase64 mrrest:YWRtaW4mYWRtaW4=");
        return headerMap;
    }

    /**
     * 删除货架
     * wcs系统通过此接口向rcs系统下发删除货架指令
     *
     * @param map
     * @return {@code Result}
     */
    public Result openRun(Map map) {
        String json = JSONObject.toJSONString(map);
        try {
            Map<String, String> headerMap = getHeaderMap();
            String res = HttpRequest.post(deleteShielfUrl)
                    .addHeaders(headerMap)
                    .body(json)
                    .execute().body();
            Result result = parseThirdRcsResult(res);
//            log.error("删除货架:"+json.toString());
//            log.error(result.toString());
//            log.error(map.toString());
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("open删除货架 方法出错了 = {}", e.getMessage());
            return Result.err().msg(e.getMessage());
        }
    }

    public Result updateTask(Map map) {
        String json = JSONObject.toJSONString(map);
        try {
            Map<String, String> headerMap = getHeaderMap();
            String res = HttpRequest.post(updateTaskUrl)
                    .addHeaders(headerMap)
                    .body(json)
                    .execute().body();
            Result result = parseThirdRcsResult(res);
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("调整任务 方法出错了 = {}", e.getMessage());
            return Result.err().msg(e.getMessage());
        }
    }


    /**
     * 创建任务
     * wcs系统通过此接口向rcs系统下发创建任务指令
     *
     * @param dto dto
     * @return {@code Result}
     */
    public synchronized Result rcsCreateTask(RcsCreateTaskDto dto) {
        log.info("AGV下发任务信息：" + JsonUtil.toJSONString(dto));
        if (ObjectUtils.isNotEmpty(redisTemplate.opsForValue().get(RedisConstant.out17 + dto.getTaskId()))) {
            return Result.err().msg("此任务已经下发至rcs任务号：" + dto.getTaskId());
        }
        //获取任务详细信息,下发给RCS设置行号
        BusinDataTask businDataTask = iBusinDataTaskService.getById(dto.getTaskId());
        if (StringUtils.isNotEmpty(businDataTask.getToRow())) {
            dto.setStation(businDataTask.getToRow());
        }
        String json = JSONObject.toJSONString(dto);
        try {
            Map<String, String> headerMap = getHeaderMap();
            String res = HttpRequest.post(agvCreateTaskUrl)
                    .addHeaders(headerMap)
                    .body(json)
                    .execute().body();
            log.info(dto.getTaskId() + "AGV下发任务返回结果：" + res);
            Result result = parseThirdRcsResult(res);
            if (result.getCode() == 200) {
                redisTemplate.opsForValue().set(RedisConstant.out17 + dto.getTaskId(), result.toString());
            }
            return result;
        } catch (Exception e) {
            e.printStackTrace();
            log.error("createTask 方法出错了 = {}", e.getMessage());
            return Result.err().msg(e.getMessage());
        }
    }

    /**
     * 更改AGV点位信息
     */
    public Result removePoint(AGVUploadStatusBo bo) {
        log.info("AGV更新点位信息：" + JsonUtil.toJSONString(bo));
        BusinDataTask byId = iBusinDataTaskService.getById(bo.getTaskId());
        String sn = bo.getSn();
        if (ObjectUtils.isNotEmpty(byId)) {
            Map map = new HashMap();
            map.put("taskId", byId.getId());
            Result result = new Result();
            result.setCode(0);
            List list = new ArrayList();
            if (StringUtils.isEmpty(byId.getNewDestination())) {
                return Result.err();
            }
            if (!"1".equals(byId.getTaskStatus())) {
                return Result.err();
            }
            Map points = (Map) JSON.parse(byId.getPoints());
            int pointnumber = points.size();
            if (pointnumber > Integer.valueOf(sn)) {
                Map<Object, Object> mapSn = new HashMap<>();
                mapSn.put("sn", pointnumber);
                mapSn.put("id", byId.getNewDestination());
                mapSn.put("action", "singleMove");
                list.add(mapSn);
                return result.data(list);
            }
        }
        return null;
    }


    /**
     * 放行任务
     * wcs系统通过此接口向rcs系统下发放行任务指令
     *
     * @param dto dto
     * @return {@code Result}
     */
    public Result queryAck(RcsCreateTaskDto dto) {
        String json = JSONObject.toJSONString(dto);
        try {
            Map<String, String> headerMap = getHeaderMap();
            String res = HttpRequest.post(queryAckByTaskUrl)
                    .addHeaders(headerMap)
                    .body(json)
                    .execute().body();
            return parseThirdRcsResult(res);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("放行 方法出错了 = {}", e.getMessage());
            return Result.err().msg(e.getMessage());
        }
    }

    public Result parseThirdRcsResult(String res) {
        try {
            res = res.trim();
            RcsThirdResult thirdResult = JSONObject.parseObject(res, RcsThirdResult.class);
            if (thirdResult == null) {
                // 添加到异常中去
                return Result.err().msg(res);
            }
            if (!RcsThirdResult.isOk(thirdResult)) {
                return Result.err().msg(res);
            }
            return Result.ok();
        } catch (Exception e) {
            log.error("parseThirdRcsResult res = {} e = {}", res, e);
            return Result.err().msg(res);
        }
    }

    /**
     * 任务取消
     * 上游系统调⽤此接⼝，将已下发待处理的任务取消
     *
     * @param /rest/tasks/del
     * @return {@code Result}
     */
    public Result rcsTaskCancel(RcsCancelTaskDto dto) {
        String json = JSONObject.toJSONString(dto);

        try {
            Map<String, String> headerMap = getHeaderMap();
            String res = HttpRequest.post(agvCancelTaskUrl)
                    .addHeaders(headerMap)
                    .body(json)
                    .execute().body();

            return parseThirdRcsResult(res);
        } catch (Exception e) {
            e.printStackTrace();
            log.error("rcs taskCancel 方法出错了 = {}", e.getMessage());
            return Result.err().msg(e.getMessage());
        }
    }


    /**
     * AGV搬运
     *
     * @param bo
     * @return {@link Result}<{@link Boolean}>
     */
    public Result<Boolean> moveByAGV(AGVMoveBo bo) {
        RcsCreateTaskDto dto = new RcsCreateTaskDto();
        dto.setMapId(1);
        dto.setTaskType(bo.getTaskType());
        if (StringUtils.isNotEmpty(bo.getRobotId())) {
            dto.setRobotId(bo.getRobotId());
        }
        dto.setTaskId(bo.getTaskId().toString());
        //库位编号
        List<RcsIdList> idList = new ArrayList<>();
        List<String> points = bo.getPoints();
        for (String point : points) {
            RcsIdList rcsIdList = new RcsIdList();
            rcsIdList.setId(point);
            log.error(point);
            idList.add(rcsIdList);
        }
        dto.setTargets(idList);
        return rcsCreateTask(dto);
        // return Result.ok();
    }

    public Result<Boolean> moveByAGV(AGVMoveBo bo, String toRow) {
        RcsCreateTaskDto dto = new RcsCreateTaskDto();
        dto.setMapId(1);
        dto.setTaskType(bo.getTaskType());
        if (StringUtils.isNotEmpty(bo.getRobotId())) {
            dto.setRobotId(bo.getRobotId());
        }
        dto.setTaskId(bo.getTaskId().toString());
        //库位编号
        List<RcsIdList> idList = new ArrayList<>();
        List<String> points = bo.getPoints();
        for (int i = 0; i < points.size(); i++) {
            RcsIdList rcsIdList = new RcsIdList();
            rcsIdList.setId(points.get(i));
//            if((points.size()-1) == i){
//                rcsIdList.setPodAngle(angle);
//            }
            log.error(points.get(i));
            idList.add(rcsIdList);
        }
        dto.setTargets(idList);
        dto.setStation(toRow);
        return rcsCreateTask(dto);
        // return Result.ok();
    }


    public Result<Boolean> moveByAGVTmp(BusinTaskQueryBo bo) {
        //呼叫AGV
        String targetPoint = isysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.putin_point);
        String tmpPoint = isysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.putout_point_tmp);
        String startPoint = isysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.target_point);

        //根据关键字查询任务号及AGV编号
        BusinDataTaskVo vo = businDataTaskMapper.selectBusinDataTaskByKeys(bo);
        String agvNo = vo.getAgvNo();

        Long plcId = vo.getPlcId();
        String taskCode = "T_" + DateUtils.dateTimeNow();
        //创建任务
        BusinTaskAddBo businTaskAddBo = new BusinTaskAddBo();
        //ZJ100001
        businTaskAddBo.setContainerId(vo.getContainerId());
        businTaskAddBo.setPlcId(plcId);
        businTaskAddBo.setBatch(DateUtils.getDate());
        businTaskAddBo.setTaskType("0");
        businTaskAddBo.setTaskCode(taskCode);
        businTaskAddBo.setAgvNo(agvNo);

        Map<String, String> snPointMap = new HashMap<>(3);
        snPointMap.put("1", startPoint);
        snPointMap.put("2", tmpPoint);
        snPointMap.put("3", tmpPoint);
        snPointMap.put("4", targetPoint);

        //新增任务单据
        businTaskAddBo.setTaskStatus("1");
        businTaskAddBo.setPoints(JsonUtil.toJSONString(snPointMap));
        BusinDataTask businDataTask = BeanUtil.toBean(businTaskAddBo, BusinDataTask.class);
        iBusinDataTaskService.insertBusinDataTask(businDataTask);
        Long taskId = businDataTask.getId();
        RcsCreateTaskDto dto = new RcsCreateTaskDto();
        dto.setMapId(1);
        dto.setTaskType(25);
        dto.setTaskId(taskId.toString());
        dto.setRobotId(agvNo);
        //点位编号
        List<RcsIdList> idList = new ArrayList<>();
        RcsIdList startId = new RcsIdList();
        RcsIdList midId = new RcsIdList();
        RcsIdList midIdTwo = new RcsIdList();
        RcsIdList endId = new RcsIdList();

        startId.setId(startPoint);
        midId.setId(tmpPoint);
        midIdTwo.setId(tmpPoint);
        endId.setId(targetPoint);
        idList.add(startId);
        idList.add(midId);
        idList.add(midIdTwo);
        idList.add(endId);
        dto.setTargets(idList);
        return rcsCreateTask(dto);
    }

    /**
     * 获取AGV实时状态信息
     *
     * @param mapId bo
     * @return {@code Result}
     */
    public Result rcsRobotsStates(String mapId) {
//        String json = JSONObject.toJSONString(mapId);
        try {
            Map<String, String> headerMap = getHeaderMap();
            String res = HttpRequest.post(agvStatesUrl)
                    .addHeaders(headerMap)
                    .body(mapId)
                    .execute().body();
            //获取AGV状态信息 推送前端及存储数据库及存储redis
            res = res.trim();
            RcsThirdResult thirdResult = JSONObject.parseObject(res, RcsThirdResult.class);
            if (thirdResult.getCode() == 0) {
                return Result.ok().data(thirdResult.getData()).msg(thirdResult.getComment());
            } else {
                return Result.err().msg(thirdResult.getComment());
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("rcsRobotsStates 方法出错了 = {}", e.getMessage());
            return Result.err().msg(e.getMessage());
        }
    }


    /**
     * AGV上报任务每一步状态    已弃用
     *
     * @param bo bo
     * @return {@code Result}
     */
    public Result<AGVStatesBo> uploadAgvTaskStatus(AGVUploadStatusBo bo) {

        //此任务是否是紧急任务，如果是则查询明细，存入redis中
        checkEmergencyOutbound(Long.valueOf(bo.getTaskId()));
        Long plcId = (Long) redisTemplate.opsForValue().get(RedisConstant.redistaskPlc + bo.getTaskId().toString());

        //根据plcId获取plc信息
        WcsPlcConnect wcsplc = (WcsPlcConnect) redisTemplate.opsForValue().get(RedisConstant.redisPlcConnect + plcId);

        List<WcsPlcProperty> propertyList = iWcsPlcPropertyService.getWcsPlcPropertyByPlcId(plcId);
        String writeTaskId = "";
        String valueType = "";
        for (WcsPlcProperty wcsPlcProperty : propertyList) {
            //AGV取走完成
            if (wcsPlcProperty.getPointType().equals("7")) {
                writeTaskId = wcsPlcProperty.getAddress();
                valueType = wcsPlcProperty.getValueType();
            }
        }

        Map<String, String> writeMap = new HashMap<>(1);
        writeMap.put(valueType, "true");
        Map<String, Object> allMap = new HashMap<>(1);
        allMap.put(writeTaskId, writeMap);

        Map<String, String> readMap = new HashMap<>(1);
        readMap.put(writeTaskId, valueType);

        PlcOperate plcOperate = plcInit.getPlcOperateByIp(wcsplc.getPlcIp());
        //回填plc状态
        PLCReadAndWrite plcReadAndWrite = new PLCReadAndWrite();
        //首先读取任务编号，同目前返回的任务编号是否一致，如果一致则回填状态；
        Map<String, Object> stringObjectMap = plcReadAndWrite.readPlcData(plcOperate, JSONObject.toJSONString(readMap));
        //if(stringObjectMap.get(writeTaskId).equals(bo.getTaskId())){
        plcReadAndWrite.execWrite(plcOperate, JSONObject.toJSONString(allMap));
        //}
        return Result.ok();
    }

    /**
     * 根据任务ID检查是否紧急出库
     *
     * @param taskId
     */
    public void checkEmergencyOutbound(Long taskId) {
        List<BusinDataTaskGoodsVo> businDataTaskGoodsVos = null;
        BusinDataTask businDataTask = businDataTaskMapper.selectById(taskId);
        if (businDataTask != null) {
            String taskType = businDataTask.getTaskType();
            //是否是紧急出库
            if (taskType.equals(TaskTypeEnum.urgent_out.getValue())) {
                //查询物料明细
                businDataTaskGoodsVos = businDataTaskGoodsMapper.getTaskGoodsByTaskCodeForOut(taskId);
            }
        }
        redisTemplate.opsForValue().set(RedisConstant.redisEmergencyOutbound, businDataTaskGoodsVos);
    }


    /**
     * AGV上报任务每一步状态
     *
     * @param
     * @return {@code Result}
     */
    public Result uploadAgvTaskStatusTmp(AGVUploadStatusBo bo) {
        log.info("AGV上报信息：" + JsonUtil.toJSONString(bo));
        Long taskID = null;
        String[] idArr = bo.getTaskId().split("_");
        if (idArr.length > 1) {
            taskID = Long.valueOf(idArr[0]);
        } else {
            taskID = Long.valueOf(bo.getTaskId());
        }
        BusinDataTask businDataTask = businDataTaskMapper.selectById(taskID);
        if (businDataTask == null) {
            return Result.err().msg("当前任务号未找到任务信息：" + taskID);
        }

        String taskType = businDataTask.getTaskType();
        //log.info("AGV上报数据查询到的任务信息：" + JsonUtil.toJSONString(businDataTask));
        String tunnl = null;
        tunnl = businDataTask.getTunnel();
        Long plcId = businDataTask.getPlcId();
        Long DPSplcId = businDataTask.getDpsNoOne();
        if (StringUtils.isNotEmpty(tunnl) && (plcId == null || !bo.getSn().equals("2")) && !"15".equals(taskType)) {
            plcId = DPSplcId;
        }
        if ("15".equals(taskType)) {
            if (bo.getSn().equals("2")) {
                plcId = 39L;
            }
        }
        if ("1".equals(taskType)) {
            if (2 < Integer.parseInt(bo.getSn())) {
                plcId = 39L;
            }
        }
        String points = businDataTask.getPoints();
        Map<String, String> agvMap = new HashMap<>();
        if (StringUtils.isNotEmpty(points)) {
            agvMap = JsonUtil.JsonStrToMap(points);
        }
        log.info("AGV的点位信息：" + agvMap.toString());


        WcsPlcConnect conn = iWcsPlcConnectService.selectWcsPlcConnectById(plcId);
        String readAddress = "";
        String readValueType = "";
        String agvPoint = "";

        String putAddress = "";
        String putAddressVtype = "";
        String putAgvPoint = "";


        String TaskAddress = "";
        String TaskddressVtype = "";
        String TaskPoint = "";

        String overAddress = "";
        String overValueType = "";
        String overputAgvPoint = "";

        String waringWaitpoint = "";
        String waringWaitpointType = "";

        Result result = new Result();
        result.setCode(200);
        result.setResult(true);

        //空治具回库
        if (taskType.equals(TaskTypeEnum.emptyCon.getValue())) {
            BusinDataTask fontbusinDataTask = businDataTaskMapper.selectfrontById(businDataTask);
            if (ObjectUtils.isNotEmpty(fontbusinDataTask)) {
                QueryWrapper<BusinPickup> pickupQueryWrapper = new QueryWrapper<>();
                pickupQueryWrapper.select("container_id", "point_no").eq("task_code", fontbusinDataTask.getTaskCode());
                List<BusinPickup> businPickupList = businPickupMapper.selectList(pickupQueryWrapper);
                if (businPickupList.size() > 0) {
                    BusinPickup businPickup = businPickupList.get(0);
                    log.info("空治具回库时，释放码头点位信息：" + JsonUtil.toJSONString(businPickup));
                    BasePoint basePoint = iBasePointService.selectBasePointById(Long.valueOf(businPickup.getPointNo()));
                    basePoint.setIsActive("1");
                    basePoint.setIsOccupy("0");
                    iBasePointService.updateById(basePoint);
                }
            }
        }

        List<WcsPlcProperty> propertyList = iWcsPlcPropertyService.getWcsPlcPropertyByPlcId(plcId);
        for (WcsPlcProperty wcsPlcProperty : propertyList) {
            /**
             * 只针对机械手输送线和立库输送线
             */
            if (wcsPlcProperty.getPointType().equals("8")) {
                if (StringUtils.isNotEmpty(tunnl) && (wcsPlcProperty.getTunnel()).equals(tunnl)) {
                    //放料完成点位
                    putAddress = wcsPlcProperty.getAddress();
                    putAddressVtype = wcsPlcProperty.getValueType();
                    agvPoint = wcsPlcProperty.getRelPoint();
                } else if (StringUtils.isEmpty(tunnl)) {
                    //放料完成点位
                    putAddress = wcsPlcProperty.getAddress();
                    putAddressVtype = wcsPlcProperty.getValueType();
                    agvPoint = wcsPlcProperty.getRelPoint();
                } else if (taskType.equals("15")) {
                    putAddress = wcsPlcProperty.getAddress();
                    putAddressVtype = wcsPlcProperty.getValueType();
                    agvPoint = wcsPlcProperty.getRelPoint();
                }

            } else if (wcsPlcProperty.getPointType().equals("1")) {
                if (StringUtils.isNotEmpty(tunnl) && (wcsPlcProperty.getTunnel()).equals(tunnl)) {
                    //点位类型=1，是否允许放料
                    readAddress = wcsPlcProperty.getAddress();
                    readValueType = wcsPlcProperty.getValueType();
                    putAgvPoint = wcsPlcProperty.getRelPoint();
                } else if (StringUtils.isEmpty(tunnl)) {
                    //点位类型=1，是否允许放料
                    readAddress = wcsPlcProperty.getAddress();
                    readValueType = wcsPlcProperty.getValueType();
                    putAgvPoint = wcsPlcProperty.getRelPoint();
                }

            } else if (wcsPlcProperty.getPointType().equals("6") && StringUtils.isNotEmpty(tunnl) && (wcsPlcProperty.getTunnel()).equals(tunnl)) {
                //请求入库
                //只针对立库输送线
                TaskAddress = wcsPlcProperty.getAddress();
                TaskddressVtype = wcsPlcProperty.getValueType();
                TaskPoint = wcsPlcProperty.getRelPoint();
            } else if (wcsPlcProperty.getPointType().equals("7")) {
                if (StringUtils.isNotEmpty(tunnl) && (wcsPlcProperty.getTunnel()).equals(tunnl) || wcsPlcProperty.getTunnel().equals("0")) {
                    //点位类型=7，取料完成
                    overAddress = wcsPlcProperty.getAddress();
                    overValueType = wcsPlcProperty.getValueType();
                    overputAgvPoint = wcsPlcProperty.getRelPoint();
                } else if (StringUtils.isEmpty(tunnl)) {
                    //点位类型=7，取料完成
                    overAddress = wcsPlcProperty.getAddress();
                    overValueType = wcsPlcProperty.getValueType();
                    overputAgvPoint = wcsPlcProperty.getRelPoint();
                }
            } else if (wcsPlcProperty.getPointType().equals("wait")) {
                waringWaitpoint = wcsPlcProperty.getAddress();
                waringWaitpointType = wcsPlcProperty.getValueType();
            }
        }


        //更新任务数据
        List<String> collect = agvMap.entrySet().stream().sorted(Map.Entry.comparingByKey()).map(e -> e.getKey()).collect(Collectors.toList());

        businDataTask.setAgvNo(bo.getRobotId());
        businDataTask.setUpdateTime(DateUtils.getNowDate());
        businDataTaskMapper.updateById(businDataTask);

        //新增AGV明细数据
        BusinDataTaskDatailAddBo bdtdBo = new BusinDataTaskDatailAddBo();
        bdtdBo.setTaskCode(Long.valueOf(taskID));
        bdtdBo.setRobotId(bo.getRobotId());
        bdtdBo.setIsState(bo.getStatus());
        bdtdBo.setExecDev("AGV");
        bdtdBo.setSn(bo.getSn());
        iBusinDataTaskDetailService.insertBusinTaskDetail(BeanUtil.toBean(bdtdBo, BusinDataTaskDetail.class));

        String taskAgvpoint = null;
        taskAgvpoint = agvMap.get(bo.getSn());
        if (ObjectUtils.isNotEmpty(conn)) {
            PlcOperate plcOperate = plcInit.getPlcOperateByIp(conn.getPlcIp());

            Map allWriteMap = new HashMap(2);

            Map overWriteMap = new HashMap(2);
            log.info("overputAgvPoint:" + overputAgvPoint);
            //写入agv取货完成
            if (StringUtils.isNotEmpty(overputAgvPoint)) {
                if (bo.getStatus().equals("completed") && overputAgvPoint.equals(taskAgvpoint)) {

                    Map writeMap = new HashMap(1);
                    writeMap.put(overValueType, "true");
                    overWriteMap.put(overAddress, writeMap);
                    Boolean over = plcReadAndWrite.execWrite(plcOperate, JSON.toJSONString(overWriteMap));
                    int i = 0;
                    while (!over && i < 50) {
                        over = plcReadAndWrite.execWrite(plcOperate, JSON.toJSONString(overWriteMap));
                        i++;
                    }
                    log.info("是否取货完成" + over + "    取货完成点位:" + overputAgvPoint + "   任务号:" + bo.getTaskId() + "    写入次数:" + i + "   写入点位:" + overAddress);

                    if (businDataTask.getTaskPath().equals(ParameterConstants.ParameterSystem.assemble_point_before)
                            || businDataTask.getTaskPath().equals(ParameterConstants.ParameterSystem.assemble_point_after)) {
                        int temp = 0;
                        String assemblePointType = RedisConstant.assemblePointBeforeTaskCount;
                        //小组装等待点位为一个，设置等待数也只需要一个
                        if (businDataTask.getTaskPath().equals(ParameterConstants.ParameterSystem.assemble_point_after)) {
                            assemblePointType = RedisConstant.assemblePointAfterTaskCount;
                        }
                        if (ObjectUtils.isEmpty(redisTemplate.opsForValue().get(assemblePointType))) {
                            redisTemplate.opsForValue().set(assemblePointType, 1);
                        } else {
                            temp = Integer.parseInt(redisTemplate.opsForValue().get(assemblePointType).toString());
                            if (temp < 3) {
                                redisTemplate.opsForValue().set(assemblePointType, ++temp);
                            }
                        }
                        log.info("添加小组装等待数完成！点位：" + assemblePointType + "数量为：" + temp);
                    }
                }
            }
            //到达紧急出库点位时调用checkEmergencyOutbound方法
            String tepairGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.urgency_out_point);
            BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();
            String outPoint = "";

            pointQueryBo.setGroupNo(tepairGroup);
            BasePointDeviceVo pointDeviceout = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBo);
            if (pointDeviceout == null) {
                log.info("请维护紧急出库接驳点");
            }
            outPoint = pointDeviceout.getPointNo();
            if (bo.getStatus().equals("completed") && outPoint.equals(taskAgvpoint)) {
                checkEmergencyOutbound(Long.valueOf(bo.getTaskId()));
            }

            //放置治具完成状态，回填AGV放置治具完成状态
            log.info("agvPoint:" + agvPoint);
            log.info("taskAgvPoint:" + taskAgvpoint);
            if (bo.getStatus().equals("completed") && agvPoint.equals(taskAgvpoint)) {
                Map writeMap = new HashMap(1);
                writeMap.put(putAddressVtype, "true");
                /**
                 * A-->b-->c场景不适用写入
                 */
                allWriteMap.put(putAddress, writeMap);
                if (tunnl != "" && tunnl != null && !taskType.equals("15")) {
                    Map taskidMap = new HashMap(1);
                    Map TaskwriteMap = new HashMap(1);
                    TaskwriteMap.put(TaskddressVtype, bo.getTaskId());
                    taskidMap.put(TaskAddress, TaskwriteMap);
                    Boolean aBoolean = plcReadAndWrite.execWrite(plcOperate, JSON.toJSONString(taskidMap));
                    int i = 0;
                    while (!aBoolean && i < 50) {
                        aBoolean = plcReadAndWrite.execWrite(plcOperate, JSON.toJSONString(taskidMap));
                        i++;
                    }
                    log.info("写入放货完成任务号是否成功:" + aBoolean + "   任务号:" + bo.getTaskId() + "   写入次数:" + i + "    写入内容:" + TaskAddress);
                }
                Boolean aBoolean = plcReadAndWrite.execWrite(plcOperate, JSON.toJSONString(allWriteMap));
                int i = 0;
                while (!aBoolean && i < 50) {
                    aBoolean = plcReadAndWrite.execWrite(plcOperate, JSON.toJSONString(allWriteMap));
                    i++;
                }
                log.info("写入放货完成是否成功:" + aBoolean + "   任务号:" + bo.getTaskId() + "   写入次数:" + i + "   写入的点位:" + putAddress);

                if (TaskTypeEnum.mechainical.getValue().equals(taskType) || TaskTypeEnum.emptyContainer_out.getValue().equals(taskType)) {
                    BusinDpscontainerRecord oneByTask = businDpsContainerRecordMapper.selectByTaskid(String.valueOf(businDataTask.getId()));
                    oneByTask.setIsState("3");
                    businDpsContainerRecordMapper.updateById(oneByTask);

                }
                if (TaskTypeEnum.emptyCon.getValue().equals(taskType) ||
                        TaskTypeEnum.mechainical.getValue().equals(taskType)
                        || TaskTypeEnum.emptyContainer_out.getValue().equals(taskType)) {
                    //更改任务状态为已完成
                    businDataTask.setTaskStatus("2");
                    businDataTaskMapper.updateById(businDataTask);
//                    if (TaskTypeEnum.emptyCon.getValue().equals(businDataTask.getTaskType())) {
//                        //删除对应点位的货架
//                        Map map = new HashMap();
//                        map.put("posId", businDataTask.getTaskPath());
//                        openRun(map);
//                    }
                }
                WcsPlcConnect conn1 = iWcsPlcConnectService.selectWcsPlcConnectById(39L);
                Map write1 = new HashMap(1);
                Map<String, Object> allHbMap = new HashMap<>(1);
//                4#入口  DB320.2.8
//                5#入口  DB320.2.10
//                6#入口  DB320.2.12
                if ("KW5".equals(businDataTask.getTaskPath())) {
                    write1.put("Boolean", "true");
                    allHbMap.put("DB320.2.2", write1);
                }
                if ("KW7".equals(businDataTask.getTaskPath())) {
                    write1.put("Boolean", "true");
                    allHbMap.put("DB320.2.4", write1);
                }
                if ("KW9".equals(businDataTask.getTaskPath())) {
                    write1.put("Boolean", "true");
                    allHbMap.put("DB320.2.5", write1);
                }
                if ("KW22".equals(businDataTask.getTaskPath())) {
                    write1.put("Boolean", "true");
                    allHbMap.put("DB320.2.8", write1);
                }
                if ("KW24".equals(businDataTask.getTaskPath())) {
                    write1.put("Boolean", "true");
                    allHbMap.put("DB320.2.10", write1);
                }
                if ("KW26".equals(businDataTask.getTaskPath())) {
                    write1.put("Boolean", "true");
                    allHbMap.put("DB320.2.12", write1);
                }
                String writePoint = JSON.toJSONString(allHbMap);
                PlcOperate plcOperateWrite = plcInit.getPlcOperateByIp(conn1.getPlcIp());
                Boolean execWrite = plcReadAndWrite.execWrite(plcOperateWrite, writePoint);
                if (execWrite) {
                    log.info("++++++++++++" + businDataTask.getTaskPath() + "打开安全光电成功");
                }

                return Result.ok();
            }
            //对到达出库点的任务进行处理(使用按钮盒时使用)
//        if (TaskTypeEnum.normal_out.getValue().equals(businDataTask.getTaskType())) {
//            //根据agv完成状态和对应点位判断是否是到达出库点
//            if (bo.getStatus().equals("completed")&&bo.getSn().equals(String.valueOf(collect.size()))) {
//                //更改任务状态
//                businDataTask.setTaskStatus("2");
//                businDataTaskMapper.updateById(businDataTask);
//            }
//        }
//            bo.getSn();
//            Map<String,String> agvsn=(Map<String, String>) JSON.parse(businDataTask.getPoints());
//            List<String> collectagvsn = agvsn.entrySet().stream().sorted(Map.Entry.comparingByKey()).map(e -> e.getKey()).collect(Collectors.toList());
//            String s = collectagvsn.get(collectagvsn.size() - 2);

            // TODO 组装线等待点位————备用
            //
//        //到达组装线等待上报点进行的业务处理
//        String reportPointGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.report_point);
//        BasePointDeviceQueryBo pointReportQueryBo = new BasePointDeviceQueryBo();
//        String reportPoint ="";
//
//        pointReportQueryBo.setGroupNo(reportPointGroup);
//        BasePointDeviceVo reportPointDeviceOut = basePointDeviceMapper.selectBasePointByGroupno(pointReportQueryBo);
//        if(ObjectUtils.isEmpty(reportPointDeviceOut)){
//            log.error("请维护组装线上报点");
//        }
//        reportPoint=reportPointDeviceOut.getPointNo();
//        if (bo.getStatus().equals("completed") && reportPoint.equals(taskAgvpoint)) {
//            // 处理是否是直接调用接口跳过等待点
//            // 如无法跳过：则添加数据用于给AGV下发出库任务时判断使用。
//            // 还要修改点位管理中的等待点为占用String taskAgvpoint = agvMap.get(bo.getSn());
//            // 如可以跳过（判断等待位是否与其是同一套保险杠），直接调用AGV提供的接口 “调整任务” 并且需要放行在等待点位中的agv
//            // 还要取消占用等待点位,删除 base_wait 中对应的数据
//
//            // 获取等待点集合
//            String waitPointsGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.m_points);
//            pointReportQueryBo = new BasePointDeviceQueryBo();
//            pointReportQueryBo.setGroupNo(waitPointsGroup);
//            List<BasePointDeviceVo> waitPointsDeviceOut = basePointDeviceMapper.getBasePointByGroupNoList(pointReportQueryBo);
//
//            // 获取等待点位数据是否有小车在等待
//            List<Map<String ,String>> waitPointListMap = (List<Map<String, String>>) redisTemplate.opsForValue().get("W_POINT_LIST_MAP");
//
//            // 是否要进等待位
//            boolean yesOrNo = true;
//
//            // 判断等待点位是否有小车在等待；如果没有就直接跳过，让小车等待并记录到redis中
//            if(ObjectUtils.isNotEmpty(waitPointListMap)){
//                // 当前在上报点的任务相关联的任务ID
//                String associatedTaskId = businDataTask.getAssociatedTasksId();
//                // 循环等待点上的小车、任务信息进行判断
//                for (int i = 0; i < waitPointListMap.size(); i++) {
//                    // 判断当前任务和等待点的任务是否一起放行
//                   if(waitPointListMap.get(i).get("taskId").equals(associatedTaskId)){
//                       // 调整AGV任务（跳过等待点位）
//                       Map totalWaitMap = new HashMap();
//                       List<Map> waitMapList = new ArrayList<>();
//                       Map waitMap = new HashMap();
//
//                       totalWaitMap.put("taskId",associatedTaskId);
//                       waitMap.put("sn",bo.getSn());
//                       waitMap.put("id",agvMap.get(agvMap.size()-1));
//                       waitMapList.add(waitMap);
//                       totalWaitMap.put("targets",waitMapList);
//                       Result resultContinue = this.updateTask(totalWaitMap);
//
//                       System.out.println(HttpStatus.SUCCESS == resultContinue.getCode() ? "========= 成功！在上报点位跳过等待点位" : "失败！在上报点位跳过等待点位");
//
//                       RcsCreateTaskDto dto = new RcsCreateTaskDto();
//                       dto.setTaskId(waitPointListMap.get(i).get("taskId"));
//                        // 获取当前等待位置的信息
//                       BasePoint basePointOne = iBasePointService.getOne(new LambdaQueryWrapper<BasePoint>()
//                               .eq(BasePoint::getPointNo,waitPointListMap.get(i).get("pointNo")));
//                       // 放行逻辑
//                       Result resultGo = this.queryAck(dto);
//
//                       System.out.println(HttpStatus.SUCCESS == resultGo.getCode() ? "========= 成功！放行等待点位" : "失败！放行等待点位");
//
//                       // 修改当前等待位置为可用
//                       basePointOne.setIsOccupy("0");
//                       iBasePointService.updateBasePoint(basePointOne);
//
//                       //将放行的等待位在redis中清除
//                       waitPointListMap.remove(i);
//                       redisTemplate.opsForValue().set("W_POINT_LIST_MAP",waitPointListMap);
//                       yesOrNo = false;
//                       break;
//                   }
//                }
//                if(yesOrNo){
//                    String waitPointStr = agvMap.get(4);
//                    List<Map<String,String>> maps=new ArrayList<>();
//                    Map<String,String> map= new HashMap();
//                    map.put("pointNo",waitPointStr);
//                    map.put("createTime",DateUtils.getTime());
//                    map.put("agvNo",bo.getRobotId());
//                    map.put("taskId",bo.getTaskId().toString());
//                    map.put("sort",waitPointStr.substring(waitPointStr.length()-1));
//                    maps.add(map);
//
//                    // 修改当前等待位置为占用
//                    BasePoint basePointOne = iBasePointService.getOne(new LambdaQueryWrapper<BasePoint>()
//                            .eq(BasePoint::getPointNo,waitPointStr));
//                    basePointOne.setIsOccupy("1");
//                    iBasePointService.updateBasePoint(basePointOne);
//                }
//            }
//            else{
//                // 获取数据并添加到redis中的等待信息
//                List<Map<String,String>> maps=new ArrayList<>();
//                Map<String,String> map= new HashMap();
//                map.put("pointNo",waitPointsDeviceOut.get(0).getPointNo());
//                map.put("createTime",DateUtils.getTime());
//                map.put("agvNo",bo.getRobotId());
//                map.put("taskId",bo.getTaskId().toString());
//                map.put("sort","1");
//                maps.add(map);
//                redisTemplate.opsForValue().set("W_POINT_LIST_MAP",maps);
//
//                // 修改当前等待位置为占用
//                BasePoint basePointOne = iBasePointService.getOne(new LambdaQueryWrapper<BasePoint>()
//                .eq(BasePoint::getPointNo,waitPointsDeviceOut.get(0).getPointNo()));
//                basePointOne.setIsOccupy("1");
//                iBasePointService.updateBasePoint(basePointOne);
//            }
//        }
        }

        //TODO 测试注释   要打开

//        //到达组装线等待上报点进行的业务处理
//        String reportPointGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.report_point);
//        BasePointDeviceQueryBo pointReportQueryBo = new BasePointDeviceQueryBo();
//        String reportPoint ="";
//
//        pointReportQueryBo.setGroupNo(reportPointGroup);
//        BasePointDeviceVo reportPointDeviceOut = basePointDeviceMapper.selectBasePointByGroupno(pointReportQueryBo);
//        if(ObjectUtils.isEmpty(reportPointDeviceOut)){
//            log.error("请维护组装线上报点");
//        }
//        reportPoint=reportPointDeviceOut.getPointNo();
//        // 到达组装线上报点之后的业务逻辑处理
//        if (bo.getStatus().equals("completed") && reportPoint.equals(taskAgvpoint)) {
//            // TODO 测试注释  要打开   这下面是要添加任务数
//            String assemblePointType = RedisConstant.assemblePointBeforeTaskCount;
//            if(businDataTask.getTaskPath().equals(ParameterConstants.ParameterSystem.assemble_point_after)){
//                assemblePointType = RedisConstant.assemblePointAfterTaskCount;
//            }
//            if (ObjectUtils.isEmpty(redisTemplate.opsForValue().get(assemblePointType))) {
//                redisTemplate.opsForValue().set(assemblePointType, 1);
//            }else{
//                int temp = Integer.parseInt(redisTemplate.opsForValue().get(assemblePointType).toString());
//                redisTemplate.opsForValue().set(assemblePointType, ++temp);
//            }
//        }


        String assemblePointGroupBefore = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.Manual_drop_point);
        BasePointDeviceQueryBo pointReportQueryBoBefore = new BasePointDeviceQueryBo();
        String assemblePointBefore = "";
        String assemblePointAfter = "";

        pointReportQueryBoBefore.setGroupNo(assemblePointGroupBefore);
        List<BasePointDeviceVo> assemblePointDeviceOutBefore = basePointDeviceMapper.getBasePointByGroupNoList(pointReportQueryBoBefore);
        if (ObjectUtils.isEmpty(assemblePointDeviceOutBefore)) {
            log.info("请维护组装线点位");
        }
        for (BasePointDeviceVo str : assemblePointDeviceOutBefore) {
            if (str.getPointNo().equals(ParameterConstants.ParameterSystem.assemble_point_after)) {
                assemblePointAfter = ParameterConstants.ParameterSystem.assemble_point_after;
            }

            if (str.getPointNo().equals(ParameterConstants.ParameterSystem.assemble_point_before)) {
                assemblePointBefore = ParameterConstants.ParameterSystem.assemble_point_before;
            }
        }

        // 到达组装线前杠点位之后的业务逻辑处理
        if (bo.getStatus().equals("completed") && assemblePointBefore.equals(taskAgvpoint)
                && businDataTask.getTaskPath().equals(assemblePointBefore)
                && assemblePointBefore.equals(ParameterConstants.ParameterSystem.assemble_point_before)) {
            // TODO 测试注释  要打开
            AssemblyLineAddBo assemblyLineAddBo = new AssemblyLineAddBo();

            assemblyLineAddBo.setTaskId(businDataTask.getId());
            assemblyLineAddBo.setAgvNo(businDataTask.getAgvNo());
            assemblyLineAddBo.setTaskType(taskType);
            assemblyLineAddBo.setContainerId(businDataTask.getContainerId());
            assemblyLineAddBo.setPointNo(assemblePointBefore);

            redisTemplate.opsForValue().set(RedisConstant.redisAssemblyLineFront, assemblyLineAddBo);

//            // TODO 中科  测试 需要还原
////            redisTemplate.opsForValue().set(RedisConstant.redisAssemblyLineFront, assemblyLineAddBo);
//
//            // TODO 中科  测试 需要删除
//            new Thread(() -> {
//                redisTemplate.opsForValue().set(RedisConstant.redisAssemblyLineFront, assemblyLineAddBo);
//            }).start();
//            try {
//                Thread.sleep(2000);
//            } catch (InterruptedException e) {
//                e.printStackTrace();
//            }
//            iBusinPickupService.savePickupRecordByAssemblyLine("front");
//            // TODO 中科  测试 需要删除
        }

        // 到达组装线前杠点位之后的业务逻辑处理
        if (bo.getStatus().equals("completed") && assemblePointAfter.equals(taskAgvpoint) && businDataTask.getTaskPath().equals(assemblePointAfter) && assemblePointAfter.equals(ParameterConstants.ParameterSystem.assemble_point_after)) {
            // TODO 测试注释  要打开
            AssemblyLineAddBo assemblyLineAddBo = new AssemblyLineAddBo();

            assemblyLineAddBo.setTaskId(businDataTask.getId());
            assemblyLineAddBo.setAgvNo(businDataTask.getAgvNo());
            assemblyLineAddBo.setTaskType(taskType);
            assemblyLineAddBo.setContainerId(businDataTask.getContainerId());
            assemblyLineAddBo.setPointNo(assemblePointAfter);

            redisTemplate.opsForValue().set(RedisConstant.redisAssemblyLineAfter, assemblyLineAddBo);
        }

        log.info("agv点位信息" + businDataTask.getPoints());
//        Map<String,String> agvsn=(Map<String, String>) JSON.parse(businDataTask.getPoints());
//        List<String> collectagvsn = agvsn.entrySet().stream().sorted(Map.Entry.comparingByKey()).map(e -> e.getKey()).collect(Collectors.toList());
//        String s = collectagvsn.get(collectagvsn.size() - 2);
        String abnormalWaitPintGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.abnormalWaitPint);
        BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();
        pointQueryBo.setGroupNo(abnormalWaitPintGroup);

        // TODO 中科  测试 需要删除 修改平库释放后直接去下挂逻辑,后续不需要可以删掉
        if (bo.getSn().equals("3") && bo.getStatus().equals("completed") && "KW18".equals(taskAgvpoint)) {
            businDataTask.setTaskStatus("2");
            iBusinDataTaskService.updateById(businDataTask);
            // 创建任务
//            BusinDataTask task = new BusinDataTask();
//            task.setTaskCode("T_" + DateUtils.dateTimeNow());
//            task.setTaskPath("KW16");
//            task.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
//            task.setTaskType(TaskTypeEnum.mechainical.getValue());
//            task.setBatch(DateUtils.dateTimeNow("yyyy-MM-dd"));
//            task.setIsDown(String.valueOf(RCSTaskTypeEnum.TO_B_AND_PUT1.getValue()));
//            task.setContainerId(businDataTask.getContainerId()== null ? 0 :businDataTask.getContainerId());
//            task.setPlcId(30L);
//            task.setAgvNo(bo.getRobotId());
//
//            HashMap<Object, Object> map = new HashMap<>();
//            map.put("1","KW18");
//            map.put("2","KW16");
//            map.put("3","KW17");
//            task.setPoints(JsonUtil.toJSONString(map));
//            iBusinDataTaskService.insertBusinTask(task);
//            Long taskId = task.getId();
//
//            RcsCreateTaskDto rcsCreateTaskDto = new RcsCreateTaskDto();
//            rcsCreateTaskDto.setTaskId(taskId.toString());
//            rcsCreateTaskDto.setTaskType(RCSTaskTypeEnum.TO_B_AND_PUT1.getValue());
//            rcsCreateTaskDto.setMapId(1);
//            rcsCreateTaskDto.setRobotId(bo.getRobotId());
//
//            RcsIdList startId = new RcsIdList();
//            RcsIdList endId = new RcsIdList();
//            RcsIdList endId1 = new RcsIdList();
//            List<RcsIdList> idList = new ArrayList<>();
//            startId.setId("KW18");
//            idList.add(startId);
//            endId.setId("KW16");
//            idList.add(endId);
//            endId1.setId("KW17");
//            idList.add(endId1);
//
//            rcsCreateTaskDto.setTargets(idList);
//            Result rcsCreateTask = rcsCreateTask(rcsCreateTaskDto);
//            if (rcsCreateTask.getCode() == HttpStatus.SUCCESS.getCode()){
//                task.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
//                iBusinDataTaskService.updateById(task);
//                //新增空治具投放记录
//                BusinDpscontainerRecord dpscontainerRecord = new BusinDpscontainerRecord();
//                dpscontainerRecord.setBranchId(SecurityUtils.getCurrentBranchId());
//                dpscontainerRecord.setContainerId(businDataTask.getContainerId()==null? 0 : businDataTask.getContainerId());
//                dpscontainerRecord.setIsState("1");
//                dpscontainerRecord.setTaskCode(taskId);
//                dpscontainerRecord.setPointNo("KW16");
//                dpscontainerRecord.setCreateTime(DateUtils.getNowDate());
//                businDpsContainerRecordMapper.insert(dpscontainerRecord);
//            }
//            log.error(rcsCreateTask.getMsg());
//            log.error(task.toString());
            //平库空治具流向接口
            Result<Boolean> kw18Result = iBusinEnptyContainerService.emptyContainerFlowDir("KW18", businDataTask.getContainerId(), bo.getRobotId(), null);
            log.info("平库空治具流向接口:" + kw18Result.getMsg());
        }
        // TODO 中科  测试 需要删除

//        BasePointDeviceVo pointDevice = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBo);
//        if (bo.getStatus().equals("started") && s.equals(bo.getSn())&&"1".equals(businDataTask.getTaskType())&&pointDevice.getPointNo().equals(taskAgvpoint)) {
//
//            PlcOperate plcOperate = plcInit.getPlcOperateByIp(conn.getPlcIp());
//
//            Map readMap = new HashMap(1);
//            readMap.put(waringWaitpoint,waringWaitpointType);
//            String readPoint = JSON.toJSONString(readMap);
//
//            Map<String, Object> pointMap = plcReadAndWrite.readPlcData(plcOperate, readPoint);
//
//            if(Boolean.valueOf(pointMap.get(waringWaitpoint).toString())){
//                new Thread(() -> {
//                    try {
//                        Thread.sleep(1500);
//                    } catch (InterruptedException e) {
//                        e.printStackTrace();
//                    }
//                    RcsCreateTaskDto dto = new RcsCreateTaskDto();
//                    dto.setTaskId(bo.getTaskId().toString());
//                    // 放行逻辑
//                    Result resultGo = this.queryAck(dto);
//                    if (resultGo.getResult()) {
//                        log.info("异常码头放行成功");
//                    }
//                }).start();
//            }else{
//                 result.setCode(503);
//                 result.setResult(false);
//                log.info("异常码头不允许放行");
//                return result;
//            }
//        }

//        if(bo.getStatus().equals("completed")&&"Urgent_out".equals(taskAgvpoint)&&"Urgent_out".equals(businDataTask.getTaskPath())&&!TaskTypeEnum.urgent_out.getValue().equals(businDataTask.getTaskType())){
//            businDataTask.setTaskStatus("2");
//            iBusinDataTaskService.updateById(businDataTask);
//        }
//        if(bo.getStatus().equals("completed")&&taskAgvpoint.contains("Artificial")&&businDataTask.getTaskPath().contains("Artificial")){
//            redisTemplate.opsForValue().set(RedisConstant.Replenishment, businDataTask.getId()+"_"+bo.getRobotId()+"_"+businDataTask.getContainerId()+"_"+businDataTask.getTaskPath());
//            businDataTask.setTaskStatus("2");
//            iBusinDataTaskService.updateById(businDataTask);
//        }
//
//        // 补货出库 扣减库存
//        if(bo.getStatus().equals("completed") && taskAgvpoint.contains("Artificial")
//                && businDataTask.getTaskPath().contains("Artificial")
//                && businDataTask.getTaskType().equals(TaskTypeEnum.replenish_out.getValue())){
//            BusinPickupAddBo businPickupAddBo = new BusinPickupAddBo();
//
//            businPickupAddBo.setContainerId(businDataTask.getContainerId());
//            businPickupAddBo.setPointNo(businDataTask.getTaskPath());
//            businPickupAddBo.setTaskCode(businDataTask.getId().toString());
//            //根据任务ID获取保险杠明细
//            List<BusinPickupDtlAddBo> pickupDtlAddBos = new ArrayList<>();
//            List<BusinDataTaskGoodsVo> goodsVos = businDataTaskMapper.selectOutBoundTaskGoods(businDataTask.getId());
//            for (BusinDataTaskGoodsVo goodsVo : goodsVos) {
//                BusinPickupDtlAddBo businPickupDtlAddBo = new BusinPickupDtlAddBo();
//                businPickupDtlAddBo.setQrCode(goodsVo.getQrCode());
//                pickupDtlAddBos.add(businPickupDtlAddBo);
//            }
//            businPickupAddBo.setTaskType(businDataTask.getTaskType());
//            businPickupAddBo.setDtlAddBos(pickupDtlAddBos);
//
//            redisTemplate.opsForValue().set(RedisConstant.Replenishment, businDataTask.getId()+"_"+bo.getRobotId()+"_"+businDataTask.getContainerId()+"_"+businDataTask.getTaskPath());
//
//            Result<Boolean> pickupRecordResult = iBusinPickupService.saveBusinPickupRecord(businPickupAddBo);
//        }

        // 获取冲孔机取货点位并验证是否到达
        pointQueryBo = new BasePointDeviceQueryBo();
        pointQueryBo.setGroupNo(sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.punching_group));
//        pointQueryBo.setDevCode(iBasePunchService.selectBasePunchRecord(new BasePunch()).getId());
        // TODO 需要重新规划查找冲孔机ID
        pointQueryBo.setDevCode(2L);

        String toPointNoOne = null;
        String toPointNoTwo = null;

        List<BasePointDeviceVo> basePointDeviceVos = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo);
        if (basePointDeviceVos.size() > 0) {
            for (BasePointDeviceVo basePointDeviceVo : basePointDeviceVos) {
                if (basePointDeviceVo.getPointNo().contains("KW11")) {
                    toPointNoTwo = basePointDeviceVo.getPointNo();
                } else {
                    toPointNoOne = basePointDeviceVo.getPointNo();
                }
            }
        }

        // 如果到达 冲孔取货点位 就修改当前任务ID并且将任务ID存入redis 用于之后的冲孔流程使用
        if (bo.getStatus().equals("completed") && toPointNoOne.equals(taskAgvpoint) && toPointNoOne.equals(businDataTask.getTaskPath())) {
            businDataTask.setTaskStatus("2");
            iBusinDataTaskService.updateById(businDataTask);
            BasePunchRecord basePunchRecord = iBasePunchRecordService.getOne(new LambdaQueryWrapper<BasePunchRecord>()
                    .eq(BasePunchRecord::getTaskCode, Long.valueOf(bo.getTaskId()))
                    .last("limit 1"));
            basePunchRecord.setAgvNo(bo.getRobotId());
            iBasePunchRecordService.updateById(basePunchRecord);
            ;
            redisTemplate.opsForValue().set(RedisConstant.startPunchingTaskId, bo.getTaskId() + "_" + bo.getRobotId() + "_" + businDataTask.getContainerId());
            redisTemplate.opsForValue().set(RedisConstant.endPunchingTaskId, bo.getTaskId() + "_" + bo.getRobotId() + "_" + businDataTask.getContainerId());
        }

        // 如果到达 冲孔放货点位 就修改当前任务ID并且将任务ID存入redis 用于之后的冲孔流程使用
//        if(bo.getStatus().equals("completed") && idArr.length > 1 && ObjectUtils.isNotEmpty(redisTemplate.opsForValue().get(idArr[1]))
//                && toPointNoTwo.equals(redisTemplate.opsForValue().get(idArr[1]))){
//            redisTemplate.opsForValue().set(RedisConstant.endPunchingTaskId, bo.getTaskId());
//        }

//        if((businDataTask.getTaskType().equals(TaskTypeEnum.abnormal_delivery.getValue())
//                || businDataTask.getTaskType().equals(TaskTypeEnum.punching_delivery.getValue()))
//                && bo.getStatus().equals("completed") && businDataTask.getTaskPath().equals(taskAgvpoint)){
//            BusinPickupAddBo businPickupAddBo = new BusinPickupAddBo();
//
//            businPickupAddBo.setContainerId(businDataTask.getContainerId());
//            businPickupAddBo.setPointNo(businDataTask.getTaskPath());
//            businPickupAddBo.setTaskCode(businDataTask.getId().toString());
//            //根据任务ID获取保险杠明细
//            List<BusinPickupDtlAddBo> pickupDtlAddBos = new ArrayList<>();
//            List<BusinDataTaskGoodsVo> goodsVos = businDataTaskMapper.selectOutBoundTaskGoods(businDataTask.getId());
//            for (BusinDataTaskGoodsVo goodsVo : goodsVos) {
//                BusinPickupDtlAddBo businPickupDtlAddBo = new BusinPickupDtlAddBo();
//                businPickupDtlAddBo.setQrCode(goodsVo.getQrCode());
//                pickupDtlAddBos.add(businPickupDtlAddBo);
//            }
//            businPickupAddBo.setTaskType(businDataTask.getTaskType());
//            businPickupAddBo.setDtlAddBos(pickupDtlAddBos);
//
//            Result<Boolean> pickupRecordResult = iBusinPickupService.saveBusinPickupRecord(businPickupAddBo);
//            if (Result.isOk(pickupRecordResult)){
//                log.info("异常/冲孔出库完成！减库存完成！---任务ID为："+businDataTask.getId());
//            }
//        }

        // 新增安全光电相关逻辑
//        if (TaskTypeEnum.normal_in.getValue().equals(businDataTask.getTaskType())
//                ||TaskTypeEnum.empty_in.getValue().equals(businDataTask.getTaskType())
//                && bo.getSn().equals("3") && bo.getStatus().equals("completed")){
//
//        }

        if (TaskTypeEnum.emptyContainer_out.getValue().equals(taskType)
                || TaskTypeEnum.normal_out.getValue().equals(taskType)
                || TaskTypeEnum.urgent_out.getValue().equals(taskType)
                || TaskTypeEnum.named_loc.getValue().equals(taskType)) {
            Map<String, String> pointMap = JsonUtil.JsonStrToMap(businDataTask.getPoints());
            String s1 = pointMap.get("1");
            String s2 = pointMap.get("2");
            WcsPlcConnect conn1 = iWcsPlcConnectService.selectWcsPlcConnectById(39L);
            Map writeMap1 = new HashMap(1);
            Map<String, Object> allHbMap = new HashMap<>(1);
//            4#出口  DB320.2.9
//            5#出口  DB320.2.11
//            6#出口  DB320.2.13
            if ("1".equals(bo.getSn()) && "completed".equals(bo.getStatus())) {
                if ("KW6".equals(s1)) {
                    writeMap1.put("Boolean", "false");
                    allHbMap.put("DB320.2.3", writeMap1);
                }
                if ("KW8".equals(s1)) {
                    writeMap1.put("Boolean", "false");
                    allHbMap.put("DB320.2.7", writeMap1);
                }
                if ("KW10".equals(s1)) {
                    writeMap1.put("Boolean", "false");
                    allHbMap.put("DB320.2.6", writeMap1);
                }
                if ("KW23".equals(s1)) {
                    writeMap1.put("Boolean", "false");
                    allHbMap.put("DB320.2.9", writeMap1);
                }
                if ("KW25".equals(s1)) {
                    writeMap1.put("Boolean", "false");
                    allHbMap.put("DB320.2.11", writeMap1);
                }
                if ("KW27".equals(s1)) {
                    writeMap1.put("Boolean", "false");
                    allHbMap.put("DB320.2.13", writeMap1);
                }
            }
            if ("2".equals(bo.getSn()) && "completed".equals(bo.getStatus())) {
                if ("LY80".equals(s2)) {
                    writeMap1.put("Boolean", "true");
                    allHbMap.put("DB320.2.3", writeMap1);
                }
                if ("LY82".equals(s2)) {
                    writeMap1.put("Boolean", "true");
                    allHbMap.put("DB320.2.7", writeMap1);
                }
                if ("LY84".equals(s2)) {
                    writeMap1.put("Boolean", "true");
                    allHbMap.put("DB320.2.6", writeMap1);
                }
                if ("LY244".equals(s1)) {
                    writeMap1.put("Boolean", "true");
                    allHbMap.put("DB320.2.9", writeMap1);
                }
                if ("LY247".equals(s1)) {
                    writeMap1.put("Boolean", "true");
                    allHbMap.put("DB320.2.11", writeMap1);
                }
                if ("LY250".equals(s1)) {
                    writeMap1.put("Boolean", "true");
                    allHbMap.put("DB320.2.13", writeMap1);
                }
            }
            String writePoint = JSON.toJSONString(allHbMap);
            PlcOperate plcOperateWrite = plcInit.getPlcOperateByIp(conn1.getPlcIp());
            Boolean execWrite = plcReadAndWrite.execWrite(plcOperateWrite, writePoint);
            if (execWrite) {
                log.info("++++++++++++" + s1 + "关闭安全光电成功");
            }
        }
        log.info("agv上报接口执行结束");
        return Result.ok();
    }


    /**
     * 呼叫AGV
     *
     * @param taskId
     * @param taskType
     * @param points
     * @return
     */
    public Result<Boolean> callAGV(Long taskId, int taskType, List<String> points) {
        AGVMoveBo moveBo = new AGVMoveBo();
        moveBo.setTaskId(taskId);
        moveBo.setTaskType(taskType);
        moveBo.setPoints(points);
        Result<Boolean> booleanResult = moveByAGV(moveBo);
        return booleanResult;
    }

    /**
     * 添加角度
     *
     * @param taskId
     * @param taskType
     * @param points
     * @param toRow
     * @return com.shkj.common.core.domain.Result<java.lang.Boolean>
     * @author Comair
     * @date 2023/7/21 20:09
     */
    public Result<Boolean> callAGV(Long taskId, int taskType, List<String> points, String toRow) {
//        List<Integer> list = Arrays.asList(1,2,5,7,9,11,13,14);
        AGVMoveBo moveBo = new AGVMoveBo();
        moveBo.setTaskId(taskId);
        moveBo.setTaskType(taskType);
        moveBo.setPoints(points);
        Result<Boolean> booleanResult = null;
        if ("0".equals(taskType) || "7".equals(taskType)) {
            booleanResult = moveByAGV(moveBo, toRow);
//            if(list.contains(Integer.parseInt(toRow))){
//
//            }else{
//                booleanResult = moveByAGV(moveBo,0);
//            }
        } else {
            booleanResult = moveByAGV(moveBo);
        }
        return booleanResult;
    }

    /**
     * 添加角度
     *
     * @param taskId
     * @param taskType
     * @param points
     * @param toRow
     * @return com.shkj.common.core.domain.Result<java.lang.Boolean>
     * @author Comair
     * @date 2023/7/21 20:09
     */
    public Result<Boolean> callAGV(Long taskId, int taskType, List<String> points, String toRow, String agvno) {
        //List<Integer> list = Arrays.asList(1,2,5,7,9,11,13,14);
        AGVMoveBo moveBo = new AGVMoveBo();
        moveBo.setTaskId(taskId);
        moveBo.setTaskType(taskType);
        moveBo.setPoints(points);
        moveBo.setRobotId(agvno);
        Result<Boolean> booleanResult = null;
        if ("0".equals(taskType) || "7".equals(taskType)) {
            booleanResult = moveByAGV(moveBo, toRow);
//            if(list.contains(Integer.parseInt(toRow))){
//
//            }else{
//                booleanResult = moveByAGV(moveBo,0);
//            }
        } else {
            booleanResult = moveByAGV(moveBo);
        }


        return booleanResult;
    }


    /**
     * 获取AGV的实时数据，并存储至Redis中
     *
     * @param mapId
     */
    public void doAgvStates(String mapId) {
        //获取AGV系统的实时数据
        String agvData = rcsRobotsStatesForString(mapId);
        //   log.info("AGV实时数据："+agvData);
        //处理设备信息，存redis中
        this.doAGVRobotsStatesForRedis(agvData);
    }


    /**
     * 获取AGV实时状态信息
     *
     * @param mapId bo
     * @return {@code Result}
     */
    public String rcsRobotsStatesForString(String mapId) {
        Map<String, Object> map = new HashMap<>();
        //  map.put("mapId",Integer.parseInt(mapId));
        String json = JSONObject.toJSONString(map);
        String res = "";
        try {
            Map<String, String> headerMap = getHeaderMap();
            res = HttpRequest.post(agvStatesUrl)
                    .addHeaders(headerMap)
                    .body(json)
                    .execute().body();

        } catch (Exception e) {
            e.printStackTrace();
            log.error(" 获取实时数据rcsRobotsStatesForString 方法出错了 = {}", e.getMessage());
        }
        return res;
    }


    /**
     * AGV设备实时状态，存储至Redis中
     *
     * @param agvData
     */
    public void doAGVRobotsStatesForRedis(String agvData) {
        //log.info("处理agv设备状态信息开始");
        if (StringUtils.isNotEmpty(agvData)) {
            RcsThirdResult thirdResult = JSONObject.parseObject(agvData, RcsThirdResult.class);
            List<BusinAgvRealRedisInfo> redisList = new ArrayList<>();
            List<BusinAgvRealInfo> list = JSONArray.parseArray(thirdResult.getData().toString(), BusinAgvRealInfo.class);
            BusinAgvRealRedisInfo businAgvRealRedisInfo = null;
            for (BusinAgvRealInfo businAgvRealInfo : list) {
                businAgvRealRedisInfo = new BusinAgvRealRedisInfo();
                String agvState = businAgvRealInfo.getAgvState();
                String online = businAgvRealInfo.getOnline();
                int agvId = businAgvRealInfo.getId();
                businAgvRealRedisInfo.setId(agvId);
                businAgvRealRedisInfo.setTaskId(businAgvRealInfo.getTaskId());

                //如果在线状态是离线，则为离线，其他为AGV状态信息
                if (online.equals("false")) {
                    businAgvRealRedisInfo.setAgvState(online);
                } else {
                    businAgvRealRedisInfo.setAgvState(agvState);
                }
                businAgvRealRedisInfo.setErrors(businAgvRealInfo.getErrors());
                redisList.add(businAgvRealRedisInfo);
            }

            redisTemplate.opsForValue().set(RedisConstant.redisAgvRealInfo, redisList);
        } else {
            log.info("AGV实时数据为空");
        }
    }

}
