package com.example.bpa.service;

import com.example.bpa.Model.IRun;
import com.example.bpa.Model.IRunT;
import com.example.bpa.Model.IThread;
import com.example.bpa.Model.IWriteCallBack;
import com.example.bpa.helper.ByteHelper;
import com.example.bpa.helper.MessageLog;
import com.example.bpa.helper.ModbusTcpServer;
import com.example.bpa.helper.RTrig;
import com.example.bpa.helper.ThreadManager;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;

public class DeviceData {
    private static volatile DeviceData _instance;

    public static DeviceData Get() {
        if (_instance == null)
            _instance = new DeviceData();
        return _instance;

    }


    //----------------------------------------------------------------Start 模拟测试 ----------------------------------------------------------------
    ConcurrentLinkedQueue<Integer> testComms = new ConcurrentLinkedQueue<>();

    public void testAddComm(int value) {
        testComms.offer(value);
    }
    //----------------------------------------------------------------End 模拟测试 ----------------------------------------------------------------

    //region 初始化
    public void Init() {
        ThreadManager.Get().StartLong("Plc设备数据监听", true, new IThread() {
            @Override
            public void Run() throws InterruptedException {

                //获取校准值-增加两个果糖通道
                ModbusTcpServer.get().ReadShort("VW0", 12, (shorts) -> {
                    for (int i = 0; i < shorts.length; i++) {
                        CalibrationValue.put(i + 1, shorts[i]);
                    }
                });

                //获取称当前重量
                ModbusTcpServer.get().ReadInt("VD356", 1, ints -> {
                    for (int i = 0; i < ints.length; i++) {
                        CallCurrentWeight.put(i + 1, ints[i]);
                    }
                });

                //获取校准基准时间
                ModbusTcpServer.get().ReadShort("VW26", 1, (shorts) -> {
                    CalibrationReferenceTime = shorts[0];
                });

                //获取温度参数 保温池温度、加热箱温度
                ModbusTcpServer.get().ReadInt("VD364", 2, ints -> {
                    BWX_FructoseTemperature=ints[0];
                    JRX_FructoseTemperature=ints[1];
                });

                //获取校准模式
                ModbusTcpServer.get().ReadBool("M1.0", 1, booleans -> {
                    WeightCalibrationMode = booleans[0];
                });

                //读取手动模式状态
                ModbusTcpServer.get().ReadBool("M50.0", 1, booleans -> {
                    WeightCalibrationMode = booleans[0];
                });

                //读取手动模式状态
                ModbusTcpServer.get().ReadBool("M50.0", 28, booleans -> {
                    for (int i=0;i<booleans.length;i++)
                    {
                        ManualValue.put(i,booleans[i]);
                    }
                });

                //读取自动模式状态
                ModbusTcpServer.get().ReadBool("M100.0", 28, booleans -> {
                    for (int i=0;i<booleans.length;i++)
                    {
                        AutomationValue.put(i,booleans[i]);
                    }
                });

                //配料完成 M0.3
                CompleteListen("M0.3", "配料完成", OnChargeMixtureCompleteNotify);

                Thread.sleep(10);
            }

            @Override
            public void RunComplete() throws InterruptedException {

            }
        });
    }
    //endregion
    //region 完成信号监听
    /**
     * 完成信号监听
     *
     * @param add      监听地址
     * @param name     监听 KEY
     * @param callback 执行委托
     */
    private void CompleteListen(String add, String name, IRun callback) {
        ModbusTcpServer.get().ReadBool(add, 1, booleans -> {
            RTrig.get(name).Start(booleans[0], () -> {
                if (callback != null)
                    callback.Run();
            });
        });
    }
    //endregion

    // region 通知接口
    /**
     * 配料完成通知
     */
    public IRun OnChargeMixtureCompleteNotify;
    /**
     * 接收到扫码信息,返回
     */
    public IRunT<String> OnScanTheCodeInformationT;
    //endregion

