package org.nl.acs.device_driver.tianneng.site;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nl.acs.device.domain.Device;
import org.nl.acs.device.service.DeviceService;
import org.nl.acs.device_driver.DeviceDriver;
import org.nl.acs.device_driver.RequestMethodEnum;
import org.nl.acs.device_driver.RouteableDeviceDriver;
import org.nl.acs.device_driver.driver.AbstractOpcDeviceDriver;
import org.nl.acs.device_driver.driver.ExecutableDeviceDriver;
import org.nl.acs.ext.wms.data.BaseRequest;
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.monitor.DeviceStageMonitor;
import org.nl.acs.opc.WcsConfig;
import org.nl.acs.route.service.RouteLineService;
import org.nl.acs.route.service.dto.RouteLineDto;
import org.nl.acs.task.domain.Task;
import org.nl.acs.task.service.TaskService;
import org.nl.acs.task.service.dto.TaskDto;
import org.nl.acs.task.service.mapper.TaskMapper;
import org.nl.acs.utils.ConvertUtil;
import org.nl.common.utils.CodeUtil;
import org.nl.config.SpringContextHolder;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 检测站点驱动
 */
@Slf4j
@Data
@RequiredArgsConstructor
public class SiteDeviceDriver extends AbstractOpcDeviceDriver implements DeviceDriver, ExecutableDeviceDriver, RouteableDeviceDriver, DeviceStageMonitor {
    protected ItemProtocol itemProtocol = new ItemProtocol(this);

    InstructionService instructionService = SpringContextHolder.getBean("instructionServiceImpl");

    DeviceService deviceservice = SpringContextHolder.getBean("deviceServiceImpl");

    RouteLineService routelineserver = SpringContextHolder.getBean("routeLineServiceImpl");

    TaskService taskserver = SpringContextHolder.getBean("taskServiceImpl");

    TaskMapper taskMapper;

    AcsToWmsService acsToWmsService = SpringContextHolder.getBean("acsToWmsServiceImpl");

    String container;
    String container_type_desc;
    String last_container_type_desc;
    String last_container;
    //放货准备锁
    String putReadyLock = null;
    //有货标记
    protected boolean has_goods_tag = false;

    private Date time = new Date();

    int mode = 0;
    int error = 0;
    int move = 0;
    int task = 0;
    int action = 0;
    int last_mode = 0;
    int last_error = 0;
    int last_move = 0;
    int last_task = 0;
    Boolean isonline = true;
    int hasGoods = 0;
    String message = null;
    Boolean iserror = false;

    int io_action = 0;
    int last_io_action = 0;
    int pallet_type = 0;
    int last_pallet_type = 0;


    int barcode = 0;
    int last_barcode = 0;


    boolean hasVehicle = false;
    boolean isReady = false;
    protected int instruction_num = 0;
    protected int instruction_num_truth = 0;
    boolean isFold = false;
    private String assemble_check_tag;

    protected String current_stage_instruction_message;
    protected String last_stage_instruction_message;
    Integer heartbeat_tag;
    private Date instruction_require_time = new Date();
    private Date instruction_finished_time = new Date();

    private int instruction_require_time_out;
    boolean requireSucess = false;

    private int instruction_finished_time_out;

    int branchProtocol = 0;
    //备注
    String remark;
    //数量
    String qty;
    //物料
    String material;
    //批次
    String batch;
    //当前指令
    Instruction inst = null;
    //上次指令
    Instruction last_inst = null;

    //触摸屏手动触发任务
    private Boolean is_has_task = false;

    //满盅入库请求标记
    boolean Sucess = false;

    //暂定 0就绪 1请求取货 2取货完成 3请求放货 4放货完成 5取货完成离开 6放货完成离开 7请求进入区域 8请求离开区域
    int flag;

    String device_code;

    @Override
    public Device getDevice() {
        return this.device;
    }


