using Opc.Ua;
using Opc.Ua.Client;
using SinumerikOpcUaAPI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace YG.Device
{
    public class DeviceOPCUat
    {
        Server opcserver;
        EndpointDescription endpointDescription;
        public bool IsOn { get; set; } = false;

        public DeviceOPCUat(string url, string username = "OpcUaClient", string pwd = "12345678")
        {
            if (opcserver == null || !opcserver.Session.Connected)
            {
                IsOn = OpcUa_Connection(url, username, pwd);
                YG.Log.Instance.WriteLogAdd("OPCUA 连接是否成功===>>" + IsOn);
            }
        }

        public bool IsConnection { get; set; } = false;

        private void Notification_KeepAlive(Session sender, KeepAliveEventArgs e)
        {
            try
            {
                if (sender != this.opcserver.Session || !ServiceResult.IsBad(e.Status))
                    return;
                this.opcserver.Session.Reconnect();
                YG.Log.Instance.WriteLogAdd($"35----->>----->>----->>----->>----->>----->>----->>----->>----->>----->>----->>Notification_KeepAlive");
                IsConnection = true;
            }
            catch (Exception ex)
            {
                IsConnection = false;
                YG.Log.Instance.WriteLogAdd($"41-->>{ex.Message}");

            }
        }
        /// <summary>
        /// 获取NC下边的文件列表
        /// </summary>
        /// <returns></returns>
        public ReferenceDescriptionCollection OpcUa_BrowseNode()
        {
            return opcserver.BrowseNode(new NodeId("Sinumerik/FileSystem/NCExtend/webApiMESFILE/", (ushort)2).ToString());
        }
        #region 终止连接
        public void OpcUa_Close()
        {
            if (OpcUa_ConState())
            {
                opcserver.Disconnect();
            }
        }
        private bool OpcUa_ConState()
        {
            if (opcserver != null && opcserver.Session.Connected)
            {
                return true;
            }
            else
            {
                YG.Log.Instance.WriteLogAdd("OPC没有连接");
            }
            return false;
        }

        #endregion

        #region 写入
        public bool OpcUa_Write(string address, object value)
        {
            try
            {
                if (OpcUa_ConState())
                {
                    opcserver.WriteValues(new List<string>() { value.ToString() }, new List<string>() { address });
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                YG.Log.Instance.WriteLogAdd($"92-->{ex.Message}");
                return false;
            }
        }
        public bool OpcUa_WriteValue(string address, object value)
        {
            try
            {
                string str = new NodeId(address, (ushort)2).ToString();

                if (OpcUa_ConState())
                {
                    opcserver.WriteValues(new List<string>() { value.ToString() }, new List<string>() { str });
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                YG.Log.Instance.WriteLogAdd($"110->{ex.Message}");
                return false;
            }
        }

        public bool OpcUa_WriteValue(List<string> addresses, List<string> values)
        {
            try
            {
                if (OpcUa_ConState())
                {
                    opcserver.WriteValues(addresses, values);
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                YG.Log.Instance.WriteLogAdd($"110->{ex.Message}");
                return false;
            }
        }
        #endregion

        #region 选中
        public bool OpcUa_Select(string filename)
        {
            bool result = false;
            try
            {
                if (OpcUa_ConState())
                {
                    string extension = System.IO.Path.GetExtension(filename);
                    if (string.IsNullOrWhiteSpace(extension) || !extension.ToUpper().Equals(".MPF"))
                    {
                        // System.Windows.Forms.MessageBox.Show("请选择要上传的文件");
                        return false;
                    }
                    try
                    {
                        string value = opcserver.MethodCallSelectProgram(filename, Convert.ToUInt32(1)).status;
                        if (value.Equals("Good"))
                        {
                            result = true;
                        }

                    }
                    catch (Exception ex)
                    {
                        YG.Log.Instance.WriteLogAdd($"{ex.Message}");
                        //System.Windows.Forms.MessageBox.Show($"{ex.Message}");

                    }
                }
                return result;

            }
            catch (Exception ex)
            {
                YG.Log.Instance.WriteLogAdd($"154--->{ex.Message}");
                return false;
            }
        }
        public bool OpcUa_Select(string path, string filename)
        {
            bool result = false;
            try
            {
                if (OpcUa_ConState())
                {
                    string extension = System.IO.Path.GetExtension(filename);
                    if (string.IsNullOrWhiteSpace(extension) || !extension.ToUpper().Equals(".MPF"))
                    {
                        //System.Windows.Forms.MessageBox.Show("请选择要上传的文件");
                        return false;
                    }
                    try
                    {
                        string value = opcserver.MethodCallSelectProgram(path + filename, Convert.ToUInt32(1)).status;
                        if (value.Equals("Good"))
                        {
                            result = true;
                        }

                    }
                    catch (Exception ex)
                    {
                        YG.Log.Instance.WriteLogAdd($"182-->{ex.Message}");
                        //System.Windows.Forms.MessageBox.Show($"{ex.Message}");

                    }
                }
                return result;

            }
            catch (Exception ex)
            {
                YG.Log.Instance.WriteLogAdd($"192-->{ex.Message}");
                return false;
            }
        }
        #endregion

        #region 读取
        public bool OpcUa_Read(string address, out string value)
        {
            bool result = false;
            value = "";
            if (OpcUa_ConState())
            {
                try
                {
                    string itemaddress = $"/Plc/{address}";
                    string str = new NodeId(itemaddress, (ushort)2).ToString();

                    if (opcserver != null && opcserver.Session.Connected)
                    {
                        value = opcserver.ReadValues(new List<string>() { str })[0];
                    }
                    result = true;
                }
                catch (Exception ex)
                {
                    YG.Log.Instance.WriteLogAdd($"{ex.Message}");
                    //System.Windows.Forms.MessageBox.Show($"{ex.Message}");

                }
            }
            return result;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="address">list里边的地址格式为I2.0,I2.1,DB2.DBX35.0等格式</param>
        /// <param name="value">查询出来的值和上面的值是一一对应的关系</param>
        /// <returns></returns>
        public bool OpcUa_Read(List<string> address, out List<string> value)
        {
            value = new List<string>();
            try
            {
                List<string> nodeIdStrings = new List<string>();
                foreach (string s in address)
                {
                    nodeIdStrings.Add(new NodeId($"/Plc/{s}", (ushort)2).ToString());
                }
                if (opcserver != null && opcserver.Session.Connected)
                {
                    value = opcserver.ReadValues(nodeIdStrings);
                }
                return true;
            }
            catch (Exception ex)
            {
                YG.Log.Instance.WriteLogAdd($"{ex.Message}");
                //System.Windows.Forms.MessageBox.Show($"{ex.Message}");
                return false;
            }
        }
        public List<string> OpcUa_Read(List<string> address)
        {
            List<string> value = new List<string>();
            try
            {
                List<string> nodeIdStrings = new List<string>();

                if (opcserver != null && opcserver.Session != null && opcserver.Session.Connected)
                {
                    value = opcserver.ReadValues(nodeIdStrings);
                }
                return value;
            }
            catch (Exception ex)
            {

                try
                {
                    OpcUa_Connection(opcserver.Session.ConfiguredEndpoint.ToString());
                }
                catch (Exception esx)
                {
                    YG.Log.Instance.WriteLogAdd($"284------->>esx---->{esx.Message} {ex.Message}--->>>");
                }
                return value;
            }
        }

        public bool OpcUa_Read(List<string> address, out Dictionary<string, string> value)
        {
            value = new Dictionary<string, string>();
            try
            {
                List<string> nodeIdStrings = new List<string>();
                foreach (string s in address)
                {
                    nodeIdStrings.Add(new NodeId($"/Plc/{s}", (ushort)2).ToString());
                    value.Add(s, "");
                }
                if (opcserver != null && opcserver.Session.Connected)
                {
                    List<string> Keys = value.Keys.ToList();
                    List<string> items = opcserver.ReadValues(nodeIdStrings);
                    for (int i = 0; i < items.Count; i++)
                    {
                        value[Keys[i]] = items[i];
                    }
                }
                return true;

            }
            catch (Exception ex)
            {
                YG.Log.Instance.WriteLogAdd($"{ex.Message}");
                //System.Windows.Forms.MessageBox.Show($"{ex.Message}");
                return false;
            }
        }
        #endregion

        #region OPCUA连接
        /// <summary>
        /// 连接opcua
        /// </summary>
        /// <param name="url"></param>
        /// <param name="username"></param>
        /// <param name="pwd"></param>
        public bool OpcUa_Connection(string url, string username = "OpcUaClient", string pwd = "12345678")
        {
            bool result = false;
            try
            {
                opcserver = new Server();
                ApplicationDescriptionCollection applicationDescriptions = opcserver.FindServers(url);
                if (applicationDescriptions.Count == 0)
                {
                    YG.Log.Instance.WriteLogAdd("没有找到服务!");
                }
                else if (applicationDescriptions.Count == 1)
                {
                    applicationDescriptions[0].DiscoveryUrls.Where(m => m.Equals(url)).FirstOrDefault().FirstOrDefaultYG(
                        (t) =>
                        {
                            try
                            {
                                var cc = opcserver.GetEndpoints(t);

                                opcserver.GetEndpoints(t).Where(n => n.EndpointUrl.Equals(url)).FirstOrDefault().FirstOrDefaultYG((tt) =>
                                {
                                    try
                                    {
                                        endpointDescription = tt;
                                        opcserver.KeepAliveNotification += new KeepAliveEventHandler(this.Notification_KeepAlive);
                                        opcserver.Connect(tt, true, username, pwd);
                                        if (opcserver.Session.Connected)
                                        {
                                            IsConnection = true;
                                            result = true;
                                        }
                                        else
                                        {
                                            result = false;
                                        }
                                    }
                                    catch (Exception ex)
                                    {
                                        YG.Log.Instance.WriteLogAdd($"355-->{ex.Message}");
                                        result = false;
                                    }

                                });
                            }
                            catch (Exception ext)
                            {
                                YG.Log.Instance.WriteLogAdd($"362-->{ext.Message}");
                            }
                        });
                }
            }
            catch (Exception eex) { YG.Log.Instance.WriteLogAdd($"368-->{eex.Message}-->{url}"); }
            return result;
        }

        /// <summary>
        /// 连接opcua
        /// </summary>
        /// <param name="url"></param>
        /// <param name="username"></param>
        /// <param name="pwd"></param>
        public static Server OpcUa_Connection1(string url, string username = "OpcUaClient", string pwd = "12345678")
        {
            Server serverOpcUa = new Server();
            try
            {

                ApplicationDescriptionCollection applicationDescriptions = serverOpcUa.FindServers(url);
                if (applicationDescriptions.Count == 0)
                {
                    YG.Log.Instance.WriteLogAdd("没有找到服务!");
                }
                else if (applicationDescriptions.Count == 1)
                {
                    applicationDescriptions[0].DiscoveryUrls.Where(m => m.Equals(url)).FirstOrDefault().FirstOrDefaultYG(
                        (t) =>
                        {
                            try
                            {
                                var cc = serverOpcUa.GetEndpoints(t);

                                serverOpcUa.GetEndpoints(t).Where(n => n.EndpointUrl.Equals(url)).FirstOrDefault().FirstOrDefaultYG((tt) =>
                                {
                                    try
                                    {

                                        serverOpcUa.Connect(tt, true, username, pwd);

                                    }
                                    catch (Exception ex)
                                    { 
                                        YG.Log.Instance.WriteLogAdd($"355-->{ex.Message}"); 
                                    }

                                });
                            }
                            catch (Exception ext)
                            {
                                YG.Log.Instance.WriteLogAdd($"362-->{ext.Message}");
                            }
                        });
                }
            }
            catch (Exception eex) { YG.Log.Instance.WriteLogAdd($"368-->{eex.Message}-->{url}"); }
            return serverOpcUa;
        }
        #endregion
        #region 添加用户权限
        /// <summary>
        /// 添加用户权限
        /// </summary>
        /// <param name="username"></param>
        public bool OpcUa_Access(string username = "OpcUaClient")
        {
            bool resultb = true;
            if (OpcUa_ConState())
            {
                try
                {
                    string result = "";
                    string strValue = "StateRead,StateWrite,FrameRead,FrameWrite,SeaRead,SeaWrite,TeaRead,TeaWrite,ToolRead,ToolWrite,DriveRead,DriveWrite,GudRead,GudWrite,PlcRead,PlcWrite,AlarmRead,FsRead,FsWrite,ApWrite,CsomReadx,CsomWritex,PlcReadDBx,PlcWriteDBx,SinuReadAll,SinuWriteAll";
                    {
                        string[] vs = strValue.Split(new string[] { "," }, StringSplitOptions.None);
                        foreach (string s in vs)
                        {
                            Server.MethodCallResult methodCallResult = opcserver.MethodCall("/Methods/GiveUserAccess", username, s);
                            if (methodCallResult != null && !methodCallResult.status.Equals("Good"))
                            {
                                result += s + methodCallResult.status;
                            }
                        }


                    }
                    if (result.Length > 0)
                    {
                        resultb = false;
                        YG.Log.Instance.WriteLogAdd($"执行权限添加是出现异常:{result}");
                    }
                }
                catch (Exception ex)
                {
                    resultb = false;
                    YG.Log.Instance.WriteLogAdd($"409-->{ex.Message}");
                }
            }
            return resultb;
        }
        #endregion
        #region 上传文件
        /// <summary>
        /// 上传文件，不能是文件夹，只能是一个文件，已经默认了一个文件位置， 如果有其他需求后期做调整
        /// </summary>
        /// <param name="file">需要上传的文件的名字，这个名字是有后缀的,</param>
        public void OpcUa_UpLoadFile(string file)
        {
            try
            {

                string extension = System.IO.Path.GetExtension(file);
                if (string.IsNullOrWhiteSpace(extension))
                {
                    //System.Windows.Forms.MessageBox.Show("请选择要上传的文件");
                    return;
                }
                try
                {
                    opcserver.MethodCallCreateNewFile("Sinumerik/FileSystem/NCExtend/webApiMESFILE/", System.IO.Path.GetFileName(file), true);
                    byte[] data = opcserver.ReadFile(file);
                    int copylen = 5000;
                    bool isover = true;
                    byte[] bt = new byte[copylen];
                    if (data.Length > copylen)
                    {

                        int runcount = data.Length / copylen;
                        for (int i = 0; i < runcount; i++)
                        {
                            Array.Copy(data, i * copylen, bt, 0, copylen);
                            if (i > 0)
                            {
                                isover = false;
                            }
                            var cc = opcserver.MethodCallCopyFileToServer($"/Methods/CopyFileToServer", $"Sinumerik/FileSystem/NCExtend/webApiMESFILE/{System.IO.Path.GetFileName(file)}", data, isover);
                            System.Console.WriteLine($"当前循环到的位置：{i}-->>{cc.status}");
                        }
                        int lastleng = data.Length % copylen;
                        bt = new byte[lastleng];
                        Array.Copy(data, runcount * copylen, bt, 0, lastleng);
                        Server.MethodCallResult methodCallResult = opcserver.MethodCallCopyFileToServer($"/Methods/CopyFileToServer", $"Sinumerik/FileSystem/NCExtend/webApiMESFILE/{System.IO.Path.GetFileName(file)}", data, isover);

                        if (methodCallResult.status.ToUpper().Equals("GOOD"))
                        {
                            YG.Log.Instance.WriteLogAdd("上传文件成功");
                        }
                        else
                        {
                            YG.Log.Instance.WriteLogAdd("上传文件失败");
                        }
                    }
                    else
                    {
                        Server.MethodCallResult methodCallResult = opcserver.MethodCallCopyFileToServer($"/Methods/CopyFileToServer", $"Sinumerik/FileSystem/NCExtend/webApiMESFILE/{System.IO.Path.GetFileName(file)}", data, isover);

                        if (methodCallResult.status.ToUpper().Equals("GOOD"))
                        {
                            YG.Log.Instance.WriteLogAdd("上传文件成功");
                        }
                        else
                        {
                            YG.Log.Instance.WriteLogAdd("上传文件失败");
                        }
                    }



                }
                catch (Exception ex)
                {
                    YG.Log.Instance.WriteLogAdd($"{ex.Message}");
                    //System.Windows.Forms.MessageBox.Show($"{ex.Message}");
                }


            }
            catch (Exception ex)
            {
                YG.Log.Instance.WriteLogAdd($"493-->{ex.Message}");
            }
        }
        #endregion
        #region 删除文件
        /// <summary>
        /// 删除文件，只能是一个文件，已经默认了一个文件位置， 如果有其他需求后期做调整
        /// </summary>
        /// <param name="file">需要删除的文件的名字，这个名字是有后缀的</param>
        public void OpcUa_DeleteFile(string file)
        {
            try
            {

                Server.MethodCallResult methodCallResult = opcserver.MethodCallDeleteFile($"Sinumerik/FileSystem/NCExtend/webApiMESFILE/{file}");
                if (methodCallResult.status.ToUpper().Equals("GOOD"))
                {
                    YG.Log.Instance.WriteLogAdd("删除文件成功");
                }
                else
                {
                    YG.Log.Instance.WriteLogAdd("删除文件失败");
                }
            }
            catch (Exception ex)
            {
                YG.Log.Instance.WriteLogAdd($"519-->{ex.Message}");
            }
        }
        public string OpcUa_DeleteFile(string path, string file)
        {
            string status = "";
            try
            {
                status = opcserver.MethodCallDeleteFile(path + file).status;
                if (status.ToUpper().Equals("GOOD"))
                {
                    YG.Log.Instance.WriteLogAdd("删除文件成功");
                }
                else
                {
                    YG.Log.Instance.WriteLogAdd("删除文件失败");
                }
            }
            catch (Exception ex)
            {
                YG.Log.Instance.WriteLogAdd($"539-->{ex.Message}");
            }
            return status;
        }
        #endregion
        #region 创建文件目录
        /// <summary>
        /// 创建文件目录，，
        /// </summary>
        /// <param name="file">类似于文件夹名称</param>
        public void OpcUa_CreateNewFile(string file = "webApiMESFILE")
        {
            try
            {
                Server.MethodCallResult methodCallResult = opcserver.MethodCallCreateNewDir($"Sinumerik/FileSystem/NCExtend", file);
                if (methodCallResult.status.ToUpper().Equals("GOOD"))
                {
                    YG.Log.Instance.WriteLogAdd("删除文件成功");
                }
                else
                {
                    YG.Log.Instance.WriteLogAdd("删除文件失败");
                }
            }
            catch (Exception ex)
            {
                YG.Log.Instance.WriteLogAdd($"565-->{ex.Message}");
            }
        }
        #endregion

        public void disConnect()
        {
            if (opcserver.Session.Connected)
            {
                opcserver.Disconnect();
            }
        }
    }
}