    /**
     * 校准值写入
     * PLC 地址VW100--VW118
     *
     * @param value 需要写入的值
     * @param ch    需要写入的通道编号，1--10
     */
    public void setCalibrationValue(short value, int ch, IWriteCallBack callback) {
        if (ch >= 1 && ch <= 12) {
            String add = "VW" + (-2 + ch * 2);
            ModbusTcpServer.get().WriteShort(add, value, callback);
        }
    }

    /**
     * 校准值
     */
    ConcurrentHashMap<Integer, Short> CalibrationValue = new ConcurrentHashMap<>();

    /**
     * 获取校准值
     *
     * @param ch 要获取的通道号
     * @return
     */
    public short getCalibrationValue(int ch) {
        if (!CalibrationValue.containsKey(ch))
            return 0;
        return CalibrationValue.get(ch);
    }

    /**
     * 需求值写入
     * ,PLC 地址 VW200--VW218
     *
     * @param value 需要写入的值
     * @param ch    需要写入的通道编号，1--10
     */
    public void setDemandValue(short value, int ch, IWriteCallBack callback) {
        if (ch >= 1 && ch <= 10) {
            String add = "VW" + (298 + ch * 2);
            ModbusTcpServer.get().WriteShort(add, value, callback);
        }
    }

    /**
     * 设置通道校准开关
     * ,PLC 地址 M2.0--M3.1
     *
     * @param value 需要写入的值
     * @param ch    需要写入的通道编号，1--10
     */
    public void setChCalibrationSwitch(boolean value, int ch, IWriteCallBack callback) {
        if (ch >= 1 && ch <= 12) {
            String add="";
            if(ch==9)
            {
                add="M3.0";
            }else if(ch==10)
            {
                add="M3.1";
            }else if(ch==11)
            {
                add="M3.2";
            }else if(ch==12)
            {
                add="M3.3";
            }else
            {
                add = ModbusTcpServer.get().getBitSingleAdd("M", 2, ch);
            }
            if (add.length() > 0)
                ModbusTcpServer.get().WriteBool(add, value, callback);
        }
    }

    //region 手动控制
    /**
     * 手动控制设备
     * @param value
     * @param ch
     * @param callback
     */
    public void setSwitch(boolean value, String ch, IWriteCallBack callback) {
        if(ch.isEmpty())
        {
            return;
        }
        String add=ch;
        if (add.length() > 0)
            ModbusTcpServer.get().WriteBool(add, value, callback);
    }
    //endregion

    /**
     * 重量清零
     */
    public void setWeightClear(IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M1.1", true, callback);
    }

    /**
     * 关闭写保护
     */
    public void setCloseWriteProtect(IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M1.2", true, callback);
    }

    /**
     * 打开写保护
     */
    public void setOpenWriteProtect(IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M1.5", true, callback);
    }

    /**
     * 零点校准
     */
    public void setZeroPointCalibration(IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M1.3", true, callback);
    }

    /**
     * 砝码值写入
     */
    public void setWeightValueWrite(IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M1.4", true, callback);
    }

    /**
     * 砝码校准模式
     */
    boolean WeightCalibrationMode;

    /**
     * 砝码校准模式
     */
    public void setWeightCalibrationMode(Boolean value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M1.0", value, callback);
    }

    /**
     * 获取砝码校准模式
     *
     * @return
     */
    public boolean getWeightCalibrationMode() {
        return WeightCalibrationMode;
    }

    /**
     * 启动通道校准
     */
    public void setChStartCalibration(IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M0.0", true, callback);
    }

    /**
     * 启动配料
     */
    public void setChargeMixtureStart(IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M0.1", true, callback);
    }

    /**
     * 手自动切换
     *
     * @param value true:自动模式，flase:手动模式
     */
    public void setHandOrAutoSwitch(boolean value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M0.2", value, callback);
    }

    /**
     * 手自动模式
     */
    boolean HandOrAutoMode;