    @Override
    public void execute() {
        String message = null;
        try {
            device_code = this.getDeviceCode();
            mode = this.itemProtocol.getMode();
            error = this.itemProtocol.getError();
            move = this.itemProtocol.getMove();
            hasGoods = this.itemProtocol.getMove();
            action = this.itemProtocol.getAction();
            pallet_type = this.itemProtocol.getPalletType();

            if (move != last_move) {
                this.setRequireSucess(false);
                //反馈输送线点位状态
                if (device_code.startsWith("ZCSSX")) {
                    BaseRequest request = new BaseRequest();
                    request.setType("1");
                    request.setDevice_code(device_code);
                    //1无货 2有货
                    request.setState(String.valueOf(move+1));
                    acsToWmsService.notify(request);
                }
            }
            if (error != last_error &&error!=0) {
                FeedBackTaskStatusRequest request = new FeedBackTaskStatusRequest();
                request.setDevice_code(this.device_code);
                request.setState("故障");
                acsToWmsService.notify(request);
            }
        } catch (Exception var17) {
            return;
        }
        if (!this.itemProtocol.getIsonline()) {
            this.setIsonline(false);
            this.setIserror(true);
            message = "信号量同步异常";
            //未联机
        } else if (mode == 0) {
            this.setIsonline(false);
            this.setIserror(true);
            message = "未联机";
            //有报警
        } else if (error != 0) {
            this.setIsonline(false);
            this.setIserror(true);
            message = "有报警";
            //无报警
        } else {
            this.setIsonline(true);
            this.setIserror(false);
            message = "";
            Instruction instruction = null;
            List toInstructions;
            switch (mode) {
                case 1:
                    log.debug("设备运转模式:等待工作");
                    return;
                case 2:
                    break;
                case 5:
                    //叫料
                    if (move==0 && !requireSucess){
                        apply(5);
                    }
                    break;
                case 6:
                    //满料出库
                    if(move==1 && !requireSucess){
                        apply(6);
                    }
                    break;
                case 7:
                    //申请空盘
                    if (move==0 && !requireSucess){
                        apply(7);
                    }
                    break;
                case 8:
                    //空托盘出库
                    if(move==1 && !requireSucess){
                        apply(8);
                    }
                    break;
            }

            switch (flag) {
                //取货完成
                case 1:
                    writing(2);
                    return;
                //放货完成
                case 2:
                    writing(3);
                    return;

            }

        }
        last_mode = mode;
        last_error = error;
        last_move = move;
        last_task = task;
        last_pallet_type = pallet_type;
        last_barcode = barcode;

    }


    public boolean exe_error() {
        if (this.error == 0) {
            return true;
        } else {
            log.debug("设备报警");
            return false;
        }
    }

    protected void thingToNothing() {
        log.debug("从有货到无货 清理数据");
        this.set_last_container(container, container_type_desc);
    }

    public void set_last_container(String barcode, String type_desc) {
        this.set_last_container(barcode);
        this.set_last_container_type_desc(type_desc);
    }

    public void set_last_container(String barcode) {
    }

    public void set_last_container_type_desc(String type) {
    }

    public boolean exe_business() {
        return true;
    }


    public void writing(int command) {
        String to_command = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code()
                + "." + ItemProtocol.item_to_command;

        //String opcservcerid = this.getDevice().getOpc_server_id();
//Server server = ReadUtil.getServer(opcservcerid);
        Map<String, Object> itemMap = new HashMap<String, Object>();
        itemMap.put(to_command, command);
        this.control(itemMap);

    }


    public boolean instruction_require(String container_code) {
        return instruction_require(container_code, WcsConfig.task_container_type_default_desc);
    }

