using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Runtime.InteropServices;

namespace GcDevicePc.Common
{
    class GCModbus
    {
        [DllImport(@"LibModbus.dll", EntryPoint = "fnLibModbus", CharSet = CharSet.Unicode)]
        public static extern uint fnLibModbus();
        [DllImport(@"LibModbus.dll", EntryPoint = "fnReadCoilStatus")]
        public static extern int fnReadCoilStatus(uint handle, byte slaveaddress, ushort address, ushort num, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] System.Byte[] dest, byte[] Ip, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnReadInputStatus")]
        public static extern int fnReadInputStatus(uint handle, byte slaveaddress, ushort address, ushort num, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] System.Char[] dest, byte[] Ip, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnReadHoldingReg")]
        public static extern int fnReadHoldingReg(uint handle, byte slaveaddress, ushort address, ushort num, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] System.UInt16[] dest, byte[] Ip, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnReadInputReg")]
        public static extern int fnReadInputReg(uint handle, byte slaveaddress, ushort address, ushort num, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] System.UInt16[] dest, byte[] Ip, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnWriteSingleCoil")]
        public static extern int fnWriteSingleCoil(uint handle, byte slaveaddress, ushort address, ushort state, byte[] Ip, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnWriteHoldingReg")]
        public static extern int fnWriteHoldingReg(uint handle, byte slaveaddress, ushort address, ushort state, byte[] Ip, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnWriteMultipleCoils")]
        public static extern int fnWriteMultipleCoils(uint handle, byte slaveaddress, ushort address, ushort num, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] System.Char[] src, byte[] Ip, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnWriteMultipleRegs")]
        public static extern int fnWriteMultipleRegs(uint handle, byte slaveaddress, ushort address, ushort num, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] System.UInt16[] src, byte[] Ip, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnReportSlaveID")]
        public static extern int fnReportSlaveID(uint handle, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] System.Char[] src, byte[] Ip, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnMaskWriteReg")]
        public static extern int fnMaskWriteReg(uint handle, byte slaveaddress, ushort address, ushort amask, ushort omask, byte[] Ip, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnReadWriteMultipleRegs")]
        public static extern int fnReadWriteMultipleRegs(uint handle, byte slaveaddress, ushort waddress, ushort wnum, ushort raddress, ushort rnum, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 1)] System.UInt16[] dest, byte[] Ip, ushort wTcpPort);
        [DllImport(@"LibModbus.dll", EntryPoint = "fnLibModbusClose")]
        public static extern void fnLibModbusClose(uint handle);

        private uint hModbusHandle;
        private System.UInt16[] dest = new System.UInt16[10] { 0, 0, 3, 4, 5, 6, 7, 8, 9, 0 };

        public GCModbus()
        {
            try
            {
                this.hModbusHandle = fnLibModbus();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
           
        }


        public int GCModbusClose()
        {
            try
            {
                fnLibModbusClose(hModbusHandle);
                return 0;
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
                return -1;
            }

        }



        ~GCModbus()
        {
            try
            {
                fnLibModbusClose(hModbusHandle);
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
            
        }
     
        public int ReadCoilStatus(ushort addr, ushort num, String ip, ushort wport, ref byte[] buf)
        {
            int ret;
            byte[] bIp = Encoding.Unicode.GetBytes(ip);
            ret = fnReadCoilStatus(hModbusHandle,1, (ushort)(addr - 1), num, buf, bIp, wport);     
            return ret;
        }

        public int ReadInputStatus(ushort addr, ushort num, String ip, ushort wport, ref char[] buf)
        {
            int ret;
            byte[] bIp = Encoding.Unicode.GetBytes(ip);
            ret = fnReadInputStatus(hModbusHandle,1, addr, 1, buf, bIp, 502);
            return ret;
        }

        public int ReadHoldingReg(ushort addr, ushort num, String ip, ushort wport, ref UInt16[] buf)
        {
            int ret;
            byte[] bIp = Encoding.Unicode.GetBytes(ip);
            ret = fnReadHoldingReg(hModbusHandle,1, (ushort)(addr - 1), num, buf, bIp, wport);
            return ret;
        }

        public int ReadInputReg(ushort addr, ushort num, String ip, ushort wport, ref UInt16[] buf)
        {
            int ret;
            byte[] bIp = Encoding.Unicode.GetBytes(ip);
            ret = fnReadInputReg(hModbusHandle, 1,addr, 1, dest, bIp, 502);
            buf[0] = dest[0];
            return ret;
        }

        public int WriteSingleCoil(ushort addr, ushort state, String ip, ushort wport)
        {
            int ret = 0;
            byte[] bIp = Encoding.Unicode.GetBytes(ip);
            ret = fnWriteSingleCoil(hModbusHandle, 1, (ushort)(addr - 1), state, bIp, wport);
            return ret;
        }

        public int WriteHoldingReg(ushort addr, ushort state, String ip, ushort wport)
        {
            int ret = 0;
            byte[] bIp = Encoding.Unicode.GetBytes(ip);
            ret = fnWriteHoldingReg(hModbusHandle,1, (ushort)(addr - 1), state, bIp, wport);
            return ret;
        }

        public int WriteMultipleRegs(ushort addr, ushort num, String ip, ushort wport, ref ushort[] buf)
        {
            int ret;
            byte[] bIp = Encoding.Unicode.GetBytes(ip);
            ret = fnWriteMultipleRegs(hModbusHandle,1, (ushort)(addr - 1), num, buf, bIp, wport);
            return ret;
        }

        public int ReportSlaveID(ushort addr, ushort num, String ip, ushort wport, ref char[] buf)
        {
            int ret;
            byte[] bIp = Encoding.Unicode.GetBytes(ip);
            ret = fnReportSlaveID(hModbusHandle, buf, bIp, 502);
            return ret;
        }

        public int MaskWriteReg(ushort addr, ushort amask, ushort omask, String ip, ushort wport)
        {
            int ret = 0;
            byte[] bIp = Encoding.Unicode.GetBytes(ip);
            ret = fnMaskWriteReg(hModbusHandle, 1, addr, amask, omask, bIp, 502);
            return ret;
        }

        public int ReadWriteMultipleRegs(ushort waddr, ushort wnum, ushort raddr, ushort rnum, String ip, ushort wport,ref UInt16[] buf)
        {
            int ret = 0;
            byte[] bIp = Encoding.Unicode.GetBytes(ip);
            ret = fnReadWriteMultipleRegs(hModbusHandle, 1, waddr, wnum, raddr, rnum, buf, bIp, 502);
            return ret;
        }

    }
}