    /**
     * 获取手自动模式的状态
     *
     * @return true:自动模式，flase:手动模式
     */
    public boolean getHandOrAutoSwitch() {
        return HandOrAutoMode;
    }

    /**
     * 设置清洗模式
     *
     * @param value true:清洗模式，false:配料模式
     */
    public void setCleaningMode(boolean value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M0.4", value, callback);
    }

    /**
     * 清洗模式
     */
    boolean CleaningMode;
    /**
     * 获取清洗模式
     *
     * @return true:清洗模式，false:配料模式
     */
    public boolean getCleaningMode() {
        return CleaningMode;
    }

    /**
     * 设置开始清洗
     */
    public void setStartCleaning(IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M0.5", true, callback);
    }
    /**
     * 清洗完成
     */
    boolean CleaningComplete;

    /**
     * 获取清洗完成的状态
     *
     * @return
     */
    public boolean getCleaningComplete() {
        return CleaningComplete;
    }

    /**
     * 称当前重量
     */
    ConcurrentHashMap<Integer, Integer> CallCurrentWeight = new ConcurrentHashMap<Integer, Integer>();

    /**
     * 获取指定称的当前重量
     *
     * @param ch 需要获取的通道号，称1--称9
     * @return
     */
    public int getCallCurrentWeight(int ch) {
        if (!CallCurrentWeight.containsKey(ch)) {
            return 0;
        }
        return CallCurrentWeight.get(ch);
    }

    //region 获取或设置-校准基准时间

    /**
     * 设置校准基准时间
     *
     * @param value 需要写入的值
     */
    public void setCalibrationReferenceTime(short value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteShort("VW26", value, callback);
    }

    /**
     * 校准基准时间
     */
    int CalibrationReferenceTime=0;

    /**
     * 获取校准基准时间
     *
     * @return
     */
    public int getCalibrationReferenceTime() {
        return CalibrationReferenceTime;
    }

    //endregion

    //region 获取或设置-排水时间

    /**
     * 设置排水时间
     *
     * @param value
     */
    public void setDrainageTime(short value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteShort("VW140", value, callback);
    }

    /**
     * 排水时间
     */
    short DrainageTime;

    /**
     * 获取排水时间
     *
     * @return
     */
    public short getDrainageTime() {
        return DrainageTime;
    }

    //endregion

    //region 获取或设置-清洗剂添加时间

    /**
     * 设置清洗剂添加时间
     *
     * @param value
     */
    public void setAddCleaningAgentTime(short value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteShort("VW142", value, callback);
    }

    /**
     * 清洗剂添加时间
     */
    short AddCleaningAgentTime;

    /**
     * 获取清洗剂添加时间
     *
     * @return
     */
    public short getAddCleaningAgentTime() {
        return AddCleaningAgentTime;
    }

    //endregion

    //region 获取或设置-进水时间

    /**
     * 设置进水时间
     *
     * @param value
     */
    public void setInletTime(short value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteShort("VW144", value, callback);
    }

    /**
     * 进水时间
     */
    short InletTime;

    /**
     * 获取进水时间
     *
     * @return
     */
    public short getInletTime() {
        return InletTime;
    }

    //endregion

    //region 获取或设置-循环清洗时间

    /**
     * 设置循环清洗时间
     *
     * @param value
     */
    public void setCyclicCleaningTime(short value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteShort("VW146", value, callback);
    }

    /**
     * 循环清洗时间
     */
    short CyclicCleaningTime;

    /**
     * 获取循环清洗时间
     *
     * @return
     */
    public short getCyclicCleaningTime() {
        return CyclicCleaningTime;
    }
    //endregion

    //region 获取或设置-清洗加热时间

    /**
     * 设置清洗加热时间
     *
     * @param value
     */
    public void setCleaningAndHeatingTime(short value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteShort("VW148", value, callback);
    }

    /**
     * 清洗加热时间
     */
    short CleaningAndHeatingTime;