    /**
     * 请求指令
     *
     * @param container_code
     * @param container_type
     */
    public synchronized boolean instruction_require(String container_code, String container_type) {
        Date date = new Date();
        if (date.getTime() - this.instruction_require_time.getTime() < (long) this.instruction_require_time_out) {
            log.trace("触发时间因为小于{}毫秒，而被无视", this.instruction_require_time_out);
            return false;
        } else {
            this.instruction_require_time = date;
            TaskDto dto = new TaskDto();
            String now = DateUtil.now();
            dto.setTask_id(IdUtil.simpleUUID());
            dto.setCreate_by(this.getDevice().getDevice_code());
            dto.setUpdate_by(this.getDevice().getDevice_code());
            dto.setStart_point_code(this.getDevice().getDevice_code());
            dto.setVehicle_code(container_code);
            dto.setVehicle_type(container_type);

            String taskcode = CodeUtil.getNewCode("TASK_NO");
            dto.setTask_code("-" + taskcode);
            dto.setTask_status("0");
            dto.setPriority("101");
            RouteLineDto jo = routelineserver.findByCode(this.getDevice().getDevice_code());
            String next_device_codecode = jo.getNext_device_code();
            if (StrUtil.isEmpty(next_device_codecode)) {
                throw new RuntimeException("该设备未找到对应路由");
            }
            dto.setNext_point_code(next_device_codecode);
            dto.setUpdate_time(now);
            dto.setCreate_time(now);

//            WQLObject wo = WQLObject.getWQLObject("acs_task");
//             JSONObject json = (JSONObject) JSONObject.toJSON(dto);
//
//            wo.insert(json);

            Task entity = ConvertUtil.convert(dto, Task.class);
            taskMapper.insert(entity);
            requireSucess = false;
            return true;
        }
    }

    @Override
    public JSONObject getDeviceStatusName() {
        JSONObject jo = new JSONObject();
        String mode = "";
        String action = "";
        String move = "";
        if (this.getMode() == 0) {
            mode = "未联机";
        } else if (this.getMode() == 1) {
            mode = "单机";
        } else if (this.getMode() == 2) {
            mode = "联机";
        } else if (this.getMode() == 3) {
            mode = "运行中";
        }

        if (this.getMove() == 0) {
            move = "无货";
            jo.put("hasGoods", false);
        } else if (this.getMove() == 1) {
            move = "有货";
            jo.put("hasGoods", true);
        } else if (this.getMove() == 2) {
            move = "有托盘有货";
            jo.put("hasGoods", true);
        }
        jo.put("device_name", this.getDevice().getDevice_name());
        jo.put("mode", mode);
        jo.put("move", move);
        jo.put("action", action);
        jo.put("isOnline", this.getIsonline());
        jo.put("error", this.getError());
        jo.put("isError", this.getIserror());
        jo.put("task", this.getTask());
        return jo;
    }

    @Override
    public void setDeviceStatus(JSONObject data) {

    }

    /**
     * lms申请任务
     *
     * @param
     */
    public synchronized boolean apply(Integer type) {
        Date date = new Date();
        if (date.getTime() - this.time.getTime() < (long) this.instruction_require_time_out) {
            log.trace("触发时间因为小于{}毫秒，而被无视", this.time);
            return false;
        } else {
            this.time = date;
            JSONObject jsonObject = new JSONObject();
            String device_code = this.device_code;
            jsonObject.put("device_code", device_code);
            jsonObject.put("requestDate", new Date());
            jsonObject.put("vehicle_type",this.pallet_type);
            jsonObject.put("requestNo", IdUtil.simpleUUID());
            switch (type) {
                case 7:
                    if(device_code.startsWith("ZCSSX")) {
                        jsonObject.put("request_method_code", "KJQKTask");
                    }else{
                        jsonObject.put("request_method_code", "TBXQKTask");
                    }
                    break;
                case 8:
                    jsonObject.put("request_method_code", "KJSKTask");
                    break;
            }
            String result=acsToWmsService.applyTaskToWms(jsonObject);
            JSONObject res_jo = JSONObject.parseObject(result);
//            if (StrUtil.equals(res_jo.getString("code"), "200")) {
                this.writing(type);
                this.setRequireSucess(true);
                log.info("acs申请任务", this.device_code, "任务申请成功!");
//            }else{
//                this.writing(99);
//            }
            return true;
        }
    }
}
