package org.nl.acs.task.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
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.metadata.IPage;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import lombok.extern.slf4j.Slf4j;
import org.nl.acs.AcsConfig;
import org.nl.acs.agv.server.XianGongAgvService;
import org.nl.acs.auto.initial.ApplicationAutoInitial;
import org.nl.acs.common.base.PageInfo;
import org.nl.acs.common.base.QueryHelpMybatisPlus;
import org.nl.acs.common.base.impl.CommonServiceImpl;
import org.nl.acs.device.domain.Device;
import org.nl.acs.device.enums.DeviceType;
import org.nl.acs.device.service.DeviceAssignedService;
import org.nl.acs.device.service.DeviceService;
import org.nl.acs.device.service.dto.DeviceAssignedDto;
import org.nl.acs.device.service.impl.DeviceServiceImpl;
import org.nl.acs.device_driver.RequestMethodEnum;
import org.nl.acs.ext.wms.data.feedBackTaskStatus.FeedBackTaskStatusRequest;
import org.nl.acs.ext.wms.service.AcsToWmsService;
import org.nl.acs.instruction.domain.Instruction;
import org.nl.acs.instruction.service.InstructionService;
import org.nl.acs.instruction.service.dto.InstructionDto;
import org.nl.acs.opc.DeviceAppService;
import org.nl.acs.opc.DeviceAppServiceImpl;
import org.nl.acs.route.domain.RoutePlan;
import org.nl.acs.route.service.RouteLineService;
import org.nl.acs.route.service.dto.RouteLineDto;
import org.nl.acs.route.service.mapper.RoutePlanMapper;
import org.nl.acs.storage_cell.service.StorageCellService;
import org.nl.acs.task.TaskInstructionLock;
import org.nl.acs.task.domain.Task;
import org.nl.acs.task.service.TaskFeedbackService;
import org.nl.acs.task.service.TaskService;
import org.nl.acs.task.service.dto.TaskDto;
import org.nl.acs.task.service.dto.TaskFeedbackDto;
import org.nl.acs.task.service.dto.TaskQueryParam;
import org.nl.acs.task.service.mapper.TaskMapper;
import org.nl.acs.utils.ConvertUtil;
import org.nl.acs.utils.PageUtil;
import org.nl.common.exception.BadRequestException;
import org.nl.common.utils.CodeUtil;
import org.nl.common.utils.FileUtil;
import org.nl.common.utils.SecurityUtils;
import org.nl.config.SpringContextHolder;
import org.nl.config.thread.ThreadPoolExecutorUtil;
import org.nl.system.service.param.ISysParamService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author jiaolm
 * @date 2023-05-09
 */
@Service
@Slf4j
@Lazy
// @CacheConfig(cacheNames = TaskService.CACHE_KEY)
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true, rollbackFor = Exception.class)
public class TaskServiceImpl extends CommonServiceImpl<TaskMapper, Task> implements TaskService, ApplicationAutoInitial {

    // private final RedisUtils redisUtils;
    @Autowired
    TaskMapper taskMapper;
    @Autowired
    RoutePlanMapper routePlanMapper;

    List<TaskDto> tasks = new CopyOnWriteArrayList<>();

    @Autowired
    DeviceAppService deviceAppService;
    @Autowired
    RouteLineService routelineserver;
    @Autowired
    AcsToWmsService acstowmsService;
    @Autowired
    TaskFeedbackService taskFeedbackService;
    @Autowired
    ISysParamService paramService;
    @Autowired
    XianGongAgvService agvService;
    @Autowired
    RouteLineService routeLineService;
    @Autowired
    DeviceAssignedService deviceAssignedService;
    @Autowired
    InstructionService instructionService;
    @Autowired
    StorageCellService storageCellService;
    private final static ThreadPoolExecutor EXECUTOR = ThreadPoolExecutorUtil.getPoll();
    @Override
    public PageInfo<TaskDto> queryAll(TaskQueryParam query, Pageable pageable) {
        IPage<Task> queryPage = PageUtil.toMybatisPage(pageable);
        IPage<Task> page = taskMapper.selectPage(queryPage, QueryHelpMybatisPlus.getPredicate(query));
        return ConvertUtil.convertPage(page, TaskDto.class);
    }

    @Override
    public List<TaskDto> queryAll(TaskQueryParam query) {
        return ConvertUtil.convertList(taskMapper.selectList(QueryHelpMybatisPlus.getPredicate(query)), TaskDto.class);
    }

    @Override
    public Task getById(String id) {
        return taskMapper.selectById(id);
    }

