using HslCommunication;
using HslCommunication.Profinet;
using HslCommunication.Profinet.Melsec;
using log4net;
using System;
using System.Text;
using System.Threading.Tasks;

namespace Aucma.Core.PLc
{
    /// <summary>
    /// 三菱PLC
    /// </summary>
    public class MelsecPlc : IPlc
    {
        private  readonly log4net.ILog log = LogManager.GetLogger(typeof(MelsecPlc));
        private MelsecMcNet melsecMcNet = null;

        #region 构造函数
        //public MelsecPlc()
        //{
        //    if (!HslCommunication.Authorization.SetAuthorizationCode("ed1415f8-e06a-43ad-95f7-c04f7ae93b41"))
        //    {
        //        //log.Info("HslCommunication激活失败");
        //        return;
        //    }
        //    Console.WriteLine("HslCommunication激活成功!");
        //    melsecMcNet = new MelsecMcNet();
        //    melsecMcNet.ConnectTimeOut = 2000;
        //} 
        public MelsecPlc(string iP, int port)
        {
            if (!HslCommunication.Authorization.SetAuthorizationCode("ed1415f8-e06a-43ad-95f7-c04f7ae93b41"))
            {
                //log.Info("HslCommunication激活失败");
                return;
            }
            Console.WriteLine("HslCommunication激活成功!");
            melsecMcNet = new MelsecMcNet();
            melsecMcNet.ConnectTimeOut = 2000;
            Connect(iP, port);//建立连接
        }
        #endregion

        #region 注册
        public bool Registed()
        {
            if (!HslCommunication.Authorization.SetAuthorizationCode("ed1415f8-e06a-43ad-95f7-c04f7ae93b41"))
            {
                log.Info("HslCommunication激活失败");
                return false;
            }
            Console.WriteLine("HslCommunication激活成功!");
            melsecMcNet = new MelsecMcNet();
            melsecMcNet.ConnectTimeOut = 2000;
            return true;
        } 
        #endregion

        #region 是否连接
        /// <summary>
        /// 是否连接
        /// </summary>
        public  bool IsConnected { get; set; }

        #endregion

