package com.dcs.equipment.service.impl;

import com.dcs.equipment.constants.EquipmentConstants;
import com.dcs.equipment.service.M1FlowService;
import com.dcs.equipment.service.ModbusTcpService;
import com.dcs.equipment.task.ModbusTcpTask;
import com.dcs.equipment.utils.ModbusUtil;
import com.dcs.hnyz.domain.EquipmentParam;
import com.dcs.hnyz.service.IEquipmentParamService;
import com.intelligt.modbus.jlibmodbus.exception.ModbusIOException;
import com.intelligt.modbus.jlibmodbus.exception.ModbusNumberException;
import com.intelligt.modbus.jlibmodbus.exception.ModbusProtocolException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

/**
 * @author: wangpx
 * @date: 2025-05-10 10:22
 */
@Service
public class M1FlowServiceImpl implements M1FlowService {

    private static final Logger logger = LoggerFactory.getLogger("M1Flow");

    @Autowired
    private IEquipmentParamService equipmentParamService;
    @Autowired
    private ModbusTcpService modbusTcpService;

    // TODO 改用数据库配置实现

    /**
     * M1注料
     */
    @Override
    public boolean M1Fill() {
        List<EquipmentParam> equipmentParamList = ModbusTcpTask.equipmentParamList;
        Map<Integer, Integer> equipmentIndexList = equipmentParamService.getEquipmentIndexList();
        try {
            // 打开N1 M1进料阀
            EquipmentParam N1Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N1));
            ModbusUtil.setCoilValue(1, N1Param.getAddress(), true);
            // 打开 N6 M1排堵进气阀2
            EquipmentParam N6Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N6));
            ModbusUtil.setCoilValue(1, N6Param.getAddress(), true);
            // 打开 N7 M1排堵出气阀2
            EquipmentParam N7Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N7));
            ModbusUtil.setCoilValue(1, N7Param.getAddress(), true);
            // 打开 N9 M1排堵出气阀1
            EquipmentParam N9Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N9));
            ModbusUtil.setCoilValue(1, N9Param.getAddress(), true);
        } catch (ModbusProtocolException | ModbusNumberException | ModbusIOException e) {
            logger.error("M1注料流程错误", e);
            return false;
        }
        return true;
    }

    /**
     * Z1注料
     */
    @Override
    public boolean Z1Fill() {
        List<EquipmentParam> equipmentParamList = ModbusTcpTask.equipmentParamList;
        Map<Integer, Integer> equipmentIndexList = equipmentParamService.getEquipmentIndexList();
        try {
            // 打开 LB3 M1换热出液泵
            EquipmentParam LB3Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.LB3_STATE_SETTING));
            ModbusUtil.setRegisterValue(1, LB3Param.getAddress(), EquipmentConstants.INVERTER_SETTING_FORWARD);
        } catch (ModbusProtocolException | ModbusNumberException | ModbusIOException e) {
            logger.error("Z1注料流程错误", e);
            return false;
        }
        return true;
    }

    /**
     * J1-M1换热
     */
    @Override
    public boolean J1TransferHeatToM1() {
        List<EquipmentParam> equipmentParamList = ModbusTcpTask.equipmentParamList;
        Map<Integer, Integer> equipmentIndexList = equipmentParamService.getEquipmentIndexList();
        try {
            // 等待LB2状态为停止 关闭N1
            EquipmentParam LB2Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.LB2_STATE));
            boolean isLB2Close;
            do {
                int LB2State = ModbusUtil.getHoldingRegisterIntegerValue(1, LB2Param.getAddress());
                isLB2Close = EquipmentConstants.INVERTER_STATUS_STOP.equals(LB2State);
                if (isLB2Close) {
//                    关闭N1 M1进料阀
                    EquipmentParam N1Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N1));
                    ModbusUtil.setCoilValue(1, N1Param.getAddress(), false);
                } else { // 未关闭LB2 提醒在第三方触摸屏上关闭N1
                    // TODO 使用ws通知 提醒在第三方触摸屏上关闭LB2
                    Thread.sleep(1000);
                }
            } while (!isLB2Close); // 等待LB2状态为停止
            // 打开D1 J1换热进液阀
            EquipmentParam D1Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.D1));
            ModbusUtil.setCoilValue(1, D1Param.getAddress(), true);
            // 启动LB4
            EquipmentParam LB4Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.LB4_STATE));
            boolean isLB4Open;
            do {
                int LB4State = ModbusUtil.getHoldingRegisterIntegerValue(1, LB4Param.getAddress());
                isLB4Open = EquipmentConstants.INVERTER_STATUS_FORWARD.equals(LB4State);
                if (!isLB4Open) { // 未启动LB4 提醒在第三方触摸屏上打开LB4
                    // TODO 使用ws通知 提醒在第三方触摸屏上打开LB4
                    Thread.sleep(1000);
                }
            } while (!isLB4Open); // 等待LB4状态为启动
            // 打开N21
            EquipmentParam N21Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N21));
            ModbusUtil.setCoilValue(1, N21Param.getAddress(), true);
            // 打开D4 J2进液换热阀
            EquipmentParam D4Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.D4));
            ModbusUtil.setCoilValue(1, D4Param.getAddress(), true);
        } catch (ModbusProtocolException | ModbusNumberException | ModbusIOException | InterruptedException e) {
            logger.error("J1-M1换热流程错误", e);
            return false;
        }
        return true;
    }

    /**
     * 水解罐注料
     * @param tankCode 水解罐编码
     */
    @Override
    public boolean hydrolysisTankFill(String tankCode) {
        List<EquipmentParam> equipmentParamList = ModbusTcpTask.equipmentParamList;
        Map<Integer, Integer> equipmentIndexList = equipmentParamService.getEquipmentIndexList();
        try {
            // 判断是否达到指定温度
            EquipmentParam M1TemperatureParam = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.M1_TEMPERATURE));
            EquipmentParam M1TemperatureSettingParam = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.M1_TEMPERATURE_SETTING));
            boolean isM1TemperatureOK;
            do {
                float M1Temperature = ModbusUtil.getHoldingRegisterFloatValue(1, M1TemperatureParam.getAddress());
                float M1TemperatureSetting = ModbusUtil.getHoldingRegisterFloatValue(1, M1TemperatureSettingParam.getAddress());

                isM1TemperatureOK = M1Temperature >= M1TemperatureSetting;
                if (!isM1TemperatureOK) Thread.sleep(500); // 未达到指定温度 每0.5s判断一次
            } while (!isM1TemperatureOK); // 等待达到指定温度
            // 打开N25
            EquipmentParam N25Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N25));
            ModbusUtil.setCoilValue(1, N25Param.getAddress(), true);
            // 打开注料阀
            // TODO 根据tankCode选择对应的注料阀 S1(D5) S2(D6) S3(D7)
            EquipmentParam D5Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.D5));
            ModbusUtil.setCoilValue(1, D5Param.getAddress(), true);
            // 打开LB9 M1出料泵
            EquipmentParam LB9Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.LB9_STATE_SETTING));
            EquipmentParam LB9StateParam = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.LB9_STATE));
            boolean isLB9Open;
            do {
                ModbusUtil.setRegisterValue(1, LB9Param.getAddress(), EquipmentConstants.INVERTER_SETTING_FORWARD);
                int LB9State = ModbusUtil.getHoldingRegisterIntegerValue(1, LB9StateParam.getAddress());
                isLB9Open = EquipmentConstants.INVERTER_STATUS_FORWARD.equals(LB9State);
                if (!isLB9Open) Thread.sleep(1000); // 未启动LB9 每秒启动一次
            } while (!isLB9Open); // 等待LB9状态为启动
            // 打开N10 M1出料阀 等待5s
            EquipmentParam N10Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N10));
            ModbusUtil.setCoilValue(1, N10Param.getAddress(), true);
            Thread.sleep(5000);
            // 关闭N9 M1排堵出气阀1
            EquipmentParam N9Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N9));
            ModbusUtil.setCoilValue(1, N9Param.getAddress(), false);
            // 关闭LB3 M1换热出液泵
            EquipmentParam LB3Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.LB3_STATE_SETTING));
            EquipmentParam LB3StateParam = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.LB3_STATE));
            boolean isLB3Close;
            do {
                ModbusUtil.setRegisterValue(1, LB3Param.getAddress(), EquipmentConstants.INVERTER_SETTING_STOP);
                int LB3State = ModbusUtil.getHoldingRegisterIntegerValue(1, LB3StateParam.getAddress());
                isLB3Close = EquipmentConstants.INVERTER_STATUS_STOP.equals(LB3State);
                if (!isLB3Close) Thread.sleep(1000); // 未关闭LB9 每秒关闭一次
            } while (!isLB3Close); // 等待LB3状态为停止
        } catch (ModbusProtocolException | ModbusNumberException | ModbusIOException | InterruptedException e) {
            logger.error(tankCode + "注料流程错误", e);
            return false;
        }
        return true;
    }

    /**
     * 水解罐待机
     * @param tankCode
     */
    @Override
    public boolean hydrolysisTankHolding(String tankCode) {
        List<EquipmentParam> equipmentParamList = ModbusTcpTask.equipmentParamList;
        Map<Integer, Integer> equipmentIndexList = equipmentParamService.getEquipmentIndexList();
        try {
            // 关闭注料阀
            // TODO 根据tankCode选择对应的注料阀 S1(D5) S2(D6) S3(D7)
            // 关闭D5 S1进料阀
            EquipmentParam D5Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.D5));
            ModbusUtil.setCoilValue(1, D5Param.getAddress(), false);
            // 关闭N21 等待3s
            EquipmentParam N21Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N21));
            ModbusUtil.setCoilValue(1, N21Param.getAddress(), false);
            Thread.sleep(3000);
            // 关闭LB4
            EquipmentParam LB4StateParam = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.LB4_STATE));
            boolean isLB4Close;
            do {
                int LB4State = ModbusUtil.getHoldingRegisterIntegerValue(1, LB4StateParam.getAddress());
                isLB4Close = EquipmentConstants.INVERTER_STATUS_STOP.equals(LB4State);
                if (!isLB4Close) {
                    // 提醒在第三方触摸屏上关闭LB4
                    // TODO 使用ws通知 提醒在第三方触摸屏上关闭LB4
                    Thread.sleep(1000);
                }
            } while (!isLB4Close); // 等待LB4状态为停止
            // 打开D8 S1加压阀
            EquipmentParam D8Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.D8));
            ModbusUtil.setCoilValue(1, D8Param.getAddress(), true);
            // 判断是否达到指定压力
            // TODO 根据tankCode选择对应的压力 S1 S2 S3
            EquipmentParam S1PressureParam = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.S1_PRESSURE));
            float pressure;
            do {
                pressure = ModbusUtil.getHoldingRegisterFloatValue(1, S1PressureParam.getAddress());
                Thread.sleep(1000);
            } while (!(pressure > 80)); // 等待压力达到指定值
            // 关闭D8 S1加压阀
            ModbusUtil.setCoilValue(1, D8Param.getAddress(), false);
            // 打开D11 S1加热阀
            EquipmentParam D11Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.D11));
            ModbusUtil.setCoilValue(1, D11Param.getAddress(), true);
            // 等待S1温度达到指定值
            EquipmentParam S1TemperatureParam = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.S1_TEMPERATURE));
            float temperature;
            do {
                temperature = ModbusUtil.getHoldingRegisterFloatValue(1, S1TemperatureParam.getAddress());
                Thread.sleep(1000);
            } while (!(temperature > 125)); // 等待温度达到指定值
            // 关闭D11 S1加热阀
            ModbusUtil.setCoilValue(1, D11Param.getAddress(), false);

        } catch (ModbusProtocolException | ModbusNumberException | ModbusIOException | InterruptedException e) {
            logger.error(tankCode + "待机流程错误", e);
            return false;
        }
        return true;
    }

    /**
     * 水解罐压力复用
     * @param targetTankCode 目标水解罐编码
     * @param sourceTankCode 源水解罐编码
     */
    @Override
    public boolean hydrolysisBalance(String targetTankCode, String sourceTankCode) {
        List<EquipmentParam> equipmentParamList = ModbusTcpTask.equipmentParamList;
        Map<Integer, Integer> equipmentIndexList = equipmentParamService.getEquipmentIndexList();
        // TODO 根据tankCode选择对应的注料阀 S1(D5) S2(D6) S3(D7)
        try {
            // 关闭D14 N25
            Integer D14OFFParam = equipmentIndexList.get(EquipmentConstants.D14_OFF);
            boolean isD14Close;
            do {
                isD14Close = ModbusUtil.getCoilValue(1, equipmentParamList.get(D14OFFParam).getAddress());
                if (!isD14Close) {
                    EquipmentParam D14Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.D14));
                    ModbusUtil.setCoilValue(1, D14Param.getAddress(), false);
                    Thread.sleep(1000);
                }
            } while (!isD14Close); // 等待D14状态为关闭
            // 打开D5 S1进料阀
            EquipmentParam D5Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.D5));
            ModbusUtil.setCoilValue(1, D5Param.getAddress(), true);
            // 打开D6 S2进料阀
            EquipmentParam D6Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.D6));
            ModbusUtil.setCoilValue(1, D6Param.getAddress(), true);
            // 判断S1 S2压力是否平衡
            // TODO 根据tankCode选择对应的压力 S1 S2 S3
            EquipmentParam S1PressureParam = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.S1_PRESSURE));
            EquipmentParam S2PressureParam = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.S2_PRESSURE));
            float S1Pressure, S2Pressure;
            do {
                S1Pressure = ModbusUtil.getHoldingRegisterFloatValue(1, S1PressureParam.getAddress());
                S2Pressure = ModbusUtil.getHoldingRegisterFloatValue(1, S2PressureParam.getAddress());
                Thread.sleep(1000);
            } while (!(Math.abs(S1Pressure - S2Pressure) < 0.01)); // 等待压力平衡
            // 关闭D5 S1进料阀
            ModbusUtil.setCoilValue(1, D5Param.getAddress(), false);
            // 关闭D6 S2进料阀
            ModbusUtil.setCoilValue(1, D6Param.getAddress(), false);
        } catch (ModbusProtocolException | ModbusNumberException | ModbusIOException | InterruptedException e) {
            logger.error(targetTankCode + "与" + sourceTankCode + "水解罐循环流程错误", e);
            return false;
        }
        return true;
    }

    /**
     * m1负压排堵
     * @return
     */
    @Override
    public boolean negativePressureUnblock() {
        List<EquipmentParam> equipmentParamList = ModbusTcpTask.equipmentParamList;
        Map<Integer, Integer> equipmentIndexList = equipmentParamService.getEquipmentIndexList();
        try {
            // 查看M1压力
            EquipmentParam M1PressureParam = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.M1_PRESSURE));
            float M1Pressure;
            do {
                M1Pressure = ModbusUtil.getHoldingRegisterFloatValue(1, M1PressureParam.getAddress());
                Thread.sleep(1000);
            } while (!(Math.abs(M1Pressure - 0) < 0.01)); // 等待M1压力泄压
            // 关闭M1所有阀门
            // 关闭N1 M1进料阀
            EquipmentParam N1Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N1));
            ModbusUtil.setCoilValue(1, N1Param.getAddress(), false);
            // 关闭N2 J2换热阀
            EquipmentParam N2Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N2));
            ModbusUtil.setCoilValue(1, N2Param.getAddress(), false);
            // 关闭N3 J1换热阀
            EquipmentParam N3Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N3));
            ModbusUtil.setCoilValue(1, N3Param.getAddress(), false);
            // 关闭N4 M1加压阀
            EquipmentParam N4Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N4));
            ModbusUtil.setCoilValue(1, N4Param.getAddress(), false);
            // 关闭N6 M1排堵进气阀2
            EquipmentParam N6Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N6));
            ModbusUtil.setCoilValue(1, N6Param.getAddress(), false);
            // 关闭N7 M1排堵出气阀2
            EquipmentParam N7Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N7));
            ModbusUtil.setCoilValue(1, N7Param.getAddress(), false);
            // 关闭N8 M1排堵进气阀1
            EquipmentParam N8Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N8));
            ModbusUtil.setCoilValue(1, N8Param.getAddress(), false);
            // 关闭N10 M1排堵出气阀1
            EquipmentParam N10Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N10));
            ModbusUtil.setCoilValue(1, N10Param.getAddress(), false);
            // 关闭N11 M1喷淋塔
            EquipmentParam N11Param = equipmentParamList.get(equipmentIndexList.get(EquipmentConstants.N11));
            ModbusUtil.setCoilValue(1, N11Param.getAddress(), false);
            // 等待 2s
            Thread.sleep(2000);
            // 打开N8 M1排堵进气阀1
            ModbusUtil.setCoilValue(1, N8Param.getAddress(), true);
            // 每秒开关N6 5次
            for (int i = 0; i < 10; i++) {
                ModbusUtil.setCoilValue(1, N6Param.getAddress(), true);
                Thread.sleep(1000);
                ModbusUtil.setCoilValue(1, N6Param.getAddress(), false);
                Thread.sleep(1000);
            }
            // 打开N11 M1喷淋塔 等待5s
            ModbusUtil.setCoilValue(1, N11Param.getAddress(), true);
            Thread.sleep(5000);
            // 等待M1泄压
            do {
                M1Pressure = ModbusUtil.getHoldingRegisterFloatValue(1, M1PressureParam.getAddress());
                Thread.sleep(1000);
            } while (!(Math.abs(M1Pressure - 0) < 0.01)); // 等待M1压力泄压
            // 关闭N11 M1喷淋塔
            ModbusUtil.setCoilValue(1, N11Param.getAddress(), false);
            // 每秒开关N7 M1排堵出气阀2 5次
            for (int i = 0; i < 10; i++) {
                ModbusUtil.setCoilValue(1, N7Param.getAddress(), true);
                Thread.sleep(1000);
                ModbusUtil.setCoilValue(1, N7Param.getAddress(), false);
                Thread.sleep(1000);
            }
            // 打开N11 M1喷淋塔 等待5s
            ModbusUtil.setCoilValue(1, N11Param.getAddress(), true);
            Thread.sleep(5000);
            // 等待M1泄压
            do {
                M1Pressure = ModbusUtil.getHoldingRegisterFloatValue(1, M1PressureParam.getAddress());
                Thread.sleep(1000);
            } while (!(Math.abs(M1Pressure - 0) < 0.01)); // 等待M1压力泄压
        } catch (ModbusProtocolException | ModbusNumberException | ModbusIOException | InterruptedException e) {
            logger.error("m1负压排堵流程错误", e);
            return false;
        }
        return true;
    }

}