package com.shkj.wms.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
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.system.service.ISysParameterService;
import com.shkj.wms.bo.*;
import com.shkj.wms.domain.*;
import com.shkj.wms.service.*;
import com.shkj.wms.third.rcs.RCSUtil;
import com.shkj.wms.third.rcs.dto.RcsCreateTaskDto;
import com.shkj.wms.third.rcs.dto.RcsIdList;
import com.shkj.wms.constants.ParameterConstants;
import com.shkj.wms.enums.TaskStatusEnum;
import com.shkj.wms.enums.TaskTypeEnum;
import com.shkj.wms.mapper.*;
import com.shkj.wms.third.rcs.enums.RCSTaskTypeEnum;
import com.shkj.wms.utils.JsonUtil;
import com.shkj.wms.utils.TunnelTaskUtil;
import com.shkj.wms.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author zjx
 */
@Slf4j
@Service
public class IBusinEnptyContainerServiceImpl extends ServiceImpl<BaseContainerMapper, BaseContainer> implements IBusinEnptyContainerService {

    @Autowired
    private ISysParameterService sysParameterService;

    @Autowired
    IBasePointService iBasePointService;

    @Autowired
    IBusinDataTaskService iBusinDataTaskService;

    @Resource
    BasePointDeviceMapper basePointDeviceMapper;

    @Resource
    BusinDpsContainerRecordMapper businDpsContainerRecordMapper;

    @Resource
    private TunnelTaskUtil tunnelTaskUtil;

    @Resource
    BaseLocationPlcMapper baseLocationPlcMapper;

    @Resource
    BaseLocationMapper baseLocationMapper;

    @Resource
    RedisTemplate redisTemplate;

    @Autowired
    IBusinDataTaskService businDataTaskService;

    @Autowired
    IBasePointService basePointService;
    @Resource
    IBaseLocationService iBaseLocationService;
    @Resource
    BusinDataTaskServiceImpl businDataTaskServiceImpl;
    @Autowired
    RCSUtil rcsUtil;

    @Autowired
    ISysStockDetailService iSysStockDetailService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public synchronized Result<Boolean> emptyContainerFlowDir(String fromPoint,Long containerId,String agvno,String LaneagvType) {
        /**
         * * 1、根据设定的保养参数，及上次保养时间，计算是否需要保养，如果需要，先保养
         * *   如果保养存放的位置满了，就不再送过去，下次再来计算；
         * * 2、入库接驳口是否需要治具
         * * 3、是否有待呼叫空治具的任务
         * * 4、入库
         */

        //入库接驳口是否需要空治具
        BusinDataTaskVo dataTaskVo = null;
        BasePointDeviceVo basePointDeviceVo = null;
        boolean stuat=false;

        String toPpoint = null;
        String tmpPoint = null;
        String agvType = null;
        Long plcid=null;
        String tunnelId=null;
        Long stkPlcId =0L;
        Long dspPlcId =0L;
        BaseLocationVo locationVo=null;
        //防止进入保养后在进入入库
        boolean stuats=true;


        //治具是否需要保养
        BasePointDeviceVo pointDeviceVo = checkContailnerUpkeep(containerId);

        if (pointDeviceVo != null){
            toPpoint = pointDeviceVo.getPointNo();
            agvType= String.valueOf(RCSTaskTypeEnum.TO_B_AND_PUT.getValue());
            stuats=false;

        }else {
            String outEmptyType = redisTemplate.opsForValue().get(RedisConstant.out_empty_type).toString();
            if("开启".equals(outEmptyType)){
                //机械手输送线接驳口是否需要空治具
                basePointDeviceVo = checkDpsPoint();
            }
        }
        BusinDpscontainerRecord dpscontainerRecord = new BusinDpscontainerRecord();

        //返回不等于null,说明有空位
        if (basePointDeviceVo !=null){
            stuats=false;
            toPpoint = basePointDeviceVo.getPointNo();
            agvType= String.valueOf(RCSTaskTypeEnum.TO_B_AND_PUT1.getValue());
            plcid=basePointDeviceVo.getPlcId();
            //新增空治具投放记录
            dpscontainerRecord.setBranchId(SecurityUtils.getCurrentBranchId());
            dpscontainerRecord.setContainerId(containerId);
            dpscontainerRecord.setIsState("1");
            dpscontainerRecord.setPointNo(toPpoint);
            dpscontainerRecord.setCreateTime(DateUtils.getNowDate());
            businDpsContainerRecordMapper.insert(dpscontainerRecord);
        }else if (stuats){
            //是否有呼叫空治具的任务
              dataTaskVo = checkTaskData();
        }

        if (dataTaskVo !=null){
            agvType= String.valueOf(RCSTaskTypeEnum.TO_B_PUT.getValue());
            toPpoint = dataTaskVo.getTaskPath();
            stuat=true;
        }else if (stuats){
            Map map = checkWareForEmptycon();
            if(ObjectUtils.isEmpty(map)){
                return Result.err().msg("暂无空治具存放区域");
            }
            pointDeviceVo = BeanUtil.toBean(map.get("basePointDeviceVo"),BasePointDeviceVo.class);
            locationVo = BeanUtil.toBean(map.get("locationVo"),BaseLocationVo.class);
            agvType= String.valueOf(RCSTaskTypeEnum.TO_B_AND_PUT.getValue());
            toPpoint = pointDeviceVo.getPointNo();
            dspPlcId=Long.valueOf(sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.LK_plc_id));

            //获取巷道对应的堆垛机信息
            BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();
            pointQueryBo.setDevType("1");
            pointQueryBo.setTunnel(pointDeviceVo.getTunnel());
            BaseDevicePlcVo baseDevicePlcVo = baseLocationPlcMapper.selectBaseDevicePlc(pointQueryBo);
            stkPlcId = baseDevicePlcVo.getPlcId();
            tunnelId = baseDevicePlcVo.getTunnel();

        }

