package org.nl.acs.device_driver.basedriver.hongxiang_device;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.nl.acs.agv.server.AgvService;
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.RouteableDeviceDriver;
import org.nl.acs.device_driver.driver.AbstractOpcDeviceDriver;
import org.nl.acs.device_driver.driver.ExecutableDeviceDriver;
import org.nl.acs.ext.wms.data.ApplyLabelingAndBindingRequest;
import org.nl.acs.ext.wms.data.ApplyLabelingAndBindingResponse;
import org.nl.acs.ext.wms.service.AcsToWmsService;
import org.nl.acs.ext.wms.service.impl.AcsToWmsServiceImpl;
import org.nl.acs.instruction.service.InstructionService;
import org.nl.acs.log.service.DeviceExecuteLogService;
import org.nl.acs.monitor.DeviceStageMonitor;
import org.nl.acs.opc.DeviceAppService;
import org.nl.acs.route.service.RouteLineService;
import org.nl.acs.storage_cell.domain.StorageCell;
import org.nl.acs.storage_cell.service.mapper.StorageCellMapper;
import org.nl.acs.task.service.TaskService;
import org.nl.system.service.param.ISysParamService;
import org.nl.config.SpringContextHolder;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.*;

/**
 * 烘箱工位
 */
@Slf4j
@Data
@RequiredArgsConstructor
public class HongXiangConveyorDeviceDriver extends AbstractOpcDeviceDriver implements DeviceDriver, ExecutableDeviceDriver, RouteableDeviceDriver, DeviceStageMonitor {
    protected ItemProtocol itemProtocol = new ItemProtocol(this);
    @Autowired
    DeviceAppService deviceAppservice = SpringContextHolder.getBean(DeviceAppService.class);
    @Autowired
    InstructionService instructionService = SpringContextHolder.getBean(InstructionService.class);
    @Autowired
    DeviceService deviceservice = SpringContextHolder.getBean(DeviceService.class);
    @Autowired
    TaskService taskserver = SpringContextHolder.getBean(TaskService.class);
    @Autowired
    RouteLineService routeLineService = SpringContextHolder.getBean(RouteLineService.class);
    @Autowired
    AcsToWmsService acsToWmsService = SpringContextHolder.getBean(AcsToWmsServiceImpl.class);
    @Autowired
    ISysParamService paramService = SpringContextHolder.getBean(ISysParamService.class);
    @Autowired
    DeviceExecuteLogService logServer = SpringContextHolder.getBean(DeviceExecuteLogService.class);
    @Autowired
    AgvService agvService = SpringContextHolder.getBean(AgvService.class);

    @Autowired
    StorageCellMapper storageCellMapper;

    private Date instruction_require_time = new Date();
    private Date instruction_finished_time = new Date();
    private Date instruction_apply_time = new Date();
    private int instruction_require_time_out = 3000;

    public int heartbeat = 0;
    public int mode = 0;
    public int move = 0;
    public int action = 0;
    public int error = 0;
    public int door = 0;
    public int temperature = 0;
    public int countdown_house = 0;
    public int countdown_min = 0;
    public int countdown_sec = 0;
    public int finish = 0;
    public int task = 0;
    public int error1 = 0;
    public int material = 0;
    public int consumption = 0;
    public float voltageA = 0;
    public float voltageB = 0;
    public float voltageC = 0;
    public float currentA = 0;
    public float currentB = 0;
    public float currentC = 0;

    public int last_heartbeat = 0;
    public int last_mode = 0;
    public int last_move = 0;
    public int last_action = 0;
    public int last_error = 0;
    public int last_door = 0;
    public int last_temperature = 0;
    public int last_countdown_house = 0;
    public int last_countdown_min = 0;
    public int last_countdown_sec = 0;
    public int last_finish = 0;
    public int last_task = 0;
    public int last_error1 = 0;
    public int last_material = 0;
    public int last_consumption = 0;
    public float last_voltageA = 0;
    public float last_voltageB = 0;
    public float last_voltageC = 0;
    public float last_currentA = 0;
    public float last_currentB = 0;
    public float last_currentC = 0;

    Boolean isonline = true;

    Boolean iserror = false;

    //1-执行任务；2-取货完成；3-放货完成；
    int flag;