    /**
     * 获取清洗加热时间
     *
     * @return
     */
    public short getCleaningAndHeatingTime() {
        return CleaningAndHeatingTime;
    }
    //endregion

    //region 获取温度信息
    /**
     * 果糖1实际温度
     */
    Boolean ReheatSwitch1=false;
    int FructoseTemperature1=0;
    int FructoseTemperature1_up=0;
    int FructoseTemperature1_down=0;
    /**
     * 设置果糖1号加热启动停止
     *
     * @param value true:启动，flase:停止
     */
    public void setReheatSwitch1(boolean value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M51.7", value, callback);
    }
    public boolean getReheatSwitch1() {
        return ReheatSwitch1;
    }
    /**
     * 设置获取果糖1上下线
     * @param value_up 上限
     * @param value_down 下限
     * @param callback
     */
    public void setFructoseTemperature1(int value_up,int value_down, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteInt("VD388", value_up, callback);
        ModbusTcpServer.get().WriteInt("VD392", value_down, callback);
    }
    /**
     * 获取果糖1实际温度
     *
     * @return
     */
    public int getFructoseTemperature1() {
        return FructoseTemperature1;
    }
    /**
     * 获取果糖1上限
     *
     * @return
     */
    public int getFructoseTemperature1_up() {
        return FructoseTemperature1_up;
    }
    /**
     * 获取果糖1下限
     *
     * @return
     */
    public int getFructoseTemperature1_down() {
        return FructoseTemperature1_down;
    }
    /**
     * 果糖2实际温度
     */
    Boolean ReheatSwitch2=false;
    int FructoseTemperature2=0;
    int FructoseTemperature2_up=0;
    int FructoseTemperature2_down=0;
    /**
     * 设置果糖2号加热启动停止
     *
     * @param value true:启动，flase:停止
     */
    public void setReheatSwitch2(boolean value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M52.0", value, callback);
    }
    public boolean getReheatSwitch2() {
        return ReheatSwitch2;
    }
    /**
     * 设置获取果糖2上下线
     * @param value_up 上限
     * @param value_down 下限
     * @param callback
     */
    public void setFructoseTemperature2(int value_up,int value_down, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteInt("VD396", value_up, callback);
        ModbusTcpServer.get().WriteInt("VD400", value_down, callback);
    }
    /**
     * 获取果糖2实际温度
     *
     * @return
     */
    public int getFructoseTemperature2() {
        return FructoseTemperature2;
    }
    /**
     * 获取果糖2上限
     *
     * @return
     */
    public int getFructoseTemperature2_up() {
        return FructoseTemperature2_up;
    }
    /**
     * 获取果糖2下限
     *
     * @return
     */
    public int getFructoseTemperature2_down() {
        return FructoseTemperature2_down;
    }
    /**
     * 清洗池实际温度
     */
    int WashTheTankTemperature=0;
    int WashTheTankTemperature_up=0;
    int WashTheTankTemperature_down=0;
    /**
     * 设置清洗池实际温度上下线
     * @param value_up 上限
     * @param value_down 下限
     * @param callback
     */
    public void setWashTheTankTemperature(int value_up,int value_down, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteInt("VD404", value_up, callback);
        ModbusTcpServer.get().WriteInt("VD408", value_down, callback);
    }
    /**
     * 清洗池实际温度
     *
     * @return
     */
    public int getWashTheTankTemperature() {
        return WashTheTankTemperature;
    }
    /**
     * 获取清洗池实际温度上限
     *
     * @return
     */
    public int getWashTheTankTemperature_up() {
        return WashTheTankTemperature_up;
    }
    /**
     * 获取清洗池实际温度下限
     *
     * @return
     */
    public int getWashTheTankTemperature_down() {
        return WashTheTankTemperature_down;
    }
    //endregion

