using HslCommunication.Profinet.Siemens;
using HslCommunication;
using Mesnac.PlcUtils.common;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HslCommunication.Profinet.Omron;

namespace Mesnac.PlcUtils.Impl
{
    internal class SiemensPlc : IPlc
    {

        private StringChange stringChange = StringChange.Instance;

        private const SiemensPLCS type = SiemensPLCS.S1200;

        private SiemensS7Net s7 = new SiemensS7Net(type);

        public SiemensPlc()
        {
            if (!HslCommunication.Authorization.SetAuthorizationCode("ed1415f8-e06a-43ad-95f7-c04f7ae93b41"))
            {
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Error("HslCommunication 11.0.6.0激活失败...");
                return;
            }
            ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug("HslCommunication 11.0.6.0激活成功");
        }

        public bool IsConnected { get; set; }

        /// <summary>
        /// 建立连接
        /// </summary>
        /// <param name="IP"></param>
        /// <param name="port"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public bool Connect(string IP, int port)
        {
            ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug("西门子S7系列PLC连接开始");
            s7.IpAddress = IP;
            s7.Port = 102;
            try
            {
                OperateResult connect = s7.ConnectServer();
                if (connect.IsSuccess)
                {
                    this.IsConnected = true;
                    ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug("西门子S7系列PLC建立连接成功!!!");
                    return true;
                }
                else
                {
                    this.IsConnected = false;
                    ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug("西门子S7系列PLC建立连接失败!!!");
                    return false;
                }
            }
            catch (Exception ex)
            {
                this.IsConnected = false;
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Error("西门子S7系列PLC建立连接异常", ex);
                return false;
            }
        }

        /// <summary>
        /// 通过地址和长度读取PLC数据
        /// </summary>
        /// <param name="len"></param>
        /// <param name="address"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public byte[] readValueByAddress(int len, string address)
        {
            //ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug("开始通过PLC地址和长度读取PLC数据");
            try
            {
                OperateResult<byte[]> read = s7.Read(address, (ushort)(len));
                if (read.IsSuccess)
                {
                    byte[] result = stringChange.ConvertFloatToINt(read.Content);
                    ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过地址和长度读取PLC数据成功:{0}", stringChange.bytesToHexStr(result, result.Length)));
                    return result;
                }
                else
                {
                    ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug("通过地址和长度读取PLC数据失败!!!");
                    this.IsConnected = false;
                    return new byte[0];
                }
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Error("通过地址和长度读取PLC数据异常", ex);
                this.IsConnected = false;
                return new byte[0];
            }
        }