        //创建任务
        BusinDataTask businDataTask = new BusinDataTask();
        businDataTask.setTaskPath(toPpoint);
        String taskstatus=TaskStatusEnum.wait_put.getValue();
        businDataTask.setTaskStatus(taskstatus);
        String Type=TaskTypeEnum.emptyCon.getValue();
        if (basePointDeviceVo !=null){
            Type=TaskTypeEnum.mechainical.getValue();
        }
        businDataTask.setTaskType(Type);
        businDataTask.setIsDown(agvType);
        businDataTask.setContainerId(containerId);
        if (plcid!=null&&plcid!=0){
            businDataTask.setPlcId(plcid);
        }
        businDataTask.setDpsNoOne(dspPlcId);
        businDataTask.setDpsNoTwo(stkPlcId);
        businDataTask.setTunnel(tunnelId);
        businDataTask.setBatch(DateUtils.getDate());
        if (StringUtils.isNotEmpty(agvno)) {
            businDataTask.setAgvNo(agvno);
        }
        if (stuat){
            businDataTask.setRemark(String.valueOf(dataTaskVo.getId()));
        }

        if (locationVo!=null){
            businDataTask.setToColumn(locationVo.getLocationColumn());
            businDataTask.setToLayer(locationVo.getLayer());
            businDataTask.setToRow(locationVo.getLocationRow());
            businDataTask.setLocationId(locationVo.getId());

        }

        int  agvTaskType = Integer.valueOf(agvType);
        RcsCreateTaskDto dto = new RcsCreateTaskDto();
        Map<String,String> snPointMap = new HashMap<>();
        List<RcsIdList> idList = new ArrayList<>();

        dto.setMapId(1);
        dto.setTaskType(agvTaskType);
        if (StringUtils.isNotEmpty(LaneagvType)){
            dto.setTaskType(Integer.valueOf(LaneagvType));
        }
        if (StringUtils.isNotEmpty(agvno)) {
            dto.setRobotId(agvno);
        }

        RcsIdList startId = new RcsIdList();
        RcsIdList endId = new RcsIdList();
        RcsIdList endId1 = new RcsIdList();

        startId.setId(fromPoint);
        idList.add(startId);
        snPointMap.put("1",fromPoint);
        snPointMap.put("2",toPpoint);
        endId.setId(toPpoint);
        idList.add(endId);
        if (String.valueOf(RCSTaskTypeEnum.TO_B_AND_PUT1.getValue()).equals(agvType)) {
            snPointMap.put("3","KW17");
            endId1.setId("KW17");
            idList.add(endId1);
        }
        dto.setTargets(idList);

        businDataTask.setPoints(JsonUtil.toJSONString(snPointMap));