    //region 实时状态
    /**
     * 实时状态
     */
    public ConcurrentHashMap<Integer, Boolean> IoStatus = new ConcurrentHashMap<Integer, Boolean>();
    /**
     * 获取实时状态
     * @param ch
     * @return
     */
    public boolean getConcurrentHash(int ch) {
        if (!IoStatus.containsKey(ch)) {
            return false;
        }
        return IoStatus.get(ch);
    }
    //endregion

    //region 设置出料口称重
    /**
     * 设置称重9校准砝码重量
     *
     * @param value
     */
    public void setCalibrationWeight9(short value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteShort("VW30", value, callback);
    }

    /**
     * 扫码清零
     */
    public void setCodeClear(IWriteCallBack callback) {
        ModbusTcpServer.get().WriteString("VW342", 20, callback);
    }
    //endregion

    //region 获取或设置保温箱温度信息
    /**
     * 水箱
     */
    int BWX_FructoseTemperature=0;
    /**
     * 水箱
     */
    int BWX_FructoseTemperature_sz=0;
    /**
     * 获取水箱实际温度
     *
     * @return
     */
    public int getBWX_FructoseTemperature() {
        return BWX_FructoseTemperature;
    }
    /**
     * 获取水箱实际温度保温温度
     *
     * @return
     */
    public int getBWX_FructoseTemperatureSZ() {
        return BWX_FructoseTemperature_sz;
    }
    public void setBWX_FructoseTemperature(int value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteInt("VD372", value, callback);
    }
    /**
     * 设置水箱加热启动停止
     *
     * @param value true:启动，flase:停止
     */
    public void setBWXSwitch(boolean value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M102.0", value, callback);
    }
    /**
     * 加热箱
     */
    int JRX_FructoseTemperature=0;
    /**
     * 加热箱
     */
    int JRX_FructoseTemperature_sz=0;
    /**
     * 获取加热箱实际温度
     *
     * @return
     */
    public int getJRX_FructoseTemperature() {
        return JRX_FructoseTemperature;
    }
    /**
     * 获取加热箱实际温度
     *
     * @return
     */
    public int getJRX_FructoseTemperatureSZ() {
        return JRX_FructoseTemperature_sz;
    }
    public void setJRX_FructoseTemperature(int value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteInt("VD380", value, callback);
    }
    /**
     * 设置加热箱加热启动停止
     *
     * @param value true:启动，flase:停止
     */
    public void setJRXSwitch(boolean value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M103.1", value, callback);
    }
    //endregion

    //region 手动或自动状态监控
    /**
     * 手动值
     */
    ConcurrentHashMap<Integer, Boolean> ManualValue = new ConcurrentHashMap<>();
    /**
     * 自动值
     */
    ConcurrentHashMap<Integer, Boolean> AutomationValue = new ConcurrentHashMap<>();
    /**
     * 获取手动
     * @param addr
     * @return
     */
    public boolean getManualValue(String addr) {
        int index= GetAddressIndex(addr);
        if (!ManualValue.containsKey(index))
            return false;
        return ManualValue.get(index);
    }
    /**
     * 获取自动
     * @param addr
     * @return
     */
    public boolean getAutomationValue(String addr) {
        int index= GetAddressIndex(addr);
        if (!AutomationValue.containsKey(index))
            return false;
        return AutomationValue.get(index);
    }
    /**
     * 获取地址顺序
     * @param address
     * @return
     */
    private int GetAddressIndex(String address) {
        //put("M51.2",10);// 1*8+2 =10
        if (address == null) return -1;
        if (address.length() > 0) {
            address = address.trim();
            if (address.toUpperCase().contains("M") && address.length() >= 4) {
                String[] res = address.substring(1).split("[.]");
                if (res != null && res.length == 2) {
                    try {
                        //int a= intNum%10;//个
                        int firstAdd = Integer.parseInt(res[0])%10;//51  1
                        int endAdd = Integer.parseInt(res[1]);//2
                        return firstAdd*8+endAdd;
                    } catch (NumberFormatException e) {
                        return -1;
                    }
                }
            }
        }
        return -1;
    }
    //endregion

}