        #region 建立连接
        /// <summary>
        /// 建立连接
        /// </summary>
        /// <param name="IP"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        public  bool Connect(string iP, int port)
        {
            melsecMcNet.IpAddress = iP;//正式环境开启
            melsecMcNet.Port = port;

            // 如果网络不太理想,配置了两个端口,一个有问题,立即切换另一个的话,可以配置如下的代码
            //melsecMcNet.GetPipeSocket().SetMultiPorts(new int[] { 6000, 6001 });
            try
            {
                // 先关闭再重连,防止多次重连
                melsecMcNet.ConnectClose();
                OperateResult connect = melsecMcNet.ConnectServer();
                if (connect.IsSuccess)
                {
                    IsConnected = true;
                    return true;
                }
                else
                {
                    melsecMcNet.RemoteStopAsync();
                    melsecMcNet.ConnectCloseAsync();
                    IsConnected = false;
                    Console.WriteLine("连接失败!");
                    return false;
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
                IsConnected = false;
                return false;
            }
        }

        #endregion

        #region 断开连接
        /// <summary>
        /// 断开连接
        /// </summary>
        /// <returns></returns>
        public  bool DisConnect()
        {
            return melsecMcNet.ConnectClose().IsSuccess;
        }
        #endregion

        #region  读取byte数据
        /// <summary>
        /// 读取byte数据
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public  byte[] ReadBytes(string address)
        {
            byte[] bytes = null;
            try
            {
                OperateResult<byte[]> read = melsecMcNet.Read(address, 26);
                if (read.IsSuccess)
                {
                    byte[] code = new byte[read.Content.Length - 2];
                    Array.Copy(read.Content, 2, code, 0, 24);
                    string scode = Encoding.ASCII.GetString(code, 0, code.Length);
                    bytes = code;
                }
            }
            catch (Exception ex)
            {
                log.Error("ReadBytes方法异常" + ex.ToString());
            }
            return bytes;
        }
        #endregion

        #region 读取bool
        /// <summary>
        /// 读取bool
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public  bool ReadBool(string address)
        {
            bool iflag = false;
            try
            {
                OperateResult<bool> read = melsecMcNet.ReadBool(address);
                if (read.IsSuccess)
                {
                    iflag = read.Content;
                }
                return iflag;
            }
            catch (Exception ex)
            {
                log.Error("ReadBool方法异常" + ex.ToString());
            }
            return iflag;
        }
        #endregion

        #region 读取int16
        /// <summary>
        /// 读取int16
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public  int ReadInt16(string address)
        {
            int returnflag = 0;
            try
            {
                OperateResult<Int16> read = melsecMcNet.ReadInt16(address);
                if (read.IsSuccess)
                {
                    returnflag = read.Content;
                }
            }
            catch (Exception ex)
            {
                log.Error("ReadInt16方法异常" + ex.ToString());
            }
            return returnflag;
        }
        #endregion

        #region 读取int32
        /// <summary>
        /// 读取int32
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public  int ReadInt32(string address)
        {
            int returnflag = 0;
            try
            {
                OperateResult<Int32> read = melsecMcNet.ReadInt32(address);
                if (read.IsSuccess)
                {
                    returnflag = read.Content;
                }
            }
            catch (Exception ex)
            {
                log.Error("ReadInt32方法异常" + ex.ToString());
            }
            return returnflag;
        }
        #endregion

        #region 读取string

        /// <summary>
        /// 读取string
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public  string ReadString(string address)
        {
            string returnflag = "";
            try
            {
                OperateResult<string> read = melsecMcNet.ReadString(address, 10);
                if (read.IsSuccess)
                {
                    returnflag = read.Content;
                }
            }
            catch (Exception ex)
            {
                log.Error("ReadString方法异常" + ex.ToString());
            }
            return returnflag;
        }
        #endregion

        #region 读取Float

        /// <summary>
        /// 读取Float
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public float ReadFloat(string address)
        {
            float flag = 0;
            try
            {
                OperateResult<float> read = melsecMcNet.ReadFloat(address);
                if (read.IsSuccess)
                {
                    flag = read.Content;
                }
            }
            catch (Exception ex)
            {
                log.Error("ReadFloat方法异常" + ex.ToString());
            }
            return flag;
        }

        #endregion

        #region 读取Double
        /// <summary>
        /// 读取Double
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public double ReadDouble(string address)
        {
            double flag = 0;
            try
            {
                OperateResult<double> read = melsecMcNet.ReadDouble(address);
                if (read.IsSuccess)
                {
                    flag = read.Content;
                }
            }
            catch (Exception ex)
            {
                log.Error("ReadDouble方法异常" + ex.ToString());
            }
            return flag;
        }

        #endregion

        #region 写入int16
        /// <summary>
        /// 写入int16
        /// </summary>
        /// <param name="address"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool WriteInt16(string address, string value)
        {
            bool iflag = false;
            try
            {
                OperateResult write = melsecMcNet.Write(address, short.Parse(value));
                //Task<OperateResult<TimeSpan>> operateResult = melsecMcNet.Wait(address, short.Parse(value));

                if (write.IsSuccess)
                {
                    iflag = true;
                }
                else
                {
                    iflag = false;
                }
                return iflag;
            }
            catch (Exception ex)
            {
                log.Error("WriteInt16方法异常" + ex.ToString());
                return iflag;
            }
        }
        #endregion

        #region 写入int32
        /// <summary>
        /// 写入int32
        /// </summary>
        /// <param name="address"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public  bool WriteInt32(string address, int value)
        {
            bool iflag = false;
            try
            {
                OperateResult write = melsecMcNet.Write(address, value);
                if (write.IsSuccess)
                {
                    iflag = true;
                }
                else
                {
                    iflag = false;
                }
                return iflag;
            }
            catch (Exception ex)
            {
                log.Error("WriteInt32方法异常" + ex.ToString());
                return iflag;
            }
        }
        #endregion

        #region 写入string
        /// <summary>
        /// 写入string
        /// </summary>
        /// <param name="address"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public  bool WriteString(string address, string value)
        {
            bool iflag = false;
            try
            {
                OperateResult write = melsecMcNet.Write(address, value);
                if (write.IsSuccess)
                {
                    iflag = true;
                }
                else
                {
                    iflag = false;
                }
            }
            catch (Exception ex)
            {
                log.Error("WriteString方法异常" + ex.ToString());
                iflag = false;
            }
            return iflag;
        }


        #endregion

        #region 写入byte
        /// <summary>
        /// 写入byte
        /// </summary>
        /// <param name="address"></param>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public  bool WriteByte(string address, byte[] bytes)
        {
            bool iflag = false;
            try
            {
                OperateResult write = melsecMcNet.Write(address, bytes);
                if (write.IsSuccess)
                {
                    iflag = true;
                }
                else
                {
                    iflag = false;
                }
            }
            catch (Exception ex)
            {
                log.Error("WriteByte方法异常" + ex.ToString());
                iflag = false;
            }
            return iflag;
        }
        #endregion

        #region 写入Float
        /// <summary>
        /// 写入byte
        /// </summary>
        /// <param name="address"></param>
        /// <param name="bytes"></param>
        /// <returns></returns>
        public  bool WriteFloat(string address, float value)
        {
            bool iflag = false;
            try
            {
                OperateResult write = melsecMcNet.Write(address, value);
                if (write.IsSuccess)
                {
                    iflag = true;
                }
                else
                {
                    iflag = false;
                }
            }
            catch (Exception ex)
            {
                log.Error("WriteByte方法异常" + ex.ToString());
                iflag = false;
            }
            return iflag;
        }


        #endregion

        #region 心跳使用——喂狗
        /// <summary>
        /// 心跳使用
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public  async Task<bool> Read(string address)
        {
            try
            {
                melsecMcNet.ReceiveTimeOut = 2000;
             
                OperateResult<bool> read = await melsecMcNet.ReadBoolAsync(address);
                if (read.IsSuccess)
                {
                    IsConnected = true;
                    return true;
                }
                else
                {
                    var k = read.ErrorCode < 0 ? false : true;
                    if (k)
                    {
                        IsConnected = true;
                        return true;
                    }
                    else
                    {
                        IsConnected = false;
                        return false;
                    }

                    
                }
            }
            catch (Exception ex)
            {
                log.Error("ReadInt32方法异常" + ex.ToString());
            }
            return false;
        }
        #endregion

        /// <summary>
        /// 读取byte
        /// </summary>
        /// <param name="address">地址</param>
        /// <param name="len">长度</param>
        /// <returns></returns>
        public byte[] Read(string address, ushort len)
        {
            OperateResult<byte[]> readbyte = melsecMcNet.Read(address, len);
            if (readbyte.IsSuccess)
            {
                IsConnected = true;
                return readbyte.Content;
            }
            else
            {
                IsConnected = false;
                return null;
            }
        }
    }
}