            //创建任务
        iBusinDataTaskService.insertBusinTask(businDataTask);
        Long taskId = businDataTask.getId();
        dto.setTaskId(taskId.toString());
        if (Type.equals(TaskTypeEnum.mechainical.getValue())) {
            //送往机械手的任务记录添加任务号
            dpscontainerRecord.setTaskCode(taskId);
            businDpsContainerRecordMapper.updateById(dpscontainerRecord);
        }
        if(Type.equals(TaskTypeEnum.emptyCon.getValue())) {
            log.info("空治具流向接口创建的任务号为:" + taskId);
            log.info("任务的治具号为:"+containerId);
            log.info("传入的起点为:"+fromPoint);
        }
        //呼叫AGV
        Result<Boolean> booleanResult =  rcsUtil.rcsCreateTask(dto);

        if (booleanResult.getCode()== HttpStatus.SUCCESS.getCode()){

            businDataTask.setTaskStatus(TaskStatusEnum.wait_callback.getValue());
            iBusinDataTaskService.updateById(businDataTask);
            //2024-07-12 呼叫AGV成功后不释放点位，待AGV取货完成后，再释放点位信息
//            //更改点位状态为空闲
//            BasePoint basePoint = basePointService.selectBasePointByPointNo(fromPoint);
//            basePoint.setIsOccupy("0");
//            basePointService.updateById(basePoint);
            //更新货位状态为已分配
            if (locationVo!=null){
                BaseLocation baseLocation = BeanUtil.toBean(locationVo,BaseLocation.class);
                baseLocation.setLocationStatus("4");
                baseLocationMapper.updateById(baseLocation);
            }
            //有呼叫空治具的任务时添加任务后更改原任务状态
            if (stuat) {
                BusinDataTask byId = iBusinDataTaskService.getById(dataTaskVo.getId());
                byId.setTaskStatus("3");
                byId.setRemark("已取消，已被任务ID为："+taskId+" 替代！");
                iBusinDataTaskService.updateById(byId);
                businDataTask.setRemark(String.valueOf(dataTaskVo.getId()));
            }
        }
        else{
            if (businDataTask.getTaskType().equals(TaskTypeEnum.mechainical.getValue())){
                //呼叫agv失败更改送往机械手的任务为2
                dpscontainerRecord.setIsState("2");
                businDpsContainerRecordMapper.updateById(dpscontainerRecord);
            }
            businDataTask.setExceptionMsg(booleanResult.getMsg());
            iBusinDataTaskService.updateById(businDataTask);
        }
        return booleanResult;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void emptyContainerFromWare() {
        /**
         *  1、入库接驳口是否需要治具
         *  2、是否有待呼叫空治具的任务
         */

        //入库接驳口是否需要空治具
        BusinDataTaskVo dataTaskVo = null;
        BasePointDeviceVo basePointDeviceVo = null;
        boolean stuats=false;

        String toPpoint = null;
        Long stkPlcId =0L;
        Long dspPlcId =0L;

        //机械手输送线接驳口是否需要空治具
        basePointDeviceVo = checkDpsPoint1();
        BusinDpscontainerRecord dpscontainerRecord = new BusinDpscontainerRecord();
        //返回不等于null,说明有空位
        if (basePointDeviceVo !=null){
            stuats=true;
            toPpoint = basePointDeviceVo.getPointNo();

        }else {
            //是否有呼叫空治具的任务
            dataTaskVo = checkTaskData();
        }

        if (dataTaskVo !=null){
            toPpoint = dataTaskVo.getTaskPath();
            stuats=true;
        }

        //输送线或是有呼叫空治具的业务，创建待执行的堆垛机任务
        BaseLocationVo baseLocationVo =null;
        String tunnles=null;
        if (stuats){
            //查询空治具所在位置
            //空治具区域
            Long emptyconArea = Long.valueOf(sysParameterService.selectConfigByKey(SecurityUtils.getCurrentBranchId(), ParameterConstants.ParameterSystem.emptycon_area));
            //按照拣货路径查找空治具所在货位
            List<BaseLocationVo> baseLocationVoList = baseLocationMapper.getEmptyContainerFromLocation(emptyconArea);

            List<String> tunnelList = baseLocationVoList.stream().map(e -> e.getTunnel()).distinct().collect(Collectors.toList());

            //从存在存放空治具货位的巷道里选择较优的巷道进行入库
            //首选选择任务数为空或者任务数最少的巷道
            //任务数相同时选取存放空治具货位最多的巷道
            List<String> tunnelResult = new ArrayList<>();
            Integer minTaskNum = 0;
            Integer maxEmptyLocationNum = 0;
            for (int i = 0; i < tunnelList.size(); i++) {
                String tunnel = tunnelList.get(i);
                Integer taskNum = tunnelTaskUtil.getTotalTaskNum(tunnel,1);
                int curEmptyNum = baseLocationVoList.stream().filter(e -> tunnel.equals(e.getTunnel())).collect(Collectors.toList()).size();
                if (minTaskNum == 0 && taskNum.equals(minTaskNum)) {
                    if(i != 0){
                        if (curEmptyNum > maxEmptyLocationNum) {
                            tunnelResult.clear();
                            tunnelResult.add(tunnel);
                            maxEmptyLocationNum = curEmptyNum;
                        }
                    } else {
                        minTaskNum = taskNum;
                        tunnelResult.add(tunnel);
                        maxEmptyLocationNum = curEmptyNum;
                    }
                }else if (minTaskNum == 0) {
                    if(i == 0){
                        minTaskNum = taskNum;
                        tunnelResult.add(tunnel);
                        maxEmptyLocationNum = curEmptyNum;
                    }
                } else if (minTaskNum != 0 && taskNum.equals(minTaskNum)) {
                    if (curEmptyNum > maxEmptyLocationNum) {
                        tunnelResult.clear();
                        tunnelResult.add(tunnel);
                        maxEmptyLocationNum = curEmptyNum;
                    }
                } else if (minTaskNum != 0 && taskNum < minTaskNum) {
                    minTaskNum = taskNum;
                    tunnelResult.clear();
                    tunnelResult.add(tunnel);
                    maxEmptyLocationNum = curEmptyNum;
                }
            }
            String tunnel = tunnelResult.get(0);
            tunnles = tunnel;

            List<BaseLocationVo> locationVoList = baseLocationVoList.stream().filter(e -> e.getTunnel().equals(tunnel)).collect(Collectors.toList());

            List<Long> listlocationId=new ArrayList<>();
            //如果是双深位 查看外侧的货位是否有托盘
            for (BaseLocationVo baseLovationVO: locationVoList) {
                if (baseLovationVO.getIsDeep().equals("2")){
                    BaseLocation one=null;
                    one = iBaseLocationService.getOne(new LambdaQueryWrapper<BaseLocation>()
                            .eq(BaseLocation::getRoute,baseLovationVO.getRoute())
                            .eq(BaseLocation::getIsDeep,"1")
                            .eq(BaseLocation::getTunnel,baseLovationVO.getTunnel())
                            .eq(BaseLocation::getAreaId,baseLovationVO.getAreaId()));
                    if (one!=null&&(one.getLocationStatus().equals("4")||one.getLocationStatus().equals("2")||one.getLocationStatus().equals("1"))){
                        listlocationId.add(baseLovationVO.getId());
                    }
                }
            }
            if (listlocationId.size()>0){
                for (int i=0;i<locationVoList.size();i++) {
                    int number=i;
                    listlocationId.stream().forEach(e->{
                        if (e.equals(locationVoList.get(number).getId())){
                            locationVoList.remove(number);
                        }
                    });
                }
            }
            if(locationVoList.size() != 0){
                //根据巷道分配货位
                baseLocationVo=locationVoList.get(0);
            }
        }
        //库内有空治具
        if (baseLocationVo !=null){
            //输送线PLCID
            dspPlcId=Long.valueOf(sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.LK_plc_id));

            //堆垛机输送线ID
            //获取巷道对应的堆垛机信息
            BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();
            pointQueryBo.setDevType("1");
            pointQueryBo.setTunnel(baseLocationVo.getTunnel());
            BaseDevicePlcVo baseDevicePlcVo = baseLocationPlcMapper.selectBaseDevicePlc(pointQueryBo);
            stkPlcId = baseDevicePlcVo.getPlcId();

            //创建任务
            BusinDataTask businDataTask = new BusinDataTask();
            businDataTask.setTaskPath(toPpoint);
            String taskstatus=TaskStatusEnum.wait_put.getValue();
            businDataTask.setTaskStatus(taskstatus);
            //空治具出库
            String Type=TaskTypeEnum.emptyContainer_out.getValue();
            businDataTask.setTaskType(Type);
            businDataTask.setDpsNoOne(dspPlcId);
            businDataTask.setDpsNoTwo(stkPlcId);
            businDataTask.setTunnel(baseLocationVo.getTunnel());
            businDataTask.setBatch(DateUtils.getDate());
            businDataTask.setFromColumn(baseLocationVo.getLocationColumn());
            businDataTask.setFromLayer(baseLocationVo.getLayer());
            businDataTask.setFromRow(baseLocationVo.getLocationRow());
            businDataTask.setLocationId(baseLocationVo.getId());
            businDataTask.setAssociatedTasksId(ObjectUtils.isNotEmpty(dataTaskVo) ? String.valueOf(dataTaskVo.getId()) : "");

            //更改货位状态为已分配
            BaseLocation location = iBaseLocationService.getById(businDataTask.getLocationId());
            location.setLocationStatus("4");
            iBaseLocationService.updateById(location);

            if (ObjectUtils.isNotEmpty(dataTaskVo)){
                BusinTaskQueryBo queryBo = new BusinTaskQueryBo();
                queryBo.setId(dataTaskVo.getId());
                BusinDataTask businDataTasks = iBusinDataTaskService.getById(new BusinDataTask().setId(dataTaskVo.getId()));
                businDataTasks.setTaskStatus("1");
                iBusinDataTaskService.updateById(businDataTasks);
            }

            //根据货位拿到库存的治具号
            SysStockDetail sysStockDetail = iSysStockDetailService.getOne(new LambdaQueryWrapper<SysStockDetail>()
                    .eq(SysStockDetail::getLocationId, baseLocationVo.getId())
                    .eq(SysStockDetail::getQty, "1")
                    .isNull(SysStockDetail::getOutQty));
            Long containerId=null;
            if (ObjectUtils.isNotEmpty(sysStockDetail)) {
                containerId = sysStockDetail.getContainerCode();
                businDataTask.setContainerId(containerId);
            }

            //创建任务
            iBusinDataTaskService.insertBusinTask(businDataTask);
            if (basePointDeviceVo!=null){
                dpscontainerRecord.setBranchId(SecurityUtils.getCurrentBranchId());
                dpscontainerRecord.setContainerId(containerId);
                dpscontainerRecord.setTaskCode(businDataTask.getId());
                dpscontainerRecord.setIsState("0");
                dpscontainerRecord.setPointNo(toPpoint);
                dpscontainerRecord.setCreateTime(DateUtils.getNowDate());
                businDpsContainerRecordMapper.insert(dpscontainerRecord);
            }
            if(StringUtils.isNotEmpty(tunnles)) {
                tunnelTaskUtil.addOutboundTaskNum(tunnles);
            }
        }
    }


    /**
     *  获取治具已使用天数，判断是否需要保养
     * @param bo bo
     * @return
     */

    public BusinContainerUpkeepVo getContainerUpkeepDay(BusinContainerUpkeepQueryBo bo) {
        //治具保养周期
        bo.setBranchId(SecurityUtils.getCurrentBranchId());
        return this.baseMapper.getContainerUpkeepDay(bo);
    }

    public BasePointDeviceVo checkContailnerUpkeep(Long containerId) {
        if (containerId == 0){
            log.info("当前治具号为0无需保养");
            return null;
        }
        // 治具保养周期
        int upkeepDay = Integer.valueOf(sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.upkeep_day));
        BusinContainerUpkeepQueryBo bo = new BusinContainerUpkeepQueryBo();
        bo.setContainerId(containerId);
        BusinContainerUpkeepVo containerUpkeepDay = this.getContainerUpkeepDay(bo);
        int daysUsed = Integer.valueOf(containerUpkeepDay.getDaysUsed());
        //治具使用天数大于等于保养周期，则送去保养
        if (Integer.valueOf(daysUsed) >= upkeepDay) {
            //获取维修区点位信息
            String tepairGroup = sysParameterService.selectConfigByKey(ParameterConstants.ParameterSystem.Upkeep_piont);
            BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();
            pointQueryBo.setGroupNo(tepairGroup);

            BasePointDeviceVo pointDevice = basePointDeviceMapper.selectBasePointByGroupno(pointQueryBo);
            return pointDevice;
        }
        return null;
    }

    public  synchronized   BasePointDeviceVo checkDpsPoint(){

        BasePointDeviceVo basePointDeviceVo =null;
        String dpsPoint = sysParameterService.selectConfigByKey(SecurityUtils.getCurrentBranchId(), ParameterConstants.ParameterSystem.putin_point);

        Object temp = redisTemplate.opsForValue().get("PLCAuto");

        if (ObjectUtils.isNotEmpty(temp) && !(boolean)temp) {
            dpsPoint =  sysParameterService.selectConfigByKey(SecurityUtils.getCurrentBranchId(), ParameterConstants.ParameterSystem.blanking_point);
        }
        BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();
        pointQueryBo.setGroupNo(dpsPoint);
        List<BasePointDeviceVo> basePointDeviceVos = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo);

        if (basePointDeviceVos.size() > 0) {
            basePointDeviceVo = basePointDeviceVos.get(0);
        }
        Map<String,Object> dpscontainerRecord = businDpsContainerRecordMapper.selectBusinDpscontainerRecord1(basePointDeviceVo.getPointNo());
        if (ObjectUtils.isNotEmpty(dpscontainerRecord)){
            //到达上限
            if(Integer.parseInt(dpscontainerRecord.get("counts").toString()) > (Integer.parseInt(dpscontainerRecord.get("max_task_qty").toString()))) {
//                if (ObjectUtils.isNotEmpty(redisTemplate.opsForValue().get(RedisConstant.check_warehouse_out))) {
//                    boolean checkWarehouseOut = Boolean.parseBoolean(redisTemplate.opsForValue().get(RedisConstant.check_warehouse_out).toString());
//                    if (checkWarehouseOut) {
//                        redisTemplate.opsForValue().set(RedisConstant.check_warehouse_out,false);
//                    }
//                }else{
//                    redisTemplate.opsForValue().set(RedisConstant.check_warehouse_out,false);
//                }
                basePointDeviceVo=null;
            }
//            else{
//                //验证是从立库出还是释放  到下挂
//                if(ObjectUtils.isNotEmpty(redisTemplate.opsForValue().get(RedisConstant.check_warehouse_out))){
//                    Boolean checkWarehouseOut = Boolean.parseBoolean(redisTemplate.opsForValue().get(RedisConstant.check_warehouse_out).toString());
//                    // 如果是false 释放到下挂
//                    if(!checkWarehouseOut){
//                        if(Integer.parseInt(dpscontainerRecord.get("counts").toString()) < Integer.parseInt(dpscontainerRecord.get("min_task_qty").toString())){
//                            redisTemplate.opsForValue().set(RedisConstant.check_warehouse_out,true);
//                        }else{
//                            basePointDeviceVo=null;
//                        }
//                    }
//                }else{
//                    if(Integer.parseInt(dpscontainerRecord.get("counts").toString()) < Integer.parseInt(dpscontainerRecord.get("min_task_qty").toString())){
//                        redisTemplate.opsForValue().set(RedisConstant.check_warehouse_out,true);
//                    }
//                }
//            }
        }else{
            redisTemplate.opsForValue().set(RedisConstant.check_warehouse_out,true);
        }
        return basePointDeviceVo;
    }


    public  synchronized BasePointDeviceVo checkDpsPoint1(){

        BasePointDeviceVo basePointDeviceVo =null;
        String dpsPoint = sysParameterService.selectConfigByKey(SecurityUtils.getCurrentBranchId(), ParameterConstants.ParameterSystem.putin_point);

        Object temp = redisTemplate.opsForValue().get("PLCAuto");

        if (ObjectUtils.isNotEmpty(temp) && !(boolean)temp) {
            dpsPoint =  sysParameterService.selectConfigByKey(SecurityUtils.getCurrentBranchId(), ParameterConstants.ParameterSystem.blanking_point);
        }
        BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();
        pointQueryBo.setGroupNo(dpsPoint);
        List<BasePointDeviceVo> basePointDeviceVos = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo);

        if (basePointDeviceVos.size() > 0) {
            basePointDeviceVo = basePointDeviceVos.get(0);
        }
        Map<String,Object> dpscontainerRecord = businDpsContainerRecordMapper.selectBusinDpscontainerRecord(basePointDeviceVo.getPointNo());
        if (ObjectUtils.isNotEmpty(dpscontainerRecord)){
            //到达上限
            if(Integer.parseInt(dpscontainerRecord.get("counts").toString()) > (Integer.parseInt(dpscontainerRecord.get("max_task_qty").toString()))) {
//                if (ObjectUtils.isNotEmpty(redisTemplate.opsForValue().get(RedisConstant.check_warehouse_out))) {
//                    boolean checkWarehouseOut = Boolean.parseBoolean(redisTemplate.opsForValue().get(RedisConstant.check_warehouse_out).toString());
//                    if (checkWarehouseOut) {
//                        redisTemplate.opsForValue().set(RedisConstant.check_warehouse_out,false);
//                    }
//                }else{
//                    redisTemplate.opsForValue().set(RedisConstant.check_warehouse_out,false);
//                }
                basePointDeviceVo=null;
            }
//            else{
//                //验证是从立库出还是释放  到下挂
//                if(ObjectUtils.isNotEmpty(redisTemplate.opsForValue().get(RedisConstant.check_warehouse_out))){
//                    Boolean checkWarehouseOut = Boolean.parseBoolean(redisTemplate.opsForValue().get(RedisConstant.check_warehouse_out).toString());
//                    // 如果是false 释放到下挂
//                    if(!checkWarehouseOut){
//                        if(Integer.parseInt(dpscontainerRecord.get("counts").toString()) < Integer.parseInt(dpscontainerRecord.get("min_task_qty").toString())){
//                            redisTemplate.opsForValue().set(RedisConstant.check_warehouse_out,true);
//                        }else{
//                            basePointDeviceVo=null;
//                        }
//                    }
//                }else{
//                    if(Integer.parseInt(dpscontainerRecord.get("counts").toString()) < Integer.parseInt(dpscontainerRecord.get("min_task_qty").toString())){
//                        redisTemplate.opsForValue().set(RedisConstant.check_warehouse_out,true);
//                    }
//                }
//            }
        }else{
            redisTemplate.opsForValue().set(RedisConstant.check_warehouse_out,true);
        }
        return basePointDeviceVo;
    }


    public synchronized  BusinDataTaskVo  checkTaskData(){
        BusinDataTaskVo dataTaskVo=null;
        BusinTaskQueryBo queryBo = new BusinTaskQueryBo();
        queryBo.setTaskType("8");
        List<BusinDataTaskVo> businDataTaskVos = iBusinDataTaskService.selectBusinDataTask(queryBo);
        if (businDataTaskVos.size()>0){
            dataTaskVo = businDataTaskVos.get(0);
        }
        queryBo.setTaskType("14");
        businDataTaskVos = iBusinDataTaskService.selectBusinDataTask(queryBo);
        if (businDataTaskVos.size()>0){
            dataTaskVo = businDataTaskVos.get(0);
        }
        return dataTaskVo;
    }

    private BaseLocationVo assginLocation(List<BaseLocationVo> locationList) {
        BaseLocationVo resultLocationVo = null;
        //根据拣货路径选择最近一个货位
        for (int i = 0; i < locationList.size(); i++) {
            BaseLocationVo locationVo = locationList.get(i);
            //如果该货位为双深位，则直接选择该库位
            if ("2".equals(locationVo.getIsDeep())) {
                return locationVo;
            } else {
                // 检查该单深位是否有对应双深位;如果有
                if ("1".equals(locationVo.getIsDeep())) {
                    BaseLocationQueryListBo bo = new BaseLocationQueryListBo();
                    bo.setAreaId(locationVo.getAreaId());
                    bo.setTunnel(locationVo.getTunnel());
                    bo.setRoute(locationVo.getRoute());
                    bo.setIsDeep("2");
                    log.info("空托入庫查詢條件："+JsonUtil.toJSONString(bo));
                    List<BaseLocationVo> baseLocationVos = baseLocationMapper.queryBaseLocationListByDerive1(bo);
                    log.info("如果查询到的是单深位，查找到的双深位货位："+JsonUtil.toJSONString(baseLocationVos));
                    if (baseLocationVos.size() > 0) {
                        log.info("查询到的双深位库位信息："+JsonUtil.toJSONString(baseLocationVos.get(0)));
                        if(baseLocationVos.get(0).getLocationStatus().equals("4")
                                || baseLocationVos.get(0).getLocationStatus().equals("1")){
                            log.info("已有庫存，繼續查找："+JsonUtil.toJSONString(baseLocationVos.get(0)));
                            continue;
                        }else{
                            return locationVo;
                        }
                    }else{
                        return locationVo;
                    }
                }
            }
        }
        return resultLocationVo;
    }

    public synchronized Map checkWareForEmptycon(){
        //入库
        //获取立库区的空治具存放区域编号
        Long emptyconArea = Long.valueOf(sysParameterService.selectConfigByKey(SecurityUtils.getCurrentBranchId(), ParameterConstants.ParameterSystem.emptycon_area));
        BaseLocationVo locationVo = null;
        List<BaseLocationVo> baseLocationVos = baseLocationMapper.getLocationByAreaId(emptyconArea);
        if (baseLocationVos.size() > 0) {
            locationVo = baseLocationVos.get(0);
        }else{
            Map map = new HashMap();
            return map;
        }
        log.info("给空治具分配货位查询到的货位信息："+JsonUtil.toJSONString(locationVo));

        //存放空治具货位所在巷道列表
        List<String> tunnelList = baseLocationVos.stream().map(e -> e.getTunnel()).distinct().collect(Collectors.toList());

        log.info("存放空治具货位所在巷道列表："+JsonUtil.toJSONString(tunnelList));
        //从存在存放空治具货位的巷道里选择较优的巷道进行入库
        //首选选择任务数为空或者任务数最少的巷道
        //任务数相同时选取存放空治具货位最多的巷道
        List<String> tunnelResult = new ArrayList<>();
        Integer minTaskNum = 0;
        Integer maxEmptyLocationNum = 0;

        for (int i = 0; i < tunnelList.size(); i++) {
            String tunnel = tunnelList.get(i);
            //Integer taskNum = businDataTaskService.getCountByTunnel(tunnel);
            Integer taskNum = tunnelTaskUtil.getTotalTaskNum(tunnel,0);
            int curEmptyNum = baseLocationVos.stream().filter(e -> tunnel.equals(e.getTunnel())).collect(Collectors.toList()).size();
            log.info("空治具分配之前----当前巷道："+tunnel+" 目前任务数："+taskNum+"  当前空货位数量："+curEmptyNum);
            if (minTaskNum == 0 && taskNum.equals(minTaskNum)) {
                if(i != 0){
                    if (curEmptyNum > maxEmptyLocationNum) {
                        tunnelResult.clear();
                        tunnelResult.add(tunnel);
                        maxEmptyLocationNum = curEmptyNum;
                    }
                } else {
                    minTaskNum = taskNum;
                    tunnelResult.add(tunnel);
                    maxEmptyLocationNum = curEmptyNum;
                }
            }else if (minTaskNum == 0) {
                if(i == 0){
                    minTaskNum = taskNum;
                    tunnelResult.add(tunnel);
                    maxEmptyLocationNum = curEmptyNum;
                }
            } else if (minTaskNum != 0 && taskNum.equals(minTaskNum)) {
                if (curEmptyNum > maxEmptyLocationNum) {
                    tunnelResult.clear();
                    tunnelResult.add(tunnel);
                    maxEmptyLocationNum = curEmptyNum;
                }
            } else if (minTaskNum != 0 && taskNum < minTaskNum) {
                minTaskNum = taskNum;
                tunnelResult.clear();
                tunnelResult.add(tunnel);
                maxEmptyLocationNum = curEmptyNum;
            }

            log.info("空治具分配之后----当前巷道："+tunnel+" 目前任务数："+taskNum+"  当前空货位数量："+curEmptyNum);
        }
        //从选取的巷道中选择库位
        BasePointDeviceVo basePointDeviceVo =null;
        if (tunnelResult.size() > 0) {
            String tunnel = tunnelResult.get(0);
            log.info("空治具选择的巷道："+tunnel);
            List<BaseLocationVo> resultLocationList = baseLocationVos.stream().filter(e -> tunnel.equals(e.getTunnel())).collect(Collectors.toList());
            locationVo = resultLocationList.get(0);
            log.info("空治具分配到的货位信息："+JsonUtil.toJSONString(locationVo));
            //巷道中货位数大于1时，进行分配
            if (resultLocationList.size() > 1) {
                BaseLocationVo assginLocation = assginLocation(resultLocationList);
                if (assginLocation != null) {
                    locationVo = assginLocation;
                }
            }

            BasePointDeviceQueryBo pointQueryBo = new BasePointDeviceQueryBo();
            pointQueryBo.setTunnel(tunnel);
            pointQueryBo.setDirection("0");
            List<BasePointDeviceVo> basePointDeviceVos = baseLocationPlcMapper.selectBasePointByGroupno(pointQueryBo);

            if (basePointDeviceVos.size() > 0) {
                basePointDeviceVo = basePointDeviceVos.get(0);
            }
        }

        Map map = new HashMap();
        map.put("basePointDeviceVo",basePointDeviceVo);
        map.put("locationVo",locationVo);
        if (ObjectUtils.isNotEmpty(locationVo)){
            BaseLocation baseLocation = BeanUtil.toBean(locationVo,BaseLocation.class);
            baseLocation.setLocationStatus("4");
            baseLocationMapper.updateById(baseLocation);
        }
        return map;
    }
}