    String device_code;

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

    //请求成功标记
    Boolean requireSucess = false;

    @Override
    public void execute() {
        String message = null;

        device_code = this.getDeviceCode();
        heartbeat = this.itemProtocol.getItem_heartbeat();
        mode = this.itemProtocol.getItem_mode();
        move = this.itemProtocol.getItem_move();
        action = this.itemProtocol.getItem_action();
        error = this.itemProtocol.getItem_error();
        door = this.itemProtocol.getItem_door();
        temperature = this.itemProtocol.getItem_temperature();
        countdown_house = this.itemProtocol.getItem_countdown_house();
        countdown_min = this.itemProtocol.getItem_countdown_min();
        countdown_sec = this.itemProtocol.getItem_countdown_sec();
        finish = this.itemProtocol.getItem_finish();
        task = this.itemProtocol.getItem_task();
        error1 = this.itemProtocol.getItem_error1();
        material = this.itemProtocol.getItem_material();
        consumption = this.itemProtocol.getItem_consumption();
        voltageA = this.itemProtocol.getItem_voltageA();
        voltageB = this.itemProtocol.getItem_voltageB();
        voltageC = this.itemProtocol.getItem_voltageC();
        currentA = this.itemProtocol.getItem_currentA();
        currentB = this.itemProtocol.getItem_currentB();
        currentC = this.itemProtocol.getItem_currentC();

        if (mode != last_mode) {
            //this.setRequireSucess(false);
        }
        if (move != last_move) {
            if (move == 0) {
                thingToNothing();
            }
        }
        if (finish != last_finish) {
            if (finish == 1) {
                logServer.deviceExecuteLog(device_code, "", "", "开始请求标记复位`此时请求标记值为requireSucess:" + requireSucess);
                requireSucess = false;
                logServer.deviceExecuteLog(device_code, "", "", "请求标记复位成功`此时请求标记值为requireSucess:" + requireSucess);
            }
            logServer.deviceExecuteLog(this.device_code, "", "", "信号move：" + last_finish + "->" + finish);
        }
        if (mode == 0) {
            this.setIsonline(false);
            message = "有报警";
            //无报警
        } else if (error != 0) {
            this.setIserror(true);
            message = "有报警";
            //无报警
        } else {
            this.setIsonline(true);
            this.setIserror(false);
            if (move == 0 && last_move == 1) {
                //requireSucess = false;
            }

            if (finish == 1 && !requireSucess) {
                logServer.deviceExecuteLog(this.getDevice_code(), "", "", "开始烘箱完成反馈lms~");
                //烘箱完成反馈LMS
                apply_finish();
            }
        }

        last_mode = mode;
        last_move = move;
        last_action = action;
        last_error = error;
        last_door = door;
        last_temperature = temperature;
        last_countdown_house = countdown_house;
        last_countdown_min = countdown_min;
        last_countdown_sec = countdown_sec;
        last_finish = finish;
        last_task = task;
        last_error1 = error1;
        last_material = material;
        last_consumption = consumption;
        last_voltageA = voltageA;
        last_voltageB = voltageB;
        last_voltageC = voltageC;
        last_currentA = currentA;
        last_currentB = currentB;
        last_currentC = currentC;
    }


    protected void thingToNothing() {
        //this.setRequireSucess(false);
    }

    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 List<String> getExtraDeviceCodes(String extraName) {
        String extraValue = (String) this.getDevice().getExtraValue().get(extraName);
        if (StrUtil.isEmpty(extraValue)) {
            return new ArrayList<>();
        }
        String devicesString = extraValue.substring(1, extraValue.length() - 1);
        List<String> devicesList = new ArrayList<>();
        String[] devices = devicesString.split(",");
        for (int i = 0; i < devices.length; i++) {
            String s = devices[i].replace("\"", "").replace("\"", "");
            devicesList.add(s);
        }
        return devicesList;
    }

