using McProtocol.Mitsubishi;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;

namespace McProtocol
{
    /// <summary>
    /// MC协议通信帮助类
    /// </summary>
    public class McHelper : IDisposable
    {
        private McProtocolTcp plc;

        /// <summary>
        /// 构造方法
        /// </summary>
        /// <param name="ip"></param>
        /// <param name="port"></param>
        public McHelper(string ip, int port)
        {
            plc = new McProtocolTcp(ip, port, McFrame.MC3E);
        }
        public McHelper(string ip, int port, McFrame mcFrame)
        {
            plc = new McProtocolTcp(ip, port, mcFrame);
        }

        /// <summary>
        /// 建立连接
        /// </summary>
        /// <returns></returns>
        public bool Connect()
        {
            try
            {
                plc.Open();
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }

        /// <summary>
        /// 退出后销毁
        /// </summary>
        public void Dispose()
        {
            plc.Dispose();
        }


        #region Int16读写操作
        /// <summary>
        /// 读取Int16数据
        /// </summary>
        /// <param name="address">地址：例如 D10</param>
        /// <param name="value">返回数据</param>
        /// <returns>读取成功还是失败</returns>
        public bool ReadInt16(string address, out short value)
        {

            short[] values = new short[1];
            bool flag = ReadInts16(address, 1, out values);
            if (!flag)
            {
                value = 0;
                return false;
            }
            value = values[0];
            return true;

        }

        /// <summary>
        /// 读取Int16数据
        /// </summary>
        /// <param name="address">地址：例如 D10</param>
        /// <param name="count">读取长度</param>
        /// <param name="values">返回数据</param>
        /// <returns>读取成功还是失败</returns>
        public bool ReadInts16(string address, int count, out short[] values)
        {
            try
            {
                //地址解析
                values = plc.ReadInt16(address, count);
                return true;
            }
            catch (Exception ex)
            {
                values = null;
                return false;
            }
        }

        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="address">地址D100</param>
        /// <param name="value">写入数据</param>
        /// <returns>写入成功还是失败</returns>
        public bool WriteInt16(string address, short value)
        {
            short[] values = new short[1];
            values[0] = value;
            return WriteInts16(address, values);

        }

        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="address">地址D100</param>
        /// <param name="values">写入数据</param>
        /// <returns>写入成功还是失败</returns>
        public bool WriteInts16(string address, short[] values)
        {
            try
            {
                plc.WriteInt16(address, values);
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        #endregion

        #region UInt16读写操作
        /// <summary>
        /// 读取UInt16数据
        /// </summary>
        /// <param name="address">例如 D10</param>
        /// <param name="value">返回数据</param>
        /// <returns>读取成功还是失败</returns>
        public bool ReadUInt16(string address, out ushort value)
        {
            ushort[] values = new ushort[1];
            bool flag = ReadUInts16(address, 1, out values);
            if (!flag)
            {
                value = 0;
                return false;
            }
            value = values[0];
            return true;
        }


        /// <summary>
        /// 读取UInt16数据
        /// </summary>
        /// <param name="address">例如 D10</param>
        /// <param name="count">读取数量</param>
        /// <param name="values">返回数据</param>
        /// <returns>读取成功还是失败</returns>
        public bool ReadUInts16(string address, int count, out ushort[] values)
        {
            try
            {
                values = plc.ReadUInt16(address, count);
                return true;
            }
            catch (Exception ex)
            {
                values = null;
                return false;
            }
        }

        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="address">地址D100</param>
        /// <param name="value">写入数据</param>
        /// <returns>写入成功还是失败</returns>
        public bool WriteUInt16(string address, ushort value)
        {

            ushort[] values = new ushort[1];
            values[0] = value;
            return WriteUInts16(address, values);
        }

        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="address">地址D100</param>
        /// <param name="values">写入数据</param>
        /// <returns>写入成功还是失败</returns>
        public bool WriteUInts16(string address, ushort[] values)
        {
            try
            {
                plc.WriteUInt16(address, values);
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        #endregion

        #region Int32读写操作
        /// <summary>
        /// 读取Int32
        /// </summary>
        /// <param name="address">例如 D10</param>
        /// <param name="value">返回数据</param>
        /// <returns>读取成功还是失败</returns>
        public bool ReadInt32(string address, out int value)
        {
            int[] values;
            bool flag = ReadInts32(address, 1, out values);
            if (!flag)
            {
                value = 0;
                return false;
            }
            value = values[0];
            return true;

        }


        /// <summary>
        /// 读取Int32
        /// </summary>
        /// <param name="address">例如 D10</param>
        /// <param name="count">读取数量</param>
        /// <param name="values">返回数据</param>
        /// <returns>读取成功还是失败</returns>
        public bool ReadInts32(string address, int count, out int[] values)
        {
            try
            {
                //地址解析
                values = plc.ReadInt32(address, count);
                return true;
            }
            catch (Exception ex)
            {
                values = null;
                return false;
            }
        }

        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="address">地址D100</param>
        /// <param name="value">写入数据</param>
        /// <returns>写入成功还是失败</returns>
        public bool WriteInt32(string address, int value)
        {
            int[] values = new int[1];
            values[0] = value;
            return WriteInts32(address, values);
        }
        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="address">地址D100</param>
        /// <param name="values">写入数据</param>
        /// <returns>写入成功还是失败</returns>
        public bool WriteInts32(string address, int[] values)
        {
            try
            {
                plc.WriteInt32(address, values);
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        #endregion

        #region UInt32读写操作
        /// <summary>
        /// 读取UInt32
        /// </summary>
        /// <param name="address">例如 D10</param>
        /// <param name="value">返回数据</param>
        /// <returns>读取成功还是失败</returns>
        public bool ReadUInt32(string address, out uint value)
        {

            uint[] values = new uint[1];
            bool flag = ReadUInts32(address, 1, out values);
            if (!flag)
            {
                value = 0;
                return false;
            }
            value = values[0];
            return true;

        }
        /// <summary>
        /// 读取UInt32
        /// </summary>
        /// <param name="address">例如 D10</param>
        /// <param name="count">读取数量</param>
        /// <param name="values">返回数据</param>
        /// <returns>读取成功还是失败</returns>
        public bool ReadUInts32(string address, int count, out uint[] values)
        {
            try
            {
                //地址解析
                values = plc.ReadUInt32(address, count);
                return true;
            }
            catch (Exception ex)
            {
                values = null;
                return false;
            }
        }

        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="address">地址D100</param>
        /// <param name="value">写入数据</param>
        /// <returns>写入成功还是失败</returns>
        public bool WriteUInt32(string address, uint value)
        {

            uint[] values = new uint[1];
            values[0] = value;
            return WriteUInts32(address, values);

        }

        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="address">地址D100</param>
        /// <param name="values">写入数据</param>
        /// <returns>写入成功还是失败</returns>
        public bool WriteUInts32(string address, uint[] values)
        {
            try
            {
                plc.WriteUInt32(address, values);
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        #endregion

        #region Float读写操作
        /// <summary>
        /// 读取Float
        /// </summary>
        /// <param name="address">例如 D10</param>
        /// <param name="value">返回数据</param>
        /// <returns>读取成功还是失败</returns>
        public bool ReadFloat(string address, out float value)
        {
            float[] values;
            bool flag = ReadFloats(address, 1, out values);
            if (!flag)
            {
                value = 0;
                return false;
            }
            value = values[0];
            return true;
        }
        /// <summary>
        /// 读取Float
        /// </summary>
        /// <param name="address">例如 D10</param>
        /// <param name="count">读取数量</param>
        /// <param name="values">返回数据</param>
        /// <returns>读取成功还是失败</returns>
        public bool ReadFloats(string address, int count, out float[] values)
        {
            try
            {
                //地址解析
                values = plc.ReadFloat(address, count);
                return true;
            }
            catch (Exception ex)
            {
                values = null;
                return false;
            }
        }

        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="address">地址D100</param>
        /// <param name="value">写入数据</param>
        /// <returns>写入成功还是失败</returns>
        public bool WriteFloat(string address, float value)
        {
            float[] values = new float[1];
            values[0] = value;
            return WriteFloats(address, values);
        }

        /// <summary>
        /// 写入数据
        /// </summary>
        /// <param name="address">地址D100</param>
        /// <param name="values">写入数据</param>
        /// <returns>写入成功还是失败</returns>
        public bool WriteFloats(string address, float[] values)
        {
            try
            {
                plc.WriteFloat(address, values);
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        #endregion

        #region String读写操作 
        /// <summary>
        /// 读取字符串
        /// </summary>
        /// <param name="address">地址，例如:D3200</param>
        /// <param name="length">此处为地址长度，例50，表示字符串长度100</param>
        /// <param name="str">读到的字符串</param>
        /// <returns>返回读取成功还是失败</returns>
        public bool ReadString(string address, int length, out string str)
        {
            try
            {
                ushort[] value = new ushort[length];
                byte[] values = plc.ReadDeviceBlock(address, length, value);
                List<byte> bytes = new List<byte>();
                foreach (var item in value)
                {
                    bytes.AddRange(BitConverter.GetBytes(item));
                }
                str = Encoding.GetEncoding("GB2312").GetString(bytes.ToArray());
                return true;
            }
            catch (Exception ex)
            {
                str = string.Empty;
                return false;
            }
        }

        /// <summary>
        /// 写入字符串
        /// </summary>
        /// <param name="address">地址，例如:D3200</param>
        /// <param name="length">此处为地址长度，例50，表示字符串长度100</param>
        /// <param name="str">写入的字符串</param>
        /// <returns>返回写入成功还是失败</returns>
        public bool WriteString(string address, int length, string str)
        {
            try
            {
                byte[] Bytes = new byte[length * 2];
                byte[] bytes = Encoding.GetEncoding("GB2312").GetBytes(str);
                if (bytes.Length > Bytes.Length)
                {
                    for (int i = 0; i < Bytes.Length; i++)
                    {
                        Bytes[i] = bytes[i];
                    }
                }
                else
                {
                    for (int i = 0; i < bytes.Length; i++)
                    {
                        Bytes[i] = bytes[i];
                    }
                }
                ushort[] value = new ushort[length];
                for (int i = 0; i < length; i++)
                {
                    value[i] = BitConverter.ToUInt16(Bytes, i * 2);
                }
                plc.WriteDeviceBlock(address, value);
                return true;
            }
            catch (Exception ex)
            {
                return false;
            }
        }
        #endregion



    }
}
