package com.bonait.bnframework.business;
import com.bonait.bnframework.common.helper.ByteHelper;
import com.bonait.bnframework.common.helper.I.IRun;
import com.bonait.bnframework.common.helper.I.IRunT;
import com.bonait.bnframework.common.helper.I.IThread;
import com.bonait.bnframework.common.helper.I.IWriteCallBack;
import com.bonait.bnframework.common.helper.MessageLog;
import com.bonait.bnframework.common.helper.RTrig;
import com.bonait.bnframework.common.helper.ThreadManager;
import com.bonait.bnframework.common.modbus.ModbusTcpServer;
import com.bonait.bnframework.common.helper.ByteHelper;
import com.bonait.bnframework.common.helper.MessageLog;
import com.bonait.bnframework.common.helper.RTrig;
import com.bonait.bnframework.common.helper.ThreadManager;

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);
    }

    public void TestInit() {
        ThreadManager.Get().StartLong("TestInit", true, new IThread() {
            @Override
            public void Run() throws InterruptedException {
                while (testComms.size() > 0) {
                    Thread.sleep(5000);
                    if (OnChargeMixtureComNotPar != null) {
                        OnChargeMixtureComNotPar.Run(testComms.poll());
                    }
                }
                Thread.sleep(100);
            }

            @Override
            public void RunComplete() throws InterruptedException {

            }
        });
        ;
    }
    //----------------------------------------------------------------End 模拟测试 ----------------------------------------------------------------

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

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

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

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

                //获取温度参数
                ModbusTcpServer.get().ReadInt("VD310", 3, ints -> {
                    FructoseTemperature1=ints[0];
                    FructoseTemperature2=ints[1];
                    WashTheTankTemperature=ints[2];
                });

                //获取温度上下限
                ModbusTcpServer.get().ReadInt("VD388", 6, ints -> {
                    FructoseTemperature1_up=ints[0];
                    FructoseTemperature1_down=ints[1];
                    FructoseTemperature2_up=ints[2];
                    FructoseTemperature2_down=ints[3];
                    WashTheTankTemperature_up=ints[4];
                    WashTheTankTemperature_down=ints[5];
                });

                //获取清洗参数
                ModbusTcpServer.get().ReadShort("VW140", 5, shorts -> {
                    DrainageTime = shorts[0];
                    AddCleaningAgentTime = shorts[1];
                    InletTime = shorts[2];
                    CyclicCleaningTime = shorts[3];
                    CleaningAndHeatingTime = shorts[4];
                });

                //获取清洗参数
                ModbusTcpServer.get().ReadBool("M6.5", 1, booleans -> {
                    WeightCalibrationMode = booleans[0];
                });

                ModbusTcpServer.get().ReadBool("M6.5", 1, booleans -> {
                    WeightCalibrationMode = booleans[0];
                });
                //IoStatus

                //读取1号果糖机按钮状态
                ModbusTcpServer.get().ReadBool("M51.7", 1, booleans -> {
                    ReheatSwitch1 = booleans[0];
                });

                //读取2号果糖机按钮状态
                ModbusTcpServer.get().ReadBool("M52.0", 1, booleans -> {
                    ReheatSwitch2 = booleans[0];
                });

                //读取当前扫码信息
                ModbusTcpServer.get().ReadString("VW342", 20, (data) -> {

                    if(!Code.equals(data))
                    {
                        if(!data.isEmpty() && OnScanTheCodeInformationT!=null)
                        {
                            MessageLog.ShowInfo("当前扫码信息:"+data);
                            OnScanTheCodeInformationT.Run(data);
                        }
                        Code=data;
                    }
                    //1.查询订单信息
                    //2.展示订单界面
                    //3.制作订单信息
                    //4.回馈订单信息
                });

                //读取实时状态
                ModbusTcpServer.get().ReadStatus("VW382", 3, data -> {
                    for (int i = 0; i < data.length; i++) {
                        byte status=data[i];//0x92
                        IoStatus.put(i*8+0, ByteHelper.getBit(status,0)==1);
                        IoStatus.put(i*8+1, ByteHelper.getBit(status,1)==1);
                        IoStatus.put(i*8+2, ByteHelper.getBit(status,2)==1);
                        IoStatus.put(i*8+3, ByteHelper.getBit(status,3)==1);
                        IoStatus.put(i*8+4, ByteHelper.getBit(status,4)==1);
                        IoStatus.put(i*8+5, ByteHelper.getBit(status,5)==1);
                        IoStatus.put(i*8+6, ByteHelper.getBit(status,6)==1);
                        IoStatus.put(i*8+7, ByteHelper.getBit(status,7)==1);
                    }
                });

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

                //清洗完成 M0.6
                CompleteListen("M0.6", "清洗完成", OnCleaningCompleteNotify);

                //去皮完成 M1.3
                CompleteListen("M1.3", "去皮完成", OnPeelingCompleteNotify);

                //扫码信号 M1.5
                //CompleteListen("M1.5", "扫码信号", OnScanTheCodeInformation);

                Thread.sleep(10);
            }

            @Override
            public void RunComplete() throws InterruptedException {

            }
        });
    }
    //endregion
    /**
     * 扫码信息
     */
    public String Code="";
    //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 OnChargeMixtureComNotPar;

    /**
     * 清洗完成通知
     */
    public IRun OnCleaningCompleteNotify;

    /**
     * 去皮完成
     */
    public IRun OnPeelingCompleteNotify;

    /**
     * 接收到扫码信息
     */
    public IRun OnScanTheCodeInformation;
    /**
     * 接收到扫码信息,返回
     */
    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" + (98 + 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" + (198 + ch * 2);
            ModbusTcpServer.get().WriteShort(add, value, callback);
        }else if(ch>=11 && ch<=12)//果糖需求
        {
            String add = "VW" + (198 +20+ 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="M03.0";
            }else if(ch==10)
            {
                add="M03.1";
            }else if(ch==11)//果糖1
            {
                add="M03.2";
            }else if(ch==12)//果糖2
            {
                add="M03.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


    /**
     * 称去皮校准
     *
     * @param value
     * @param ch    设置称的通道号，ch1-ch8
     */
    public void setRemovePeelCalibration(boolean value, int ch, IWriteCallBack callback) {
        if (ch >= 1 && ch <= 8) {
            String add = ModbusTcpServer.get().getBitSingleAdd("M", 5, ch);
            if (add.length() > 0)
                ModbusTcpServer.get().WriteBool(add, value, callback);
        }
    }

    /**
     * 砝码值写入
     *
     * @param value
     * @param ch    设置称的砝码通道号，ch1-ch8
     */
    public void setWeightValue(boolean value, int ch, IWriteCallBack callback) {
        if (ch >= 1 && ch <= 8) {
            String add = ModbusTcpServer.get().getBitSingleAdd("M", 15, ch);
            if (add.length() > 0)
                ModbusTcpServer.get().WriteBool(add, value, callback);
        }
    }

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

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

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

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

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

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

    /**
     * 砝码校准模式
     */
    public void setWeightCalibrationMode(Boolean value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M6.5", 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);
    }

    /**
     * 设置一键去皮
     */
    public void setOneClickPeeling(IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M1.2", true, callback);
    }

    /**
     * 一键去皮完成状态
     */
    boolean OneClickPeelingComplete;

    /**
     * 设置一键去皮完成状态
     *
     * @param value
     */
    public void setOneClickPeelingComplete(boolean value) {
        OneClickPeelingComplete = value;
    }

    /**
     * 清洗完成
     */
    boolean CleaningComplete;

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

    //region 获取或设置-校准模式

    /**
     * 设置校准模式
     *
     * @param value true:零点校准模式，false:清零去皮模式
     */
    public void setCalibrationMode(boolean value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteBool("M1.4", value, callback);
    }

    /**
     * 校准模式
     */
    boolean CalibrationMode;

    /**
     * 获取校准模式
     *
     * @return true:零点校准模式，false:清零去皮模式
     */
    public boolean getCalibrationMode() {
        return CalibrationMode;
    }

    //endregion



    /**
     * 称当前重量
     */
    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(int value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteInt("VD124", 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
    /**
     * 设置8路称校准砝码重量
     *
     * @param value
     */
    public void setCalibrationWeight(short value, IWriteCallBack callback) {
        ModbusTcpServer.get().WriteShort("VW250", value, callback);
    }

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

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