    @Override
    // @Cacheable(key = "'id:' + #p0")
    public TaskDto findById(String id) {
        return ConvertUtil.convert(getById(id), TaskDto.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insert(TaskDto resources) {
        Task entity = ConvertUtil.convert(resources, Task.class);
        return taskMapper.insert(entity);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateById(TaskDto resources) {
        Task entity = ConvertUtil.convert(resources, Task.class);
        int ret = taskMapper.updateById(entity);
        // delCaches(resources.id);
        return ret;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeByIds(Set<String> ids) {
        // delCaches(ids);
        return taskMapper.deleteBatchIds(ids);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeById(String id) {
        Set<String> set = new HashSet<>(1);
        set.add(id);
        return this.removeByIds(set);
    }

    /*
    private void delCaches(String id) {
        redisUtils.delByKey(CACHE_KEY + "::id:", id);
    }

    private void delCaches(Set<String> ids) {
        for (String id: ids) {
            delCaches(id);
        }
    }*/

    /*
    @Override
    public void download(List<TaskDto> all, HttpServletResponse response) throws IOException {
      List<Map<String, Object>> list = new ArrayList<>();
      for (TaskDto task : all) {
        Map<String,Object> map = new LinkedHashMap<>();
              map.put("任务外部标识", task.getExtTaskId());
              map.put("任务号", task.getTaskCode());
              map.put("载具号", task.getVehicleCode());
              map.put("载具类型", task.getVehicleType());
              map.put("任务类型", task.getTaskType());
              map.put("任务状态", task.getTaskStatus());
              map.put("复合任务", task.getCompoundTask());
              map.put("复合任务数据", task.getCompoundTaskData());
              map.put("再次请求", task.getRequestAgain());
              map.put("再次请求成功", task.getRequestAgainSuccess());
              map.put("关联编号", task.getLinkNum());
              map.put("是否下发", task.getIsSend());
              map.put("物料类型", task.getMaterial());
              map.put("物料数量", task.getQuantity());
              map.put("任务优先级", task.getPriority());
              map.put("创建类型", task.getCreateType());
              map.put("完成类型", task.getFinishType());
              map.put("执行描述编码", task.getExecuteCode());
              map.put("执行描述信息", task.getExecuteMessage());
              map.put("起始点位编码", task.getStartPointCode());
              map.put("起始设备编码", task.getStartDeviceCode());
              map.put("放货点位编码", task.getPutPointCode());
              map.put("放货设备编码", task.getPutDeviceCode());
              map.put("起始点位编码2", task.getStartPointCode2());
              map.put("起始设备编码2", task.getStartDeviceCode2());
              map.put("目标点位编码", task.getNextPointCode());
              map.put("目标设备编码", task.getNextDeviceCode());
              map.put("目标点位编码2", task.getNextPointCode2());
              map.put("目标设备编码2", task.getNextDeviceCode2());
              map.put("排", task.getFromX());
              map.put("列", task.getFromY());
              map.put("层", task.getFromZ());
              map.put("排", task.getPutX());
              map.put("列", task.getPutY());
              map.put("层", task.getPutZ());
              map.put("排", task.getToX());
              map.put("列", task.getToY());
              map.put("层", task.getToZ());
              map.put("排2", task.getFromX2());
              map.put("列2", task.getFromY2());
              map.put("层2", task.getFromZ2());
              map.put("排2", task.getToX2());
              map.put("列2", task.getToY2());
              map.put("层2", task.getToZ2());
              map.put("路由方案名称", task.getRoutePlanName());
              map.put("路由方案编码", task.getRoutePlanCode());
              map.put("是否需要反馈上位系统", task.getIsNeedfeedback());
              map.put("空盘数量", task.getEmptypalletNum());
              map.put("备注", task.getRemark());
              map.put("是否启用", task.getIsActive());
              map.put("是否删除", task.getIsDelete());
              map.put("创建者", task.getCreateBy());
              map.put("创建时间", task.getCreateTime());
              map.put("修改者", task.getUpdateBy());
              map.put("修改时间", task.getUpdateTime());
              map.put("重量", task.getWeight());
              map.put("agv系统类型", task.getAgvSystemType());
              map.put("立库任务类型", task.getStorageTaskType());
              map.put("温度", task.getTemperature());
              map.put("时间", task.getOvenTime());
        list.add(map);
      }
      FileUtil.downloadExcel(list, response);
    }*/

    /**
     * 获取未完成任务
     *
     * @throws Exception
     */
    @Override
    public void autoInitial() throws Exception {
        Class var1 = TaskInstructionLock.class;
        synchronized (TaskInstructionLock.class) {
            this.reload();
        }
    }

    public synchronized void reload() {
        List list = this.queryAll("task_status <2 and is_delete =0 order by create_time");

        tasks = new CopyOnWriteArrayList<>(list);
    }

    @Override
    public List queryAll(String whereJson) {
        List<Task> taskList = new LambdaQueryChainWrapper<>(taskMapper)
                .lt(Task::getTask_status, "2")
                .eq(Task::getIs_delete, "0")
                .orderByDesc(Task::getCreate_time)
                .list();
        return ConvertUtil.convertList(taskList, TaskDto.class);
    }

    @Override
    public Map<String, Object> queryAll(Map whereJson, Pageable page) {

        String task_code = (String) whereJson.get("task_code");
        String vehicle_code = (String) whereJson.get("vehicle_code");
        String material_type = (String) whereJson.get("material_type");
        String status = (String) whereJson.get("status");
        String point_code = (String) whereJson.get("point_code");
        String is_over = (String) whereJson.get("is_over");

        IPage<Task> queryPage = PageUtil.toMybatisPage(page);
        LambdaQueryWrapper<Task> wrapper = new LambdaQueryWrapper<>();
        if (!StrUtil.isEmpty(task_code)) {
            wrapper.eq(Task::getTask_code, task_code);
        }
        if (!StrUtil.isEmpty(vehicle_code)) {
            wrapper.eq(Task::getVehicle_code, vehicle_code);
        }
        if (!StrUtil.isEmpty(material_type)) {
            wrapper.eq(Task::getMaterial, material_type);
        }
        if (!StrUtil.isEmpty(status)) {
            wrapper.eq(Task::getTask_status, status);
        }
        if (!StrUtil.isEmpty(point_code)) {
            wrapper.and(task -> task.like(Task::getStart_point_code, point_code).or().like(Task::getNext_point_code, point_code));
        }
        if (!StrUtil.isEmpty(is_over)) {
            if (StrUtil.equals(is_over, "1")) {
                wrapper.ge(Task::getTask_status, 2);
            } else {
                wrapper.lt(Task::getTask_status, 2);
            }
        }
        if (StrUtil.isEmpty(is_over) && StrUtil.isEmpty(status)) {
            wrapper.lt(Task::getTask_status, 2);
        }
        IPage<Task> taskPage = taskMapper.selectPage(queryPage, wrapper);
        final JSONObject json = (JSONObject) JSON.toJSON(ConvertUtil.convertPage(taskPage, TaskDto.class));
        return json;
    }

    @Override
    public Map<String, Object> queryAllByCache(Map whereJson, Pageable page) {
        this.reload();
        String task_code = (String) whereJson.get("task_code");
        String vehicle_code = (String) whereJson.get("vehicle_code");
        String material_type = (String) whereJson.get("material_type");
        String status = (String) whereJson.get("status");
        String point_code = (String) whereJson.get("point_code");
        String is_over = (String) whereJson.get("is_over");
        String task_type = (String) whereJson.get("task_type");
        List<TaskDto> taskList = new ArrayList();

        synchronized (TaskServiceImpl.class) {
            Iterator<TaskDto> it = tasks.iterator();
            while (it.hasNext()) {
                TaskDto task = it.next();
                if ("1".equals(is_over) && Integer.valueOf(task.getTask_status()) < 2) {
                    continue;
                }
                if (!"1".equals(is_over) && Integer.valueOf(task.getTask_status()) >= 2) {
                    continue;
                }
                if (!ObjectUtil.isEmpty(task_code) && !task.getTask_code().contains(task_code)) {
                    continue;
                }
                if (!ObjectUtil.isEmpty(status) && !task.getTask_status().equals(status)) {
                    continue;
                }
                if (!ObjectUtil.isEmpty(vehicle_code) && !task.getVehicle_code().contains(vehicle_code)) {
                    continue;
                }
                if (!ObjectUtil.isEmpty(material_type) && !task.getMaterial().equals(material_type)) {
                    continue;
                }
                if (!ObjectUtil.isEmpty(point_code)
                        && !(task.getStart_point_code().contains(point_code)
                        || task.getNext_point_code().contains(point_code))) {
                    continue;
                }
                if (!ObjectUtil.isEmpty(task_type) && !task.getTask_type().equals(task_type)) {
                    continue;
                }
                taskList.add(task);
            }

            // 按照创建时间排序
            taskList =
                    taskList.stream()
                            .sorted(
                                    (task1, task2) ->
                                            DateUtil.compare(
                                                    DateUtil.parseDate(task1.getCreate_time()),
                                                    DateUtil.parse(task2.getCreate_time())))
                            .collect(Collectors.toList());

        }

        Integer currentPageNumber = page.getPageNumber() + 1;
        Integer pageMaxSize = page.getPageSize();
        List<TaskDto> taskDtoList =
                taskList.stream()
                        .skip((currentPageNumber - 1) * pageMaxSize)
                        .limit(pageMaxSize)
                        .collect(Collectors.toList());
        JSONObject jo = new JSONObject();
        jo.put("content", taskDtoList);
        jo.put("totalElements", taskList.size());
        return jo;

    }

    @Override
    public Map<String, Object> getAll(Map whereJson, Pageable page) {
        String task_code = (String) whereJson.get("task_code");
        String vehicle_code = (String) whereJson.get("vehicle_code");
        String material_type = (String) whereJson.get("material_type");
        String status = (String) whereJson.get("status");
        String point_code = (String) whereJson.get("point_code");
        String create_time = (String) whereJson.get("createTime");
        String end_time = (String) whereJson.get("end_time");

        IPage<Task> queryPage = PageUtil.toMybatisPage(page);
        LambdaQueryWrapper<Task> wrapper = new LambdaQueryWrapper<>();
//        wrapper.eq(InstructionMybatis::getIs_delete,"0");
        if (!StrUtil.isEmpty(task_code)) {
            wrapper.eq(Task::getTask_code, task_code);
        }
        if (!StrUtil.isEmpty(vehicle_code)) {
            wrapper.like(Task::getVehicle_code, vehicle_code);
        }
        if (!StrUtil.isEmpty(material_type)) {
            wrapper.eq(Task::getMaterial, material_type);
        }
        if (!StrUtil.isEmpty(status)) {
            wrapper.eq(Task::getTask_status, status);
        }
        if (!StrUtil.isEmpty(point_code)) {
            wrapper.and(task -> task.like(Task::getStart_point_code, point_code).or().like(Task::getNext_point_code, point_code));
        }
        if (!StrUtil.isEmpty(create_time) && !StrUtil.isEmpty(end_time)) {
            wrapper.between(Task::getCreate_time, create_time, end_time);
        }
        IPage<Task> taskPage = taskMapper.selectPage(queryPage, wrapper);
        final JSONObject json = (JSONObject) JSON.toJSON(ConvertUtil.convertPage(taskPage, TaskDto.class));
        JSONArray array = json.getJSONArray("content");
        int totalElements = (int) json.getLongValue("totalElements");
        JSONArray arr = new JSONArray();
        for (int i = 0; i < array.size(); i++) {
            JSONObject jsonObject = (JSONObject) array.get(i);
            jsonObject.put("hasChildren", true);
            arr.add(jsonObject);
        }
        JSONObject jo = new JSONObject();
        jo.put("content", arr);
        jo.put("totalElements", totalElements);
        return jo;
    }

    @Override
    public List<TaskDto> queryAll(Map whereJson) {

        List<Task> taskList = new LambdaQueryChainWrapper<>(taskMapper)
                .list();
        return ConvertUtil.convertList(taskList, TaskDto.class);
    }

//    @Override
//    public TaskDto findById(String task_id) {
//        WQLObject wo = WQLObject.getWQLObject("acs_task");
//        JSONObject json = wo.query("task_id ='" + task_id + "'").uniqueResult(0);
//        final TaskDto obj = json.toJavaObject(TaskDto.class);
//        return obj;
//    }

    @Override
    public List<TaskDto> queryAllUnfinished(Map whereJson) {
//        WQLObject wo = WQLObject.getWQLObject("acs_task");
//        JSONArray arr = wo.query("task_status < 2 ").getResultJSONArray(0);
//        List<TaskDto> list = arr.toJavaList(TaskDto.class);
//        return list;
        List<Task> taskList = new LambdaQueryChainWrapper<>(taskMapper)
                .lt(Task::getTask_status, "2")
                .list();
        return ConvertUtil.convertList(taskList, TaskDto.class);
    }

    @Override
    public TaskDto findByCode(String code) {
//        WQLObject wo = WQLObject.getWQLObject("acs_task");
//        JSONObject json = wo.query("task_code ='" + code + "'").uniqueResult(0);
//        final TaskDto obj = json.toJavaObject(TaskDto.class);
//        return obj;
        Task task = new LambdaQueryChainWrapper<>(taskMapper)
                .eq(Task::getTask_code, code)
                .one();
        return ConvertUtil.convert(task, TaskDto.class);
    }

    @Override
    public List<TaskDto> queryTaskByDeviceCode(String device_code) {
        List<TaskDto> list = new ArrayList<>();
        Iterator<TaskDto> iterator = tasks.iterator();
        while (iterator.hasNext()) {
            TaskDto task = iterator.next();
            if (task.getStart_device_code().equals(device_code)
                    && StrUtil.equals(task.getTask_status(), "0")) {
                list.add(task);
            }
        }
        return list;
    }

    @Override
    public List<TaskDto> queryTaskByStartDeviceCode(String start_device_code) {
        List<TaskDto> list = new ArrayList<>();
        Iterator<TaskDto> iterator = tasks.iterator();
        while (iterator.hasNext()) {
            TaskDto task = iterator.next();
            if (!StrUtil.equals(task.getTask_type(), "6")) {
                continue;
            }
            if ((task.getStart_device_code().equals(start_device_code)
                    || task.getStart_device_code2().equals(start_device_code))
                    && StrUtil.equals(task.getTask_status(), "0")) {
                list.add(task);
            }
        }
        return list;
    }

    @Override
    public List<TaskDto> queryTaskByBackDeviceCode(String back_start_device_code) {
        List<TaskDto> list = new ArrayList<>();
        Iterator<TaskDto> iterator = tasks.iterator();
        while (iterator.hasNext()) {
            TaskDto task = iterator.next();
            if (!StrUtil.equals(task.getTask_type(), "6")) {
                continue;
            }
            if (task.getStart_device_code().equals(back_start_device_code)
                    && StrUtil.equals(task.getTask_status(), "0")) {
                list.add(task);
            }
        }
        return list;
    }

    @Override
    public List<TaskDto> queryTaskByDeviceCodeAndStatus(String device_code) {
        List<TaskDto> list = new ArrayList<>();
        Iterator<TaskDto> iterator = tasks.iterator();
        while (iterator.hasNext()) {
            TaskDto task = iterator.next();
            if (task.getStart_device_code().equals(device_code)
                    && StrUtil.equals(task.getTask_status(), "1")) {
                Instruction instruction = instructionService.findByTaskcodeAndStatus(task.getTask_code());
                if (ObjectUtil.isNotEmpty(instruction)) {
                    list.add(task);
                }
            }
        }
        return list;
    }

    public List<TaskDto> queryTaskByStartAndIntStatus(String head_start_device_code) {
        List<TaskDto> list = new ArrayList<>();
        Iterator<TaskDto> iterator = tasks.iterator();
        while (iterator.hasNext()) {
            TaskDto task = iterator.next();
            if (!StrUtil.equals(task.getTask_type(), "6")) {
                continue;
            }
            if ((task.getStart_device_code().equals(head_start_device_code)
                    || task.getStart_device_code2().equals(head_start_device_code))
                    && StrUtil.equals(task.getTask_status(), "1")) {
                Instruction instruction = instructionService.findByTaskcodeAndStatus(task.getTask_code());
                if (ObjectUtil.isNotEmpty(instruction)) {
                    list.add(task);
                }
            }
        }
        return list;
    }

    public List<TaskDto> queryTaskByNextAndIntStatus(String back_start_device_code) {
        List<TaskDto> list = new ArrayList<>();
        Iterator<TaskDto> iterator = tasks.iterator();
        while (iterator.hasNext()) {
            TaskDto task = iterator.next();
            if (!StrUtil.equals(task.getTask_type(), "6")) {
                continue;
            }
            if ((task.getStart_device_code().equals(back_start_device_code))
                    && StrUtil.equals(task.getTask_status(), "1")) {
                Instruction instruction = instructionService.findByTaskcodeAndStatus(task.getTask_code());
                if (ObjectUtil.isNotEmpty(instruction)) {
                    list.add(task);
                }
            }
        }
        return list;
    }

    @Override
    public TaskDto queryTaskByLinkNum(String link_num) {
        return null;
    }

    @Override
    public List<TaskDto> queryByStauts(String status) {
//        WQLObject wo = WQLObject.getWQLObject("acs_task");
//        JSONArray arr = wo.query("task_status = '" + status + "'").getResultJSONArray(0);
//        List<TaskDto> list = arr.toJavaList(TaskDto.class);
//        return list;
        List<Task> taskList = new LambdaQueryChainWrapper<>(taskMapper)
                .eq(Task::getTask_status, status)
                .list();
        return ConvertUtil.convertList(taskList, TaskDto.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void create(TaskDto dto) throws Exception {
        dto = foramte(dto);
        if (!StrUtil.isEmpty(dto.getVehicle_code())) {
            TaskDto vehicle_dto = this.findByContainer(dto.getVehicle_code());
            if (vehicle_dto != null) {
                throw new BadRequestException("已存在该载具号的任务!");
            }
        }
        String currentUsername = SecurityUtils.getCurrentUsername();
        String now = DateUtil.now();
        String task_uuid = dto.getTask_id();
        if (StrUtil.isEmpty(task_uuid)) {
            dto.setTask_id(IdUtil.simpleUUID());
        }
        String task_code = dto.getTask_code();
        if (StrUtil.isEmpty(task_code)) {
            task_code = CodeUtil.getNewCode("TASK_NO");
            task_code = "-" + task_code;
        }
        String start_point_code = dto.getStart_point_code();
        String next_point_code = dto.getNext_point_code();
        String start_device_code = dto.getStart_device_code();
        String next_device_code = dto.getNext_device_code();
        String route_plan_code = dto.getRoute_plan_code();
        dto.setCreate_by("auto");
        dto.setUpdate_by(currentUsername);
        dto.setUpdate_time(now);
        dto.setCreate_time(now);
        dto.setTask_code(task_code);
        dto.setRoute_plan_code(route_plan_code);
        dto.setTask_status("0");
        dto.setStart_device_code2(dto.getStart_point_code2());
        dto.setNext_device_code2(dto.getNext_point_code2());

        if (StrUtil.isEmpty(dto.getPriority())) {
            dto.setPriority("1");
        }
        String plan_code = dto.getRoute_plan_code();
        // 判断起点终点设备类型
        String startDeviceType = deviceAppService.findDeviceTypeByCode(dto.getStart_device_code());
        String nextDeviceType = deviceAppService.findDeviceTypeByCode(dto.getNext_device_code());
        //        if (routelineserver
        //                .getShortPathLines(dto.getStart_device_code(), dto.getNext_device_code(), plan_code)
        //                .size()
        //                == 0) {
        //            throw new Exception(dto.getStart_point_code() + "->" + dto.getNext_point_code() + "路由不通!");
        //        }
        String createTaskCheck = paramService.findByCode(AcsConfig.CREATETASKCHECK).getValue();
        DeviceService deviceService = SpringContextHolder.getBean(DeviceServiceImpl.class);
        DeviceAppService appService = SpringContextHolder.getBean(DeviceAppServiceImpl.class);
        Device nextdevice = appService.findDeviceByCode(next_device_code);
        Device startdevice = appService.findDeviceByCode(start_device_code);
        dto.setMaterial(startdevice.getMaterial_type());
        if (StrUtil.equals(createTaskCheck, "1")) {
            // 判断起点为输送设备
            if (StrUtil.equals(DeviceType.conveyor.toString(), startDeviceType)) {
            }

            if (StrUtil.equals(DeviceType.conveyor.toString(), nextDeviceType)) {
            }
        } else {
            // 判断起点为输送设备
            if (StrUtil.equals(DeviceType.conveyor.toString(), startDeviceType)) {
            }

            if (StrUtil.equals(DeviceType.conveyor.toString(), nextDeviceType)) {
                //                if (nextdevice.getDeviceDriver() instanceof
                // StandardOrdinarySiteDeviceDriver) {
                //                    standardOrdinarySiteDeviceDriver = (StandardOrdinarySiteDeviceDriver)
                // nextdevice.getDeviceDriver();
                //                    if (nextdevice.getHas_goods() != 0) {
                //                        throw new Exception("任务终点需满足无货!");
                //                    }
                //                }

                JSONObject jo = new JSONObject();
                JSONObject jo2 = new JSONObject();
                if (!StrUtil.isEmpty(dto.getMaterial())) {
                    if (!StrUtil.equals(dto.getMaterial(), "1")) {
                        jo.put("hasGoodStatus", "2");
                        jo.put("material_type", dto.getMaterial());
                    } else {
                        jo.put("hasGoodStatus", "1");
                        jo.put("material_type", "1");
                    }

                } else {
                    jo.put("hasGoodStatus", "1");
                    jo.put("material_type", "1");
                }
                jo.put("device_code", dto.getStart_device_code());
                jo.put("quantity", dto.getQuantity());
                jo.put("remark", dto.getRemark());
                jo.put("batch", startdevice.getBatch());
                jo.put("islock", "true");
                deviceService.changeDeviceStatus(jo);
                Device deviceByCode = deviceAppService.findDeviceByCode(dto.getNext_device_code());
                jo2.put("device_code", dto.getNext_device_code());
                jo2.put("hasGoodStatus", deviceByCode.getHas_goods());
                jo2.put("quantity", deviceByCode.getQuantity());
                jo2.put("remark", deviceByCode.getRemark());
                jo2.put("material_type", deviceByCode.getMaterial_type());
                jo2.put("batch", deviceByCode.getBatch());
                jo2.put("islock", "true");
                deviceService.changeDeviceStatus(jo2);
            }
        }
        Task entity = ConvertUtil.convert(dto, Task.class);
        taskMapper.insert(entity);
        synchronized (TaskServiceImpl.class) {
            System.out.println("-------------------" + dto.getTask_code());
            System.out.println("-------------1" + tasks.size());

            tasks.add(dto);
            System.out.println("-------------2" + tasks.size());

        }
    }

    /**
     * 常规任务保存
     *
     * @param /
     * @throws Exception
     */
    @Override
    public void ordinaryTaskCreate(JSONObject json) throws Exception {
        JSONArray array = json.getJSONArray("data");

        if (array.size() == 0) {
            throw new RuntimeException("请选择起点");
        }
        for (int i = 0; i < array.size(); i++) {
            JSONObject arrjo = array.getJSONObject(i);
            String material_type = arrjo.getString("material_type");
            String quantity = arrjo.getString("quantity");
            String remark = arrjo.getString("remark");
            TaskDto dto = new TaskDto();
            Map whereJson = (Map) array.get(i);

            // String device_code = (String) whereJson.get("device_code");
            String device_code = MapUtil.getStr(whereJson, "device_code");
            dto.setRoute_plan_code("one");
            String next_device_code = "";
            String plan_uuid =
                    new LambdaQueryChainWrapper<>(routePlanMapper)
                            .eq(RoutePlan::getPlan_code, dto.getRoute_plan_code())
                            .one().getPlan_uuid();
            JSONArray ja = routelineserver.queryNextLine(device_code, plan_uuid);
            for (int j = 0; j < ja.size(); j++) {
                JSONObject jo = (JSONObject) ja.get(j);
                next_device_code = jo.get("next_device_code").toString();
            }
            if (ObjectUtil.isNotEmpty(this.findByStartCode(device_code))) {
                throw new BadRequestException("已存在该起点的任务!");
            }
            if (StrUtil.equals(material_type, "") || StrUtil.equals(quantity, "")) {
                throw new RuntimeException("请填写物料信息!");
            }
            dto.setStart_device_code(device_code);
            dto.setStart_point_code(device_code);
            dto.setNext_device_code(next_device_code);
            dto.setNext_point_code(next_device_code);
            dto.setRemark(remark);
            dto.setMaterial(material_type);
            create(dto);
        }
    }

    /**
     * 特殊任务保存
     *
     * @param /
     * @throws Exception
     */
    @Override
    public void specialTaskCreate(JSONObject json) throws Exception {

        JSONArray array = json.getJSONArray("data1");
        JSONArray array2 = json.getJSONArray("data2");
        JSONArray array3 = json.getJSONArray("data3");
        if (array.size() != 0 && array3.size() != 0) {
            throw new RuntimeException("只能选择一个终点");
        }

        for (int i = 0; i < array2.size(); i++) {
            JSONObject arrjo = array2.getJSONObject(i);
            String material_type = arrjo.getString("material_type");
            String quantity = arrjo.getString("quantity");
            String remark = arrjo.getString("remark");
            TaskDto dto = new TaskDto();
            Map whereJson;
            Map whereJson2;
            Map whereJson3;
            if (array.size() != 0) {
                whereJson = (Map) array.get(i);
            } else {
                whereJson = null;
            }
            if (array2.size() != 0) {
                whereJson2 = (Map) array2.get(i);
            } else {
                whereJson2 = null;
            }
            if (array3.size() != 0) {
                whereJson3 = (Map) array3.get(i);
            } else {
                whereJson3 = null;
            }
            String start_device_code = MapUtil.getStr(whereJson2, "device_code");
            String next_device_code = "";
            if (ObjectUtil.isEmpty(whereJson)) {
                next_device_code = MapUtil.getStr(whereJson3, "device_code");
            } else {
                next_device_code = MapUtil.getStr(whereJson, "device_code");
            }

            if (ObjectUtil.isNotEmpty(this.findByStartCode(start_device_code))
                    || ObjectUtil.isNotEmpty(this.findByNextCode(next_device_code))) {
                throw new BadRequestException("已存在该起点或终点的任务!");
            }
            if (StrUtil.equals(material_type, "") || StrUtil.equals(quantity, "")) {
                throw new RuntimeException("请填写物料信息!");
            }
            dto.setRoute_plan_code("two");
            dto.setStart_device_code(start_device_code);
            dto.setStart_point_code(start_device_code);
            dto.setNext_device_code(next_device_code);
            dto.setNext_point_code(next_device_code);
            dto.setRemark(remark);
            dto.setMaterial(material_type);
            create(dto);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(TaskDto dto) {

        TaskDto entity = this.findById(dto.getTask_id());
        if (entity == null) {
            throw new BadRequestException("被删除或无权限，操作失败!");
        }

        String currentUsername = SecurityUtils.getCurrentUsername();
        String now = DateUtil.now();
        dto.setUpdate_time(now);
        dto.setUpdate_by(currentUsername);

        Task task = ConvertUtil.convert(dto, Task.class);
        taskMapper.updateById(task);

        Iterator<TaskDto> iterator = tasks.iterator();
        //      while (iterator.hasNext()) {
        //        TaskDto task = iterator.next();
        //        if (task.getTask_code().equals(dto.getTask_code())) {
        //          iterator.remove();
        //        }
        //      }
        removeByCodeFromCache(entity.getTask_code());
        if (StrUtil.equals(dto.getTask_status(), "0") || StrUtil.equals(dto.getTask_status(), "1")) {
            tasks.add(dto);
        }
        // 判断是否为WMS下发的任务，如果是反馈任务状态给WMS
        String hasWms = paramService.findByCode(AcsConfig.HASWMS).getValue();
        if (!StrUtil.startWith(dto.getTask_code(), "-") && StrUtil.equals(hasWms, "1")) {
            TaskFeedbackDto feefbackdto = taskFeedbackService.findByCode(entity.getTask_code());
            FeedBackTaskStatusRequest request = new FeedBackTaskStatusRequest();
            request.setTask_code(entity.getTask_code());
            request.setTask_id(entity.getExt_task_id());
            request.setTask_status(dto.getTask_status());
            request.setRequest_medthod_code(RequestMethodEnum.feedback_task_status.getCode());
            request.setRequest_medthod_name(RequestMethodEnum.feedback_task_status.getName());
            boolean flag = false;
            String resp = null;
            //反馈任务状态
            sendTaskStatus(request);
        }

    }


    private void sendTaskStatus(FeedBackTaskStatusRequest request) {
        CompletableFuture<String> future = new CompletableFuture<>();
        EXECUTOR.submit(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    log.info("任务号" + request.getTask_code() + "开始反馈wcs任务完成状态" + request.getTask_status());
                    String resp = acstowmsService.feedTaskStatus(request);
                    JSONObject result = JSONObject.parseObject(resp);
                    if ("200".equals("200")) {
                        log.info("任务号" + request.getTask_code() + "开始反馈wcs任务完成状态" + "成功。");
                        break;
                    } else {
                        log.info("任务号" + request.getTask_code() + "开始反馈wcs任务完成状态" + "失败,服务器响应的失败原因为：" + result.getString("message"));
                    }
                }
                future.complete("反馈wcs任务完成状态");
            } catch (Exception e) {
                future.completeExceptionally(e);
            }
        });
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteAll(String[] ids) throws Exception {
        for (String task_id : ids) {
            this.cancel(task_id);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void finish(String id) {
        TaskDto entity = this.findById(id);
        if (entity == null) throw new BadRequestException("被删除或无权限，操作失败!");
        InstructionService instructionservice = SpringContextHolder.getBean("instructionServiceImpl");
        InstructionDto instdto = instructionservice.findByTaskid(id, "instruction_status <2 ");
        if (instdto != null) throw new BadRequestException("有指令未完成!");
        String currentUsername = SecurityUtils.getCurrentUsername();
        String now = DateUtil.now();
        entity.setUpdate_time(now);
        entity.setUpdate_by(currentUsername);
        entity.setTask_status("2");

        Task task = ConvertUtil.convert(entity, Task.class);
        taskMapper.updateById(task);

        removeByCodeFromCache(entity.getTask_code());
        // 判断是否为WMS下发的任务，如果是反馈任务状态给WMS
        String hasWms = paramService.findByCode(AcsConfig.HASWMS).getValue();
        if (!StrUtil.startWith(entity.getTask_code(), "-") && StrUtil.equals(hasWms, "1")) {
            FeedBackTaskStatusRequest request = new FeedBackTaskStatusRequest();
            request.setTask_id(entity.getExt_task_id());
            request.setTask_code(entity.getTask_code());
            request.setTask_status(entity.getTask_status());
            request.setRequest_medthod_code(RequestMethodEnum.feedback_task_status.getCode());
            request.setRequest_medthod_name(RequestMethodEnum.feedback_task_status.getName());
            boolean flag = false;
            String resp = null;
            //反馈任务状态
            sendTaskStatus(request);

        }
        // 如果属于先知AGV，关闭运单序列
        if (StrUtil.equals(paramService.findByCode(AcsConfig.AGVTYPE).getValue(), "3")) {
            try {
                agvService.markComplete(entity.getTask_code());
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancel(String id) throws Exception {
        TaskDto entity = this.findById(id);
        if (entity == null) {
            throw new BadRequestException("被删除或无权限，操作失败!");
        }
        try {
            InstructionService instructionservice = SpringContextHolder.getBean("instructionServiceImpl");
            instructionservice.cancel(id);
        } catch (Exception e) {
            throw new BadRequestException(e.getMessage());
        }
        String currentUsername = SecurityUtils.getCurrentUsername();
        String now = DateUtil.now();
        entity.setUpdate_time(now);
        entity.setUpdate_by(currentUsername);
        entity.setTask_status("3");
        Task task = ConvertUtil.convert(entity, Task.class);
        taskMapper.updateById(task);
        //    synchronized (TaskServiceImpl.class){
        //      Iterator<TaskDto> it = tasks.iterator();
        //      // 清理缓存
        //      while (it.hasNext()) {
        //        TaskDto taskDto = it.next();
        //        if (taskDto.getTask_id().equals(id)) {
        //          tasks.remove(taskDto);
        //        }
        //      }}
        removeByCodeFromCache(entity.getTask_code());
        // 判断是否为WMS下发的任务，如果是反馈任务状态给WMS
        String hasWms = paramService.findByCode(AcsConfig.HASWMS).getValue();
        if (!StrUtil.startWith(entity.getTask_code(), "-") && StrUtil.equals(hasWms, "1")) {
            FeedBackTaskStatusRequest request = new FeedBackTaskStatusRequest();
            request.setTask_id(entity.getExt_task_id());
            request.setTask_code(entity.getTask_code());
            request.setTask_status(entity.getTask_status());
            request.setRequest_medthod_code(RequestMethodEnum.feedback_task_status.getCode());
            request.setRequest_medthod_name(RequestMethodEnum.feedback_task_status.getName());
            boolean flag = false;
            String resp = null;
            //反馈任务状态
            sendTaskStatus(request);
        }
        List<RouteLineDto> shortPathsList =
                routeLineService.getShortPathLines(
                        entity.getStart_device_code(),
                        entity.getNext_device_code(),
                        entity.getRoute_plan_code());
        if (ObjectUtil.isNotEmpty(shortPathsList)) {
            // != 0 为agv任务
            if (!StrUtil.equals(shortPathsList.get(0).getType(), "0")) {
                if (StrUtil.equals(paramService.findByCode(AcsConfig.AGVTYPE).getValue(), "3")) {
                    agvService.markComplete(entity.getTask_code());
                }
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancelNoSendWms(String id) throws Exception {
        TaskDto entity = this.findById(id);
        if (entity == null) {
            throw new BadRequestException("被删除或无权限，操作失败!");
        }
        InstructionService instructionservice = SpringContextHolder.getBean("instructionServiceImpl");
        InstructionDto instdto = instructionservice.findByTaskid(id, "instruction_status <2 ");
        if (instdto != null) {
            throw new BadRequestException("有指令未完成!");
        }
        String currentUsername = SecurityUtils.getCurrentUsername();
        String now = DateUtil.now();
        entity.setUpdate_time(now);
        entity.setUpdate_by(currentUsername);
        entity.setTask_status("3");


        Task task = ConvertUtil.convert(entity, Task.class);
        taskMapper.updateById(task);


        removeByCodeFromCache(entity.getTask_code());

        List<RouteLineDto> shortPathsList =
                routeLineService.getShortPathLines(
                        entity.getStart_device_code(),
                        entity.getNext_device_code(),
                        entity.getRoute_plan_code());
        String type = shortPathsList.get(0).getType();

    }

    @Override
    public Instruction createTemporaryInst(TaskDto acsTask) {
        if (acsTask == null) {
            throw new BadRequestException("被删除或无权限，操作失败!");
        }
        acsTask = foramte(acsTask);
        ISysParamService paramService = SpringContextHolder.getBean(ISysParamService.class);
        DeviceAppService appService = SpringContextHolder.getBean(DeviceAppServiceImpl.class);
        InstructionService instructionservice = SpringContextHolder.getBean("instructionServiceImpl");
        //        InstructionDto inst = instructionservice.findByTaskid(acsTask, "instruction_status < 2
        // ");
        //        if (inst != null) {
        //            throw new BadRequestException("有指令未完成!");
        //        }

        String taskid = acsTask.getTask_id();
        String taskcode = acsTask.getTask_code();
        String vehiclecode = acsTask.getVehicle_code();
        String priority = acsTask.getPriority();
        String start_point_code = acsTask.getStart_point_code();
        String start_device_code = acsTask.getStart_device_code();
        String route_plan_code = acsTask.getRoute_plan_code();
        String vehicleType = acsTask.getVehicle_type();
        // 是否复合任务 =0非复合任务
        String compound_task = acsTask.getCompound_task();
        String next_point_code = acsTask.getNext_point_code();
        String next_device_code = acsTask.getNext_device_code();
        String start_point_code2 = acsTask.getStart_point_code2();
        String next_point_code2 = acsTask.getNext_point_code2();
        String agv_system_type = acsTask.getAgv_system_type();
        String task_type = acsTask.getTask_type();
        String from_x = acsTask.getFrom_x();
        String from_y = acsTask.getFrom_y();
        String from_z = acsTask.getFrom_z();
        String to_x = acsTask.getTo_x();
        String to_y = acsTask.getTo_y();
        String to_z = acsTask.getTo_z();

        /** 开始平均分解校验 */
        String this_device_code =
                this.queryAssignedByDevice(acsTask.getStart_device_code(), acsTask.getNext_device_code());
        if (StrUtil.isEmpty(this_device_code)) {
            List<RouteLineDto> shortPathsList =
                    routeLineService.getShortPathLines(
                            start_device_code, acsTask.getNext_device_code(), route_plan_code);
            RouteLineDto routeLineDto = shortPathsList.get(0);
            String path = routeLineDto.getPath();
            String type = routeLineDto.getType();
            String[] str = path.split("->");
            List<String> pathlist = Arrays.asList(str);
            int index = 0;
            for (int m = 0; m < pathlist.size(); m++) {
                if (pathlist.get(m).equals(start_device_code)) {
                    index = m + 1;
                    break;
                }
            }
            next_device_code = pathlist.get(index);
        } else {
            next_device_code = this_device_code;
        }

        if (StrUtil.equals(appService.findDeviceTypeByCode(next_device_code), "storage")) {
            next_point_code = next_device_code + "-" + acsTask.getTo_y() + "-" + acsTask.getTo_z();
        } else {
            next_point_code = next_device_code;
        }

        Instruction instdto = new Instruction();
        if (StrUtil.isEmpty(instdto.getInstruction_code())) {
            instdto.setInstruction_code(CodeUtil.getNewCode("INSTRUCT_NO"));
        }
        instdto.setInstruction_type(task_type);
        instdto.setInstruction_id(IdUtil.simpleUUID());
        instdto.setRoute_plan_code(route_plan_code);
        instdto.setRemark(acsTask.getRemark());
        instdto.setMaterial(acsTask.getMaterial());
        instdto.setQuantity(acsTask.getQuantity());
        instdto.setTask_id(taskid);
        instdto.setTask_code(taskcode);
        instdto.setVehicle_code(vehiclecode);
        String now = DateUtil.now();
        instdto.setCreate_time(now);
        instdto.setCreate_by("auto");
        instdto.setStart_device_code(start_device_code);
        instdto.setNext_device_code(next_device_code);
        instdto.setStart_point_code(start_point_code);
        instdto.setNext_point_code(next_point_code);
        instdto.setPriority(priority);
        instdto.setInstruction_status("0");
        instdto.setExecute_device_code(start_point_code);
        instdto.setVehicle_type(vehicleType);
        instdto.setStart_point_code2(start_point_code2);
        instdto.setStart_device_code2(start_point_code2);
        instdto.setNext_device_code2(next_point_code2);
        instdto.setNext_point_code2(next_point_code2);
        instdto.setAgv_system_type(agv_system_type);
        instdto.setFrom_x(from_x);
        instdto.setFrom_y(from_y);
        instdto.setFrom_z(from_z);
        instdto.setTo_x(to_x);
        instdto.setTo_y(to_y);
        instdto.setTo_z(to_z);

        // 判断agv系统
        // 1、1楼叉车系统
        // 2、2楼1区域AGV系统
        // 3、2楼2区域AGV系统
        if (!StrUtil.equals(agv_system_type, "1")) {
            // task_type
            // 1、生箔； Itype=1:取空，取满，放空，放满；
            // 2、分切  Itype=3取满、取空、放满、放空；
            // 3、普通任务 Itype=2:取货、放货；
            // 4、叉车任务
            // 5、输送任务
            // 6、行架
            // 7、立库
            if (StrUtil.equals(task_type, "1")) {
                instdto.setAgv_inst_type("1");
            } else if (StrUtil.equals(task_type, "3")) {
                instdto.setAgv_inst_type("2");
            } else if (StrUtil.equals(task_type, "2")) {
                instdto.setAgv_inst_type("3");
            }
        } else {
            instdto.setAgv_inst_type("4");
        }
        return instdto;
    }

    @Override
    public Instruction createInst(String ids) throws Exception {
        TaskDto acsTask = this.findById(ids);
        if (acsTask == null) {
            throw new BadRequestException("被删除或无权限，操作失败!");
        }
        //只有执行中的任务才能创建指令
        if (!"1".equals(acsTask.getTask_status())) {
            throw new BadRequestException("任务未执行，不能创建指令!");
        }
        DeviceAppService appService = SpringContextHolder.getBean(DeviceAppServiceImpl.class);
        InstructionService instructionservice = SpringContextHolder.getBean("instructionServiceImpl");
        InstructionDto inst = instructionservice.findByTaskid(ids, "instruction_status < 2 ");
        if (inst != null) {
            throw new BadRequestException("有指令未完成!");
        }
        String taskid = acsTask.getTask_id();
        String taskcode = acsTask.getTask_code();
        String vehiclecode = acsTask.getVehicle_code();
        String priority = acsTask.getPriority();
        String start_point_code = acsTask.getStart_point_code();
        String start_device_code = acsTask.getStart_device_code();
        String route_plan_code = acsTask.getRoute_plan_code();
        String vehicleType = acsTask.getVehicle_type();
        // 是否复合任务 =0非复合任务
        String compound_task = acsTask.getCompound_task();
        String next_point_code = acsTask.getNext_point_code();
        String next_device_code = acsTask.getNext_device_code();
        String start_point_code2 = acsTask.getStart_point_code2();
        String next_point_code2 = acsTask.getNext_point_code2();
        String agv_system_type = acsTask.getAgv_system_type();
        String task_type = acsTask.getTask_type();
        /** 开始平均分解校验 */
        //        String this_device_code =
        //                this.queryAssignedByDevice(acsTask.getStart_device_code(), acsTask.getNext_device_code());
        //        if (StrUtil.isEmpty(this_device_code)) {
        //            List<RouteLineDto> shortPathsList =
        //                    routeLineService.getShortPathLines(
        //                            start_device_code, acsTask.getNext_device_code(), route_plan_code);
        //            RouteLineDto routeLineDto = shortPathsList.get(0);
        //            String path = routeLineDto.getPath();
        //            String type = routeLineDto.getType();
        //            String[] str = path.split("->");
        //            List<String> pathlist = Arrays.asList(str);
        //            int index = 0;
        //            for (int m = 0; m < pathlist.size(); m++) {
        //                if (pathlist.get(m).equals(start_device_code)) {
        //                    index = m + 1;
        //                    break;
        //                }
        //            }
        //            next_device_code = pathlist.get(index);
        //        } else {
        //            next_device_code = this_device_code;
        //        }

        if (StrUtil.equals(appService.findDeviceTypeByCode(next_device_code), "storage")) {
            next_point_code = next_device_code + "-" + acsTask.getTo_y() + "-" + acsTask.getTo_z();
        } else {
            next_point_code = next_device_code;
        }
        Instruction instdto = new Instruction();
        instdto.setInstruction_type(task_type);
        instdto.setInstruction_id(IdUtil.simpleUUID());
        instdto.setRoute_plan_code(route_plan_code);
        instdto.setMaterial(acsTask.getMaterial());
        instdto.setQuantity(acsTask.getQuantity());
        instdto.setTask_id(taskid);
        instdto.setTask_code(taskcode);
        instdto.setVehicle_code(vehiclecode);
        String now = DateUtil.now();
        instdto.setCreate_time(now);
        instdto.setCreate_by("auto");
        instdto.setStart_device_code(start_device_code);
        instdto.setNext_device_code(next_point_code);
        instdto.setStart_point_code(start_point_code);
        instdto.setNext_point_code(next_point_code);
        instdto.setPriority(priority);
        instdto.setInstruction_status("0");
        instdto.setExecute_device_code(start_point_code);
        instdto.setVehicle_type(vehicleType);
        instdto.setStart_point_code2(start_point_code2);
        instdto.setStart_device_code2(start_point_code2);
        instdto.setNext_device_code2(next_point_code2);
        instdto.setNext_point_code2(next_point_code2);
        instdto.setAgv_system_type(agv_system_type);
        instdto.setAgv_inst_type("1");
        instdto.setExt_task_id(acsTask.getExt_task_id());
        try {
            instructionservice.create2(instdto);
        } catch (Exception e) {
            log.error("手动创建指令失败！任务id为:{},指令号为:{}，失败原因{}", acsTask.getTask_id(), instdto.getInstruction_code(), e.getMessage());
        }
        return instdto;
    }

    public Instruction createInst1(String ids) throws Exception {
        TaskDto acsTask = this.findById(ids);
        if (acsTask == null) {
            throw new BadRequestException("被删除或无权限，操作失败!");
        }
        DeviceAppService appService = SpringContextHolder.getBean(DeviceAppServiceImpl.class);
        InstructionService instructionservice = SpringContextHolder.getBean("instructionServiceImpl");
        InstructionDto inst = instructionservice.findByTaskid(ids, "instruction_status < 2 ");
        if (inst != null) {
            throw new BadRequestException("有指令未完成!");
        }

        String taskid = acsTask.getTask_id();
        String taskcode = acsTask.getTask_code();
        String vehiclecode = acsTask.getVehicle_code();
        String priority = acsTask.getPriority();
        String start_point_code = acsTask.getStart_point_code();
        String start_device_code = acsTask.getStart_device_code();
        String route_plan_code = acsTask.getRoute_plan_code();
        String vehicleType = acsTask.getVehicle_type();
        // 是否复合任务 =0非复合任务
        String compound_task = acsTask.getCompound_task();
        String next_point_code = acsTask.getNext_point_code();
        String next_device_code = acsTask.getNext_device_code();
        String start_point_code2 = acsTask.getStart_point_code2();
        String next_point_code2 = acsTask.getNext_point_code2();
        String agv_system_type = acsTask.getAgv_system_type();
        String task_type = acsTask.getTask_type();
        /** 开始平均分解校验 */
        String this_device_code =
                this.queryAssignedByDevice(acsTask.getStart_device_code(), acsTask.getNext_device_code());
        if (StrUtil.isEmpty(this_device_code)) {
            List<RouteLineDto> shortPathsList =
                    routeLineService.getShortPathLines(
                            start_device_code, acsTask.getNext_device_code(), route_plan_code);
            RouteLineDto routeLineDto = shortPathsList.get(0);
            String path = routeLineDto.getPath();
            String type = routeLineDto.getType();
            String[] str = path.split("->");
            List<String> pathlist = Arrays.asList(str);
            int index = 0;
            for (int m = 0; m < pathlist.size(); m++) {
                if (pathlist.get(m).equals(start_device_code)) {
                    index = m + 1;
                    break;
                }
            }
            next_device_code = pathlist.get(index);
        } else {
            next_device_code = this_device_code;
        }

        if (StrUtil.equals(appService.findDeviceTypeByCode(next_device_code), "storage")) {
            next_point_code = next_device_code + "-" + acsTask.getTo_y() + "-" + acsTask.getTo_z();
        } else {
            next_point_code = next_device_code;
        }

        Instruction instdto = new Instruction();
        instdto.setInstruction_type(task_type);
        instdto.setInstruction_id(IdUtil.simpleUUID());
        instdto.setRoute_plan_code(route_plan_code);
        instdto.setRemark(acsTask.getRemark());
        instdto.setMaterial(acsTask.getMaterial());
        instdto.setQuantity(acsTask.getQuantity());
        instdto.setTask_id(taskid);
        instdto.setTask_code(taskcode);
        instdto.setVehicle_code(vehiclecode);
        String now = DateUtil.now();
        instdto.setCreate_time(now);
        instdto.setCreate_by("auto");
        instdto.setStart_device_code(start_device_code);
        instdto.setNext_device_code(next_device_code);
        instdto.setStart_point_code(start_point_code);
        instdto.setNext_point_code(next_point_code);
        instdto.setPriority(priority);
        instdto.setInstruction_status("0");
        instdto.setExecute_device_code(start_point_code);
        instdto.setVehicle_type(vehicleType);
        instdto.setStart_point_code2(start_point_code2);
        instdto.setStart_device_code2(start_point_code2);
        instdto.setNext_device_code2(next_point_code2);
        instdto.setNext_point_code2(next_point_code2);
        instdto.setAgv_system_type(agv_system_type);
        instdto.setAgv_inst_type("1");
        instructionservice.create2(instdto);

        //        acsTask.setTask_status("1");
        //        this.update(acsTask);
        return instdto;
    }

    @Override
    public Instruction createInst(Instruction inst) throws Exception {
        InstructionService instructionservice = SpringContextHolder.getBean("instructionServiceImpl");
        instructionservice.create2(inst);
        return inst;
    }

    @Override
    public void download(List<TaskDto> all, HttpServletResponse response) throws IOException {
        List<Map<String, Object>> list = new ArrayList<>();
        for (TaskDto acsTask : all) {
            Map<String, Object> map = new LinkedHashMap<>();
            map.put("任务号", acsTask.getTask_code());
            map.put("载具号", acsTask.getVehicle_code());
            map.put("载具类型", acsTask.getVehicle_type());
            map.put("任务类型", acsTask.getTask_type());
            map.put("任务状态", acsTask.getTask_status());
            map.put("任务优先级", acsTask.getPriority());
            map.put("创建类型", acsTask.getCreate_type());
            map.put("完成类型", acsTask.getFinish_type());
            map.put("执行描述编码", acsTask.getExecute_code());
            map.put("执行描述信息", acsTask.getExecute_message());
            map.put("起始点位编码", acsTask.getStart_point_code());
            map.put("起始设备编码", acsTask.getStart_device_code());
            map.put("目标点位编码", acsTask.getNext_point_code());
            map.put("目标设备编码", acsTask.getNext_device_code());
            map.put("排", acsTask.getFrom_x());
            map.put("列", acsTask.getFrom_y());
            map.put("层", acsTask.getFrom_z());
            map.put("排", acsTask.getTo_x());
            map.put("列", acsTask.getTo_y());
            map.put("层", acsTask.getTo_z());
            map.put("路由方案名称", acsTask.getRoute_plan_name());
            map.put("路由方案编码", acsTask.getRoute_plan_code());
            map.put("是否需要反馈上位系统", acsTask.getIs_needfeedback());
            map.put("备注", acsTask.getRemark());
            map.put("是否启用", acsTask.getIs_active());
            map.put("是否删除", acsTask.getIs_delete());
            map.put("创建者", acsTask.getCreate_by());
            map.put("创建时间", acsTask.getCreate_time());
            map.put("修改者", acsTask.getUpdate_by());
            map.put("修改时间", acsTask.getUpdate_time());
            list.add(map);
        }
        FileUtil.downloadExcel(list, response);
    }

    @Override
    public void createTaskByClick(JSONObject json) {
    }

    @Override
    public int checkAllowCreate(String devicecode) {
        Map map = new HashMap();
        List<TaskDto> taskList = this.queryAllUnfinished(map);
        int num = 0;
        for (int i = 0; i < taskList.size(); i++) {
            TaskDto onetask = taskList.get(i);
            String next_code = onetask.getNext_point_code();
            if (StrUtil.equals(devicecode, next_code)) {
                num = num + 1;
            }
        }
        return num;
    }

    @Override
    public boolean removeByCodeFromCache(String code) {
        CopyOnWriteArrayList<TaskDto> taskDtos = (CopyOnWriteArrayList<TaskDto>) this.tasks;
        taskDtos.removeIf((task) -> {
            return task.getTask_code().equals(code);
        });
        return true;
    }

    @Override
    public List<TaskDto> findAllTaskFromCache() {
        return tasks;
    }

    public TaskDto findByContainer(String container_code) {
        Iterator var3 = tasks.iterator();

        while (var3.hasNext()) {
            TaskDto task = (TaskDto) var3.next();
            if (StrUtil.equals(task.getVehicle_code(), container_code)) {
                return task;
            }
        }

        return null;
    }

    public TaskDto findByCodeFromCache(String task_code) {
        Iterator var3 = tasks.iterator();

        while (var3.hasNext()) {
            TaskDto task = (TaskDto) var3.next();
            if (StrUtil.equals(task.getTask_code(), task_code)) {
                return task;
            }
        }
        return null;
    }

    @Override
    public TaskDto findByNextCode(String device_code) {
        Iterator var3 = tasks.iterator();

        while (var3.hasNext()) {
            TaskDto task = (TaskDto) var3.next();
            if (StrUtil.equals(task.getNext_device_code(), device_code)) {
                return task;
            }
        }
        return null;
    }

    @Override
    public List<TaskDto> findAllByNextCode(String device_code) {
        return null;
    }

    @Override
    public Integer queryAllTaskMaterialQty(String device_code) {
        return null;
    }

    @Override
    public TaskDto findByStartCodeAndReady(String device_code) {
        Iterator var3 = tasks.iterator();

        while (var3.hasNext()) {
            TaskDto task = (TaskDto) var3.next();
            //            if (!StrUtil.equals(task.getTask_type(), "5")) {
            //                continue;
            //            }
            if (StrUtil.equals(task.getStart_device_code(), device_code)
                    && StrUtil.equals(task.getTask_status(), "0")) {
                return task;
            }
        }
        return null;
    }

    @Override
    public TaskDto findByStartCode(String device_code) {
        Iterator var3 = tasks.iterator();

        while (var3.hasNext()) {
            TaskDto task = (TaskDto) var3.next();
            if (StrUtil.equals(task.getStart_device_code(), device_code)) {
                return task;
            }
        }
        return null;
    }

    @Override
    public TaskDto foramte(TaskDto task) {
        String start_point_code = task.getStart_point_code();
        String next_point_code = task.getNext_point_code();
        String from_y = null;
        String from_z = null;
        String to_y = null;
        String to_z = null;
        if (StrUtil.contains(start_point_code, "-") && StrUtil.count(start_point_code, "-") == 2) {
            String[] start_point = start_point_code.split("-");
            task.setFrom_x(start_point[0]);
            task.setStart_device_code(start_point[0]);
            if (Integer.parseInt(start_point[1]) < 10 && start_point[1].length() == 1) {
                from_y = "0" + start_point[1];
                task.setFrom_y(from_y);
            } else {
                from_y = start_point[1];
                task.setFrom_y(from_y);
            }
            if (Integer.parseInt(start_point[2]) < 10 && start_point[2].length() == 1) {
                from_z = "0" + start_point[2];
                task.setFrom_z(from_z);
            } else if (start_point[2].length() == 2) {
                from_z = start_point[2];
                task.setFrom_z(start_point[2]);
            } else {
                from_z = start_point[2];
            }
            task.setStart_point_code(task.getStart_device_code() + "-" + from_y + "-" + from_z);
            task.setStart_device_code(task.getStart_device_code());

        } else {
            String start_device =
                    deviceAppService
                            .findDeviceByCode(start_point_code)
                            .getDeviceDriverDefination()
                            .getFitDeviceTypes()
                            .get(0)
                            .name();
            // 如果point_device为货架，则不包含列层信息，需要重新拼接
            if (StrUtil.equals("storage", start_device)) {
                if (StrUtil.isEmpty(task.getFrom_x())) {
                    throw new BadRequestException("货位信息起点需要包含列信息");
                }
                if (StrUtil.isEmpty(task.getFrom_y())) {
                    throw new BadRequestException("货位信息起点需要包含层信息");
                }
                if (Integer.parseInt(task.getFrom_y()) < 10 && task.getFrom_y().length() == 1) {
                    from_y = "0" + task.getFrom_y();
                    task.setFrom_y(from_y);
                } else {
                    from_y = task.getFrom_y();
                }
                if (Integer.parseInt(task.getFrom_z()) < 10 && task.getFrom_z().length() == 1) {
                    from_z = "0" + task.getFrom_z();
                    task.setFrom_z(from_z);
                } else if (task.getFrom_z().length() == 2) {
                    from_z = task.getFrom_z();
                    task.setFrom_z(from_z);
                } else {
                    from_z = task.getFrom_z();
                }
                task.setFrom_x(start_point_code);
                task.setStart_point_code(start_point_code + "-" + from_y + "-" + from_z);
                task.setStart_device_code(start_point_code);
            } else {
                task.setStart_device_code(start_point_code);
                task.setStart_device_code(start_point_code);
            }
        }

        if (StrUtil.contains(next_point_code, "-") && StrUtil.count(next_point_code, "-") == 2) {
            String[] next_point = next_point_code.split("-");
            task.setNext_device_code(next_point[0]);
            task.setTo_x(next_point[0]);
            if (Integer.parseInt(next_point[1]) < 10 && next_point[1].length() == 1) {
                to_y = "0" + next_point[1];
                task.setTo_y(to_y);
            } else {
                to_y = next_point[1];
                task.setTo_y(to_y);
            }
            if (Integer.parseInt(next_point[2]) < 10 && next_point[2].length() == 1) {
                to_z = "0" + next_point[2];
                task.setTo_z(to_z);
            } else if (next_point[2].length() == 2) {
                to_z = next_point[2];
                task.setTo_z(to_z);
            } else {
                to_z = next_point[2];
                task.setTo_z(to_z);
            }
            task.setNext_point_code(task.getNext_device_code() + "-" + to_y + "-" + to_z);
            task.setNext_device_code(task.getNext_device_code());

        } else {
            String next_device =
                    deviceAppService
                            .findDeviceByCode(next_point_code)
                            .getDeviceDriverDefination()
                            .getFitDeviceTypes()
                            .get(0)
                            .name();
            if (StrUtil.equals("storage", next_device)) {
                if (StrUtil.isEmpty(task.getTo_x())) {
                    throw new BadRequestException("货位信息终点需要包含列信息");
                }
                if (StrUtil.isEmpty(task.getTo_y())) {
                    throw new BadRequestException("货位信息终点需要包含层信息");
                }
                if (Integer.parseInt(task.getTo_y()) < 10 && task.getTo_y().length() == 1) {
                    to_y = "0" + task.getTo_y();
                    task.setTo_y(to_y);
                } else {
                    to_y = task.getTo_y();
                }
                if (Integer.parseInt(task.getTo_z()) < 10 && task.getTo_z().length() == 1) {
                    to_z = "0" + task.getTo_z();
                    task.setTo_z(to_z);
                } else if (task.getTo_z().length() == 2) {
                    to_z = task.getTo_z();
                    task.setTo_z(to_z);
                } else {
                    to_z = task.getTo_z();
                }
                task.setTo_x(next_point_code);
                task.setNext_point_code(next_point_code + "-" + to_y + "-" + to_z);
                task.setNext_device_code(next_point_code);

            } else {
                task.setNext_device_code(next_point_code);
                task.setNext_device_code(next_point_code);
            }
        }
        return task;
    }

    @Override
    public void updateByCodeFromCache(TaskDto dto) {
        removeByCodeFromCache(dto.getTask_code());
        tasks.add(dto);
    }

    @Override
    public String queryAssignedByDevice(String device_code, String task_nextdeice_code) {
        List<DeviceAssignedDto> list =
                deviceAssignedService.queryAssignedBydevice(device_code, task_nextdeice_code);
        int flag1 = 0;
        String flag2 = null;
        for (int i = 0; i < list.size(); i++) {
            DeviceAssignedDto dto = list.get(i);
            String inst_nextDevice_code = dto.getInst_nextdevice_code();
            String task_nextDevice_code = dto.getTask_nextdevice_code();
            String param = dto.getParam();
            JSONObject jo = JSON.parseObject(param);
            String regEx = "[`~!@#$%^&*()+=|{}':;'\\[\\].<>/?~！@#￥%……&*（）——+|{}【】'：”“’。、？]";
            Pattern p = Pattern.compile(regEx);
            Matcher m = p.matcher(inst_nextDevice_code);
            String toSpeechText = m.replaceAll("").trim();

            String[] str = toSpeechText.split(",");
            List pathlist = Arrays.asList(str);
            for (int j = 0; j < pathlist.size(); j++) {
                String this_device_code = pathlist.get(j).toString();
                JSONObject data = JSON.parseObject(jo.getString(this_device_code));
                String limit = data.getString("limit");
                int num = instructionService.querySameDestinationInst(this_device_code);
                if (num >= Integer.parseInt(limit)) {
                    continue;
                }
                if (j == 0) {
                    flag1 = num;
                }
                if (num <= flag1) {
                    flag2 = this_device_code;
                }
            }
        }
        if (!StrUtil.isEmpty(flag2)) {
            return flag2;
        }
        return null;
    }

    @Override
    public Integer querySameDeviceReadyTask(String start_device, String next_device, String status) {
        int num = 0;
        Iterator<TaskDto> iterator = tasks.iterator();
        while (iterator.hasNext()) {
            TaskDto task = iterator.next();
            if (StrUtil.equals(task.getStart_device_code(), start_device)
                    && StrUtil.equals(task.getNext_device_code(), next_device)
                    && StrUtil.equals(task.getTask_status(), status)) {
                num++;
            }
        }

        return num;
    }


    @Override
    public Integer querySameTaskByType(String taskType) {
        int num = 0;
        Iterator<TaskDto> iterator = tasks.iterator();
        while (iterator.hasNext()) {
            TaskDto task = iterator.next();
            if (task.getTask_type().equals(taskType) && task.getTask_status().equals("1")) {
                num++;
            }
        }

        return num;
    }

    @Override
    public Integer querySameOriginTask(String code) {
        int num = 0;
        Iterator<TaskDto> iterator = tasks.iterator();
        while (iterator.hasNext()) {
            TaskDto task = iterator.next();
            if (StrUtil.equals(task.getStart_device_code(), code)) {
                num++;
            }
        }

        return num;
    }

    @Override
    public Integer querySameDestinationTask(String code) {
        int num = 0;
        Iterator<TaskDto> iterator = tasks.iterator();
        while (iterator.hasNext()) {
            TaskDto task = iterator.next();
            if (StrUtil.equals(task.getNext_device_code(), code)) {
                num++;
            }
        }

        return num;
    }
}
