package com.example.bpa.modbus4j;

import android.util.Log;

import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.msg.ReadCoilsRequest;
import com.serotonin.modbus4j.msg.ReadCoilsResponse;
import com.serotonin.modbus4j.msg.ReadDiscreteInputsRequest;
import com.serotonin.modbus4j.msg.ReadDiscreteInputsResponse;
import com.serotonin.modbus4j.msg.ReadExceptionStatusRequest;
import com.serotonin.modbus4j.msg.ReadExceptionStatusResponse;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersRequest;
import com.serotonin.modbus4j.msg.ReadHoldingRegistersResponse;
import com.serotonin.modbus4j.msg.ReadInputRegistersRequest;
import com.serotonin.modbus4j.msg.ReadInputRegistersResponse;
import com.serotonin.modbus4j.msg.ReportSlaveIdRequest;
import com.serotonin.modbus4j.msg.ReportSlaveIdResponse;
import com.serotonin.modbus4j.msg.WriteCoilRequest;
import com.serotonin.modbus4j.msg.WriteCoilResponse;
import com.serotonin.modbus4j.msg.WriteCoilsRequest;
import com.serotonin.modbus4j.msg.WriteCoilsResponse;
import com.serotonin.modbus4j.msg.WriteMaskRegisterRequest;
import com.serotonin.modbus4j.msg.WriteMaskRegisterResponse;
import com.serotonin.modbus4j.msg.WriteRegisterRequest;
import com.serotonin.modbus4j.msg.WriteRegisterResponse;
import com.serotonin.modbus4j.msg.WriteRegistersRequest;
import com.serotonin.modbus4j.msg.WriteRegistersResponse;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ModbusReq {
    private static final String TAG = ModbusReq.class.getSimpleName();
    private static ModbusReq modbusReq;
    private ModbusMaster mModbusMaster;
    private ModbusParam modbusParam = new ModbusParam();
    ExecutorService executorService = Executors.newFixedThreadPool(1);
    private boolean isInit = false;

    private ModbusReq() {
    }

    public static synchronized ModbusReq getInstance() {
        if (modbusReq == null) {
            modbusReq = new ModbusReq();
        }

        return modbusReq;
    }

    public ModbusReq setParam(ModbusParam modbusParam) {
        this.modbusParam = modbusParam;
        return modbusReq;
    }

    public void init(final OnRequestBack<String> onRequestBack) {
        ModbusFactory mModbusFactory = new ModbusFactory();
        IpParameters params = new IpParameters();
        params.setHost(this.modbusParam.host);
        params.setPort(this.modbusParam.port);
        params.setEncapsulated(this.modbusParam.encapsulated);
        this.mModbusMaster = mModbusFactory.createTcpMaster(params, this.modbusParam.keepAlive);
        this.mModbusMaster.setRetries(this.modbusParam.retries);
        this.mModbusMaster.setTimeout(this.modbusParam.timeout);
        this.executorService.submit(new Runnable() {
            public void run() {
                try {
                    ModbusReq.this.mModbusMaster.init();
                } catch (ModbusInitException var2) {
                    ModbusReq.this.mModbusMaster.destroy();
                    ModbusReq.this.isInit = false;
                    Log.d(ModbusReq.TAG, "Modbus4Android init failed " + var2);
                    onRequestBack.onFailed("Modbus4Android init failed ");
                    return;
                }

                Log.d(ModbusReq.TAG, "Modbus4Android init success");
                ModbusReq.this.isInit = true;
                onRequestBack.onSuccess("Modbus4Android init success");
            }
        });
    }

    public void destory() {
        modbusReq = null;
        this.mModbusMaster.destroy();
        this.isInit = false;
    }

    public void readCoil(final OnRequestBack<boolean[]> onRequestBack, final int slaveId, final int start, final int len) {
        if (!this.isInit) {
            onRequestBack.onFailed("Modbus master is not inited successfully...");
        } else {
            this.executorService.submit(new Runnable() {
                public void run() {
                    try {
                        ReadCoilsRequest request = new ReadCoilsRequest(slaveId, start, len);
                        ReadCoilsResponse response = (ReadCoilsResponse)ModbusReq.this.mModbusMaster.send(request);
                        if (response.isException()) {
                            onRequestBack.onFailed(response.getExceptionMessage());
                        } else {
                            boolean[] booleanData = response.getBooleanData();
                            boolean[] resultByte = new boolean[len];
                            System.arraycopy(booleanData, 0, resultByte, 0, len);
                            onRequestBack.onSuccess(resultByte);
                        }
                    } catch (ModbusTransportException var5) {
                        var5.printStackTrace();
                        onRequestBack.onFailed(var5.toString());
                    }

                }
            });
        }
    }

    public void readDiscreteInput(final OnRequestBack<boolean[]> onRequestBack, final int slaveId, final int start, final int len) {
        if (!this.isInit) {
            onRequestBack.onFailed("Modbus master is not inited successfully...");
        } else {
            this.executorService.submit(new Runnable() {
                public void run() {
                    try {
                        ReadDiscreteInputsRequest request = new ReadDiscreteInputsRequest(slaveId, start, len);
                        ReadDiscreteInputsResponse response = (ReadDiscreteInputsResponse)ModbusReq.this.mModbusMaster.send(request);
                        if (response.isException()) {
                            onRequestBack.onFailed(response.getExceptionMessage());
                        } else {
                            boolean[] booleanData = response.getBooleanData();
                            boolean[] resultByte = new boolean[len];
                            System.arraycopy(booleanData, 0, resultByte, 0, len);
                            onRequestBack.onSuccess(resultByte);
                        }
                    } catch (ModbusTransportException var5) {
                        var5.printStackTrace();
                        onRequestBack.onFailed(var5.toString());
                    }

                }
            });
        }
    }

    public void readHoldingRegisters(final OnRequestBack<short[]> onRequestBack, final int slaveId, final int start, final int len) {
        if (!this.isInit) {
            onRequestBack.onFailed("Modbus master is not inited successfully...");
        } else {
            this.executorService.submit(new Runnable() {
                public void run() {
                    try {
                        ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, start, len);
                        ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse)ModbusReq.this.mModbusMaster.send(request);
                        if (response.isException()) {
                            onRequestBack.onFailed(response.getExceptionMessage());
                        } else {
                            onRequestBack.onSuccess(response.getShortData());
                        }
                    } catch (ModbusTransportException var3) {
                        var3.printStackTrace();
                        onRequestBack.onFailed(var3.toString());
                    }

                }
            });
        }
    }

    public void readInputRegisters(final OnRequestBack<short[]> onRequestBack, final int slaveId, final int start, final int len) {
        if (!this.isInit) {
            onRequestBack.onFailed("Modbus master is not inited successfully...");
        } else {
            this.executorService.submit(new Runnable() {
                public void run() {
                    try {
                        ReadInputRegistersRequest request = new ReadInputRegistersRequest(slaveId, start, len);
                        ReadInputRegistersResponse response = (ReadInputRegistersResponse)ModbusReq.this.mModbusMaster.send(request);
                        if (response.isException()) {
                            onRequestBack.onFailed(response.getExceptionMessage());
                        } else {
                            onRequestBack.onSuccess(response.getShortData());
                        }
                    } catch (ModbusTransportException var3) {
                        var3.printStackTrace();
                        onRequestBack.onFailed(var3.toString());
                    }

                }
            });
        }
    }

    public void writeCoil(final OnRequestBack<String> onRequestBack, final int slaveId, final int offset, final boolean value) {
        if (!this.isInit) {
            onRequestBack.onFailed("Modbus master is not inited successfully...");
        } else {
            this.executorService.submit(new Runnable() {
                public void run() {
                    try {
                        WriteCoilRequest request = new WriteCoilRequest(slaveId, offset, value);
                        WriteCoilResponse response = (WriteCoilResponse)ModbusReq.this.mModbusMaster.send(request);
                        if (response.isException()) {
                            onRequestBack.onFailed(response.getExceptionMessage());
                        } else {
                            onRequestBack.onSuccess("Success");
                        }
                    } catch (ModbusTransportException var3) {
                        var3.printStackTrace();
                        onRequestBack.onFailed(var3.toString());
                    }

                }
            });
        }
    }

    public void writeCoils(final OnRequestBack<String> onRequestBack, final int slaveId, final int start, final boolean[] values) {
        if (!this.isInit) {
            onRequestBack.onFailed("Modbus master is not inited successfully...");
        } else {
            this.executorService.submit(new Runnable() {
                public void run() {
                    try {
                        WriteCoilsRequest request = new WriteCoilsRequest(slaveId, start, values);
                        WriteCoilsResponse response = (WriteCoilsResponse)ModbusReq.this.mModbusMaster.send(request);
                        if (response.isException()) {
                            onRequestBack.onFailed(response.getExceptionMessage());
                        } else {
                            onRequestBack.onSuccess("Success");
                        }
                    } catch (ModbusTransportException var3) {
                        var3.printStackTrace();
                        onRequestBack.onFailed(var3.toString());
                    }

                }
            });
        }
    }

    public void writeRegister(final OnRequestBack<String> onRequestBack, final int slaveId, final int offset, final int value) {
        if (!this.isInit) {
            onRequestBack.onFailed("Modbus master is not inited successfully...");
        } else {
            this.executorService.submit(new Runnable() {
                public void run() {
                    try {
                        WriteRegisterRequest request = new WriteRegisterRequest(slaveId, offset, value);
                        WriteRegisterResponse response = (WriteRegisterResponse)ModbusReq.this.mModbusMaster.send(request);
                        if (response.isException()) {
                            onRequestBack.onFailed(response.getExceptionMessage());
                        } else {
                            onRequestBack.onSuccess("Success");
                        }
                    } catch (ModbusTransportException var3) {
                        var3.printStackTrace();
                        onRequestBack.onFailed(var3.toString());
                    }

                }
            });
        }
    }

    public void writeRegisters(final OnRequestBack<String> onRequestBack, final int slaveId, final int start, final short[] values) {
        if (!this.isInit) {
            onRequestBack.onFailed("Modbus master is not inited successfully...");
        } else {
            this.executorService.submit(new Runnable() {
                public void run() {
                    try {
                        WriteRegistersRequest request = new WriteRegistersRequest(slaveId, start, values);
                        WriteRegistersResponse response = (WriteRegistersResponse)ModbusReq.this.mModbusMaster.send(request);
                        if (response.isException()) {
                            onRequestBack.onFailed(response.getExceptionMessage());
                        } else {
                            onRequestBack.onSuccess("Success");
                        }
                    } catch (ModbusTransportException var3) {
                        var3.printStackTrace();
                        onRequestBack.onFailed(var3.toString());
                    }

                }
            });
        }
    }


    public void readExceptionStatus(final OnRequestBack<Byte> onRequestBack, final int slaveId) {
        if (!this.isInit) {
            onRequestBack.onFailed("Modbus master is not inited successfully...");
        } else {
            this.executorService.submit(new Runnable() {
                public void run() {
                    try {
                        ReadExceptionStatusRequest request = new ReadExceptionStatusRequest(slaveId);
                        ReadExceptionStatusResponse response = (ReadExceptionStatusResponse)ModbusReq.this.mModbusMaster.send(request);
                        if (response.isException()) {
                            onRequestBack.onFailed(response.getExceptionMessage());
                        } else {
                            onRequestBack.onSuccess(response.getExceptionStatus());
                        }
                    } catch (ModbusTransportException var3) {
                        var3.printStackTrace();
                        onRequestBack.onFailed(var3.toString());
                    }

                }
            });
        }
    }

    public void reportSlaveId(final OnRequestBack<byte[]> onRequestBack, final int slaveId) {
        if (!this.isInit) {
            onRequestBack.onFailed("Modbus master is not inited successfully...");
        } else {
            this.executorService.submit(new Runnable() {
                public void run() {
                    try {
                        ReportSlaveIdRequest request = new ReportSlaveIdRequest(slaveId);
                        ReportSlaveIdResponse response = (ReportSlaveIdResponse)ModbusReq.this.mModbusMaster.send(request);
                        if (response.isException()) {
                            onRequestBack.onFailed(response.getExceptionMessage());
                        } else {
                            onRequestBack.onSuccess(response.getData());
                        }
                    } catch (ModbusTransportException var3) {
                        var3.printStackTrace();
                        onRequestBack.onFailed(var3.toString());
                    }

                }
            });
        }
    }

    public void writeMaskRegister(final OnRequestBack<String> onRequestBack, final int slaveId, final int offset, final int and, final int or) {
        if (!this.isInit) {
            onRequestBack.onFailed("Modbus master is not inited successfully...");
        } else {
            this.executorService.submit(new Runnable() {
                public void run() {
                    try {
                        WriteMaskRegisterRequest request = new WriteMaskRegisterRequest(slaveId, offset, and, or);
                        WriteMaskRegisterResponse response = (WriteMaskRegisterResponse)ModbusReq.this.mModbusMaster.send(request);
                        if (response.isException()) {
                            onRequestBack.onFailed(response.getExceptionMessage());
                        } else {
                            onRequestBack.onSuccess("Success");
                        }
                    } catch (ModbusTransportException var3) {
                        var3.printStackTrace();
                        onRequestBack.onFailed(var3.toString());
                    }

                }
            });
        }
    }
}