    public void writing(String param, String value) {

        String to_param = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code()
                + "." + param;
        //String opcservcerid = this.getDevice().getOpc_server_id();
//Server server = ReadUtil.getServer(opcservcerid);
        Map<String, Object> itemMap = new HashMap<String, Object>();

        itemMap.put(to_param, Integer.parseInt(value));
//            itemMap.put(to_param, Integer.parseInt(value));
        this.control(itemMap);
        logServer.deviceExecuteLog(device_code, "", "", "下发电气信号设备号:" + device_code + ",下发电气:" + to_param + ",下发电气值:" + value);

    }

    public void writing(int type, int command) {
        String to_command = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code()
                + "." + org.nl.acs.device_driver.basedriver.cargo_lift_conveyor.ItemProtocol.item_to_command;
        String to_target = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code()
                + "." + org.nl.acs.device_driver.basedriver.cargo_lift_conveyor.ItemProtocol.item_to_target;
        String to_task = this.getDevice().getOpc_server_code() + "." + this.getDevice().getOpc_plc_code() + "." + this.getDevice().getDevice_code()
                + "." + org.nl.acs.device_driver.basedriver.cargo_lift_conveyor.ItemProtocol.item_to_task;
        //String opcservcerid = this.getDevice().getOpc_server_id();
//Server server = ReadUtil.getServer(opcservcerid);
        Map<String, Object> itemMap = new HashMap<String, Object>();
        if (type == 1) {
            itemMap.put(to_command, command);
            log.info("设备:" + device_code + ",下发PLC信号" + to_command + ",value:" + command);
        } else if (type == 2) {
            itemMap.put(to_target, command);
            log.info("设备:" + device_code + ",下发PLC信号" + to_target + ",value:" + command);

        } else if (type == 3) {
            itemMap.put(to_task, command);
            log.info("设备:" + device_code + ",下发PLC信号" + to_task + ",value:" + command);
        }

        this.control(itemMap);
    }

    @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 = "联机";
        }
        String requireSucess = "0";
        if (this.requireSucess) {
            requireSucess = "1";
        }
        jo.put("requireSucess", requireSucess);

        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("temperature", temperature);
        jo.put("finish", finish);
        jo.put("isOnline", this.getIsonline());
        jo.put("error", this.getError());
        jo.put("isError", this.getIserror());
        jo.put("countdown_house", countdown_house);
        jo.put("countdown_min", countdown_min);
        jo.put("countdown_sec", countdown_sec);
        jo.put("door", door);
        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) {

    }

    public synchronized boolean apply_finish() {
        Date date = new Date();
        if (date.getTime() - this.instruction_apply_time.getTime() < (long) this.instruction_require_time_out) {
            log.trace("触发时间因为小于{}毫秒，而被无视", this.instruction_require_time_out);
            return false;
        } else {
            this.instruction_apply_time = date;
            ApplyLabelingAndBindingRequest applyLabelingAndBindingRequest = new ApplyLabelingAndBindingRequest();
//            JSONObject device_json = WQLObject.getWQLObject("acs_storage_cell").query("storage_code ='" + this.device_code + "'").uniqueResult(0);
            StorageCell storageCell = new LambdaQueryChainWrapper<>(storageCellMapper)
                    .eq(StorageCell::getStorage_code, this.device_code)
                    .one();
            String start_point_code = null;
            if (!ObjectUtil.isEmpty(storageCell)) {
//                start_point_code = (String) device_json.get("parent_storage_code") == null ? this.device_code : (String) device_json.get("parent_storage_code");
                start_point_code = (String) storageCell.getParent_storage_code() == null ? this.device_code : (String) storageCell.getParent_storage_code();
            }
            applyLabelingAndBindingRequest.setDevice_code(start_point_code);
            applyLabelingAndBindingRequest.setType("3");
            ApplyLabelingAndBindingResponse applyLabelingAndBindingResponse = acsToWmsService.applyLabelingAndBindingRequest(applyLabelingAndBindingRequest);
            if (applyLabelingAndBindingResponse.getstatus() == 200) {
                requireSucess = true;
                logServer.deviceExecuteLog(this.getDevice_code(), "", "", "烘箱完成反馈lms响应消息:" + String.valueOf(applyLabelingAndBindingResponse));
            } else {
                logServer.deviceExecuteLog(this.getDevice_code(), "", "", "烘箱完成反馈lms响应消息:" + String.valueOf(applyLabelingAndBindingResponse));
            }
            return true;
        }
    }

}