        /// <summary>
        /// 通过PLC地址写入int类型数据
        /// </summary>
        /// <param name="value"></param>
        /// <param name="address"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public bool writeValueByAddress(int value, string address)
        {
            //ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("开始通过PLC地址{0}写入int类型数据{1}",address,value));
            try
            {
                OperateResult operateResult = s7.Write(address, Convert.ToInt32(value));
                if (operateResult.IsSuccess)
                {
                    ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("开始通过PLC地址{0}写入int类型数据{1}成功", address, value));
                    return true;
                }
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("开始通过PLC地址{0}写入int类型数据{1}失败!!!", address, value));
                this.IsConnected = false;
                return false;
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Error("通过PLC地址写入int类型数据", ex);
                this.IsConnected = false;
                return false;
            }
        }

        /// <summary>
        /// 通过PLC地址清零数据
        /// </summary>
        /// <param name="address"></param>
        /// <param name="len"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public bool resetByAddress(string address, int len)
        {
            //ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("开发通过PLC地址{0}清零数据", address));
            try
            {
                byte[] write = new byte[len * 2];
                for (int i = 0; i < len * 2; i++)
                {
                    write[i] = 0;
                }
                OperateResult operateResult = s7.Write(address, write);

                if (operateResult.IsSuccess)
                {
                    ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}清零数据成功", address));
                    return true;
                }
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}清零数据失败!!!", address));
                return false;
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Error(String.Format("通过PLC地址{0}清零数据异常", address), ex);
                return false;
            }
        }

        /// <summary>
        /// 通过PLC地址读取EA值
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public string readEaByAddress(string address)
        {
            //ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}读取EA值", address));
            try
            {
                OperateResult<Byte[]> read = s7.Read(address, (ushort)(8));

                if (read.IsSuccess && read.Content != null)
                {
                    string result = Convert.ToString(read.Content);
                    ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}读取EA值成功:{1}", address, result));
                    return result;
                }
                else
                {
                    ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}读取EA值失败!!!", address));
                    this.IsConnected = false;
                    return "";
                }
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Error("通过PLC地址读取EA值异常", ex);
                this.IsConnected = false;
                return "";
            }
        }

        /// <summary>
        /// 通过PLC地址读取交互信号
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public int readInteractiveSignal(string address)
        {
            //ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("开始通过PLC地址{0}读取交互信号", address));
            try
            {
                OperateResult<short> read = s7.ReadInt16(address);
                if (read.IsSuccess)
                {
                    ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}读取交互信号成功:{1}", address, read.Content));
                    return read.Content;
                }
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}读取交互信号失败!!!", address));
                this.IsConnected = false;
                return 0;
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Error("通过PLC地址读取交互信号异常", ex);
                this.IsConnected = false;
                return 0;
            }
        }

        /// <summary>
        /// 通过PLC地址读取int32类型数据
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        public int readInt32ByAddress(string address)
        {
            //ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("开始通过PLC地址{0}读取int32类型数据",address));
            try
            {
                OperateResult<short> read = s7.ReadInt16(address);
                if (read.IsSuccess)
                {
                    ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}读取int32类型数据成功:{1}", address, read.Content));
                    return read.Content;
                }
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}读取int32类型数据失败!!!", address));
                this.IsConnected = false;
                return 0;
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Error("通过PLC地址读取int32类型数据异常", ex);
                this.IsConnected = false;
                return 0;
            }
        }

        /// <summary>
        /// 通过PLC地址写入int32类型数据
        /// </summary>
        /// <param name="address"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public bool writeInt32ByAddress(string address, int value)
        {
            ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("开始通过PLC地址{0}写入int32类型数据{1}", address, value));
            try
            {
                OperateResult write = s7.Write(address, short.Parse(Convert.ToString(value)));
                if (write.IsSuccess)
                {
                    ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}写入int32类型数据{1}成功", address, value));
                    return true;
                }
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}写入int32类型数据{1}失败!!!", address, value));
                this.IsConnected = false;
                return false;
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Error(String.Format("通过PLC地址{0}写入int32类型数据异常", address), ex);
                this.IsConnected = false;
                return false;
            }
        }

        /// <summary>
        /// 通过PLC地址写入String类型数据
        /// </summary>
        /// <param name="address"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public bool writeStringByAddress(string address, string value)
        {
            //ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}写入String类型数据{1}",address,value));
            try
            {
                OperateResult operateResult = s7.Write(address, value);
                if (operateResult.IsSuccess)
                {
                    ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}写入String类型数据{1}成功", address, value));
                    return true;
                }
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}写入String类型数据{1}失败!!!", address, value));
                //this.IsConnected = false;
                return false;
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Error(String.Format("通过PLC地址{0}写入String类型数据异常", address), ex);
                //this.IsConnected = false;
                return false;
            }
        }

        /// <summary>
        /// 通过PLC地址读取string类型数据
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public string readStringByAddress(string address, ushort length)
        {
            //ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("开始通过PLC地址{0}读取string类型数据", address));
            try
            {
                OperateResult<String> read = s7.ReadString(address, length);
                if (read.IsSuccess)
                {
                    ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}读取string类型数据成功:{1}", address, read.Content));
                    return read.Content;
                }
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}读取string类型数据失败!!!", address));
                this.IsConnected = false;
                return "";
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Error("通过PLC地址读取int32类型数据异常", ex);
                return "";
            }
        }

        /// <summary>
        /// 通过PLC地址读取Bool类型数据
        /// </summary>
        /// <param name="address"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public OperateResult<bool> readBoolByAddress(string address)
        {
            //ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("开始通过PLC地址{0}读取bool类型数据", address));
            try
            {
                OperateResult<bool> read = s7.ReadBool(address);
                if (read.IsSuccess)
                {
                    ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}读取bool类型数据成功:{1}", address, read.Content));
                }
                else
                {
                    ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}读取bool类型数据失败!!!", address));
                }
                return read;
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Error("通过PLC地址读取int32类型数据异常", ex);
                return new OperateResult<bool>() { IsSuccess = false, Content = false };
            }
        }

        /// <summary>
        /// 通过PLC地址写入Bool类型数据
        /// </summary>
        /// <param name="address"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool writeBoolByAddress(string address, bool value)
        {
            //ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("开始通过PLC地址{0}写入bool类型数据{1}", address, value));
            try
            {
                OperateResult write = s7.Write(address, short.Parse(stringChange.ParseToInt(value ? "1" : "0").ToString()));
                if (write.IsSuccess)
                {
                    ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}写入bool类型数据{1}成功", address, value));
                    return true;
                }
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}写入bool类型数据{1}失败!!!", address, value));
                this.IsConnected = false;
                return false;
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Error(String.Format("通过PLC地址{0}写入bool类型数据异常", address), ex);
                this.IsConnected = false;
                return false;
            }
        }

        public bool DisConnect()
        {
            return s7.ConnectClose().IsSuccess;
        }

        public bool writeDoubleByAddress(string address, int value)
        {
            try
            {
                OperateResult write = s7.Write(address, Convert.ToDouble(value));

                if (write.IsSuccess)
                {
                    ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}写入Double类型数据{1}成功", address, value));
                    return true;
                }
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Debug(String.Format("通过PLC地址{0}写入Double类型数据{1}失败!!!", address, value));
                return false;
            }
            catch (Exception ex)
            {
                ICSharpCode.Core.LoggingService<OmronNJPlc>.Error(String.Format("通过PLC地址{0}写入Double类型数据异常", address), ex);
                return false;
            }
        }
    }
}