using Opc.Ua;
using Opc.Ua.Client;
using SinumerikOpcUaAPI;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace YG.Device
{
    public class DeviceOPCUat : DeviceList
    {
        //private static DeviceOPCUat clientTest = new DeviceOPCUat();
        //public static DeviceOPCUat Instance { get { return clientTest; } }
        Server opcserver;
        EndpointDescription endpointDescription;
        public override bool IsOn { get; set; } = false;
        public DeviceOPCUat(string url, string username = "OpcUaClient", string pwd = "12345678")
        {
            IsOn = OpcUa_Connection(url, username, pwd);
        }
        public DeviceOPCUat()
        {
        }
        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;
                System.Windows.Forms.MessageBox.Show(ex.Message, "Error");
            }
        }
        public override object Clone()
        {
            return this.MemberwiseClone();
        }
        /// 
        /// 获取NC下边的文件列表
        /// 
        /// 
        public ReferenceDescriptionCollection OpcUa_BrowseNode()
        {
            return opcserver.BrowseNode(new NodeId("Sinumerik/FileSystem/NCExtend/YGMESFILE/", (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没有连接");
                System.Windows.Forms.MessageBox.Show("OPC没有连接");
            }
            return false;
        }
        #endregion
        #region 写入
        public bool OpcUa_Write(string address, object value)
        {
            try
            {
                string itemaddress = $"/Plc/{address}";
                string str = new NodeId(itemaddress, (ushort)2).ToString();
                if (OpcUa_ConState())
                {
                    opcserver.WriteValues(new List() { value.ToString() }, new List() { str });
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                YG.Log.Instance.WriteLogAdd($"92-->{ex.Message}");
                System.Windows.Forms.MessageBox.Show($"{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() { value.ToString() }, new List() { str });
                    return true;
                }
                return false;
            }
            catch (Exception ex)
            {
                YG.Log.Instance.WriteLogAdd($"110->{ex.Message}");
                System.Windows.Forms.MessageBox.Show($"{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($"Sinumerik/FileSystem/NCExtend/YGMESFILE/{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() { str })[0];
                    }
                    result = true;
                }
                catch (Exception ex)
                {
                    YG.Log.Instance.WriteLogAdd($"{ex.Message}");
                    System.Windows.Forms.MessageBox.Show($"{ex.Message}");
                }
            }
            return result;
        }
        /// 
        /// 
        /// 
        /// list里边的地址格式为I2.0,I2.1,DB2.DBX35.0等格式
        /// 查询出来的值和上面的值是一一对应的关系
        /// 
        public bool OpcUa_Read(List address, out List value)
        {
            value = new List();
            try
            {
                List nodeIdStrings = new List();
                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 OpcUa_Read(List address)
        {
            List value = new List();
            try
            {
                List nodeIdStrings = new List();
                foreach (string s in address)
                {
                    nodeIdStrings.Add(new NodeId(s, (ushort)2).ToString());
                }
                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}--->>>");
                }
                YG.Log.Instance.WriteLogAdd($"272-->{ex.Message}--->>{address.Json_SerializeObject()}--->{opcserver.Session.ConfiguredEndpoint}");
                // System.Windows.Forms.MessageBox.Show($"{ex.Message}");
                return value;
            }
        }
        public bool OpcUa_Read(List address, out Dictionary value)
        {
            value = new Dictionary();
            try
            {
                List nodeIdStrings = new List();
                foreach (string s in address)
                {
                    nodeIdStrings.Add(new NodeId($"/Plc/{s}", (ushort)2).ToString());
                    value.Add(s, "");
                }
                if (opcserver != null && opcserver.Session.Connected)
                {
                    List Keys = value.Keys.ToList();
                    List 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连接
        /// 
        /// 连接opcua
        /// 
        /// 
        /// 
        /// 
        public bool OpcUa_Connection(string url, string username = "OpcUaClient", string pwd = "12345678")
        {
            bool result = false;
            try
            {
               
                opcserver = new Server();
                Subscription sp = new Subscription();
                ApplicationDescriptionCollection applicationDescriptions = opcserver.FindServers(url);
                if (applicationDescriptions.Count == 0)
                {
                    YG.Log.Instance.WriteLogAdd("没有找到服务!");
                    System.Windows.Forms.MessageBox.Show("没有找到服务!");
                }
                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}"); }
            // opcserver.Connect(new Opc.Ua.EndpointDescription(url) {  })
            return result;
        }
        #endregion
        #region 添加用户权限
        /// 
        /// 添加用户权限
        /// 
        /// 
        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 上传文件
        /// 
        /// 上传文件,不能是文件夹,只能是一个文件,已经默认了一个文件位置, 如果有其他需求后期做调整
        /// 
        /// 需要上传的文件的名字,这个名字是有后缀的,
        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/YGMESFILE/", 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/YGMESFILE/{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/YGMESFILE/{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/YGMESFILE/{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 删除文件
        /// 
        /// 删除文件,只能是一个文件,已经默认了一个文件位置, 如果有其他需求后期做调整
        /// 
        /// 需要删除的文件的名字,这个名字是有后缀的
        public void OpcUa_DeleteFile(string file)
        {
            try
            {
                Server.MethodCallResult methodCallResult = opcserver.MethodCallDeleteFile($"Sinumerik/FileSystem/NCExtend/YGMESFILE/{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 创建文件目录
        /// 
        /// 创建文件目录,,
        /// 
        /// 类似于文件夹名称
        public void OpcUa_CreateNewFile(string file = "YGMESFILE")
        {
            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 override void DeviceClose()
        {
            base.DeviceClose();
        }
        //
    }
}