using IMCS.Device;
using IMCS_CCS.Utils.DeviceProtocol;
using Newtonsoft.Json;
using Opc.Ua;
using Opc.Ua.Client;
using SinumerikOpcUaAPI;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using YG.Device;

namespace IMCS
{
    public partial class Form_Main : Form
    {
        public string UPLOAD_NC_PATH = "Sinumerik/FileSystem/Work Pieces/TEST1/";
        //public string UPLOAD_NC_PATH = "Sinumerik/FileSystem/NCExtend/";
        public string CHANNEL_NO = "1";
        public string TEMP_NC_NAME = "7999.MPF";
        private uint currentToolArea = 1;
        Server opcServer = null;
        public Dictionary<string, Server> deviceList { get; set; } = new Dictionary<string, Server>();

        public Form_Main()
        {
            InitializeComponent();
        }
        private void Form1_Load(object sender, EventArgs e)
        {

            HttpListener httpListenner;
            httpListenner = new HttpListener();
            httpListenner.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
            httpListenner.Prefixes.Add("http://127.0.0.1:8010/opcua/");
            httpListenner.Start();
            label1.Text = "HttpServer已开启：http://127.0.0.1:8010/opcua/";
            new Thread(new ThreadStart(delegate
            {
                try
                {
                    loop(httpListenner);

                }
                catch (Exception ex)
                {
                    string ss = ex.ToString();
                    httpListenner.Stop();

                    /*  Application.ExitThread();
                      Application.Exit();
                      Application.Restart();
                      Process.GetCurrentProcess().Kill();*/
                }
            })).Start();

        }


        private void loop(HttpListener httpListenner)
        {

            while (true)
            {
                HttpListenerContext context = httpListenner.GetContext();
                context.Response.AppendHeader("Access-Control-Allow-Origin", "*");
                HttpListenerRequest request = context.Request;
                HttpListenerResponse response = context.Response;
                Servlet servlet = new MyServlet();
                servlet.onCreate();
                if (request.HttpMethod == "POST")
                {
                    if (!request.Url.ToString().Contains("favicon"))
                    {
                        try
                        {
                            Stream stream = context.Request.InputStream;
                            StreamReader reader = new StreamReader(stream, Encoding.UTF8);
                            string body = reader.ReadToEnd();

                            YG.Log.Instance.WriteLogAdd(">>>===收到POST数据 : >>>>===" + body);
                            ResponseBody responseBody = new ResponseBody();

                            RequestBody opcBody = JsonConvert.DeserializeObject<RequestBody>(body);

                            AddList(DateTime.Now.ToString(), "POST", opcBody.ServerUrl + opcBody.Type, "OK");

                            if (deviceList == null || (deviceList.Where(m => m.Key.Equals(opcBody.ServerUrl)).Count() == 0))
                            {
                                opcServer = DeviceOPCUat.OpcUa_Connection1(opcBody.ServerUrl, opcBody.UserName, opcBody.Password);
                                if (opcServer.Session != null)
                                {
                                    deviceList.Add(opcBody.ServerUrl, opcServer);
                                }
                            }
                            else
                            {
                                opcServer = deviceList.Where(m => m.Key.Equals(opcBody.ServerUrl)).FirstOrDefault().Value;
                            }
                            if (opcServer == null || !opcServer.Session.Connected)
                            {
                                opcServer = DeviceOPCUat.OpcUa_Connection1(opcBody.ServerUrl, opcBody.UserName, opcBody.Password);
                            }
                            //else
                            //{
                            //    opcServer.Session.Reconnect();
                            //}

                            if (opcServer.Session.Connected)
                            {
                                if (opcBody.Type == ActionTypeEnum.Connect.ToString()) //连接状态
                                {
                                    responseBody.result = true;
                                }
                                else if (opcBody.Type == ActionTypeEnum.Collect.ToString()) //采集
                                {
                                    //ETH_S7Simens s7 = new ETH_S7Simens("192.168.11.164");

                                    //responseBody.runDatasInfo = JsonConvert.SerializeObject(s7.deviceInfo);

                                    //string s = responseBody.runDatasInfo;
                                    opcBody.Addresses.Add("ns=2;s=/Channel/GeometricAxis/actFeedRate"); //进给倍率
                                    opcBody.Addresses.Add("ns=2;s=/Channel/Spindle/speedOvr");//主轴倍率
                                    opcBody.Addresses.Add("ns=2;s=/Channel/Spindle/actSpeed");//主轴实际速度
                                    opcBody.Addresses.Add("ns=2;s=/Channel/Spindle/driveLoad");//主轴负载
                                    opcBody.Addresses.Add("ns=2;s=/Channel/ProgramInfo/selectedWorkPProg");//主程序
                                    List<string> values = opcServer.ReadValues(opcBody.Addresses);
                                    RunDatasInfo runDatasInfo = new RunDatasInfo();
                                    for (int i = 0; i < values.Count; i++)
                                    {
                                        if (i == 0)
                                        {
                                            runDatasInfo.feedRate = values[i];
                                        }
                                        else if (i == 1)
                                        {
                                            runDatasInfo.spindleMagnification = values[i];
                                        }
                                        else if (i == 2)
                                        {
                                            runDatasInfo.spindleSpeed = values[i];
                                        }
                                        else if (i == 3)
                                        {
                                            runDatasInfo.spindleLoad = values[i];
                                        }
                                    }
                                    responseBody.runDatasInfo = JsonConvert.SerializeObject(runDatasInfo);

                                    //报警 
                                    SinumerikOpcUaAPI.FilterDefinition m_filter = new SinumerikOpcUaAPI.FilterDefinition();
                                    m_filter.AreaId = new NodeId("Sinumerik", (ushort)2);
                                    m_filter.Severity = EventSeverity.Min;
                                    m_filter.IgnoreSuppressedOrShelved = true;
                                    m_filter.EventTypes = (IList<NodeId>)new NodeId[1]
                                    {
                                     ObjectTypeIds.ConditionType
                                    };
                                    m_filter.SelectClauses = m_filter.ConstructSelectClauses(opcServer.Session, ObjectTypeIds.ConditionType);
                                    for (int index = 0; index < m_filter.SelectClauses.Count<SimpleAttributeOperand>(); ++index)
                                    {
                                        responseBody.errorsInfo += m_filter.SelectClauses[index].ToString() + (object)index + " ";
                                    }
                                }
                                else if (opcBody.Type == ActionTypeEnum.ToolList.ToString())
                                {
                                    List<ToolsInfo> toolInfoList = new List<ToolsInfo>();
                                    int index = 1;
                                    List<string> stringList = this.readVariables(opcServer, new string[6]
                                       {
                                          "/Tool/Catalogue/toolNo[u<Area index>, <Row index>]".Replace("<Area index>", this.currentToolArea.ToString()).Replace("<Row index>", index.ToString()),
                                          "/Tool/Catalogue/toolIdent[u<Area index>, <Row index>]".Replace("<Area index>", this.currentToolArea.ToString()).Replace("<Row index>", index.ToString()),
                                          "/Tool/Catalogue/toolInMag[u<Area index>, <Row index>]".Replace("<Area index>", this.currentToolArea.ToString()).Replace("<Row index>", index.ToString()),
                                          "/Tool/Catalogue/toolInPlace[u<Area index>, <Row index>]".Replace("<Area index>", this.currentToolArea.ToString()).Replace("<Row index>", index.ToString()),
                                          "/Tool/Catalogue/nrDuplo[u<Area index>, <Row index>]".Replace("<Area index>", this.currentToolArea.ToString()).Replace("<Row index>", index.ToString()),
                                          "/Tool/Catalogue/numCuttEdges[u<Area index>, <Row index>]".Replace("<Area index>", this.currentToolArea.ToString()).Replace("<Row index>", index.ToString())
                                       }
                                       );
                                    ToolsInfo toolInfo = new ToolsInfo(); ;
                                    toolInfo.number = Convert.ToUInt16(stringList[0]) + "";
                                    //toolInfo.toolIdent = stringList[1];
                                    //toolInfo.toolInMag = Convert.ToUInt16(stringList[2]);
                                    //toolInfo.toolInPlace = Convert.ToUInt16(stringList[3]);
                                    //toolInfo.nrDuplo = Convert.ToUInt16(stringList[4]);
                                    //toolInfo.numCuttEdges = Convert.ToUInt16(stringList[5]);
                                    toolInfoList.Add(toolInfo);
                                    responseBody.toolsInfo = JsonConvert.SerializeObject(toolInfoList);
                                }
                                else if (opcBody.Type == ActionTypeEnum.Read.ToString())
                                {
                                    responseBody.values = opcServer.ReadValues(opcBody.Addresses);
                                }
                                else if (opcBody.Type == ActionTypeEnum.Write.ToString())
                                {
                                    opcServer.WriteValues(opcBody.Values, opcBody.Addresses);
                                }
                                else if (opcBody.Type == ActionTypeEnum.SelectNc.ToString())
                                {
                                    string sSelectedFileName = Path.GetFileName(opcBody.Path);
                                    string status = opcServer.MethodCallSelectProgram(UPLOAD_NC_PATH + sSelectedFileName, Convert.ToUInt32(CHANNEL_NO)).status;
                                    if (status == "Good")
                                    {
                                        responseBody.msg = "选择成功";
                                    }
                                    else
                                    {
                                        responseBody.msg = "选择失败";
                                    }
                                }
                                else if (opcBody.Type == ActionTypeEnum.Upload.ToString())
                                {
                                    string file = opcBody.Path;
                                    string serverPath = "";
                                    //选择临时文件
                                    string status = opcServer.MethodCallSelectProgram(UPLOAD_NC_PATH + TEMP_NC_NAME, Convert.ToUInt32(CHANNEL_NO)).status;
                                    try
                                    {
                                        string extension = Path.GetExtension(file);
                                        if (string.IsNullOrWhiteSpace(extension))
                                        {
                                            responseBody.msg = "文件名不合法";
                                        }
                                        try
                                        {

                                            byte[] data = opcServer.ReadFile(file);

                                            serverPath = UPLOAD_NC_PATH + Path.GetFileName(file);
                                            Server.MethodCallResult methodCallResult = opcServer.MethodCallCopyFileToServer("/Methods/CopyFileToServer", serverPath, data, true);

                                            if (methodCallResult.status.ToUpper().Equals("GOOD"))
                                            {
                                                responseBody.msg = "上传文件成功";
                                                YG.Log.Instance.WriteLogAdd(file + "上传文件成功");
                                            }
                                            else
                                            {
                                                responseBody.msg = "上传文件失败";
                                                YG.Log.Instance.WriteLogAdd(file + "上传文件失败");
                                            }
                                            // } 
                                        }
                                        catch (Exception ex)
                                        {
                                            responseBody.msg = "上传文件失败===>" + ex.Message;
                                            YG.Log.Instance.WriteLogAdd($"{ex.Message}");
                                        }


                                    }
                                    catch (Exception ex)
                                    {
                                        responseBody.msg = "上传文件失败===>" + ex.Message;
                                        YG.Log.Instance.WriteLogAdd($"493-->{ex.Message}");
                                    }
                                    //设位主程序
                                    status = opcServer.MethodCallSelectProgram(serverPath, Convert.ToUInt32(CHANNEL_NO)).status;
                                }

                            }
                            else
                            {
                                responseBody.code = 0;
                                responseBody.msg = "服务器离线，连不上opcUa";
                                responseBody.result = false;
                            }
                            response.ContentType = "application/json;charset=UTF-8";
                            response.ContentEncoding = Encoding.UTF8;
                            response.AppendHeader("Content-Type", "application/json;charset=UTF-8");
                            string retJsonData = JsonConvert.SerializeObject(responseBody);


                            using (StreamWriter writer = new StreamWriter(response.OutputStream, Encoding.UTF8))
                            {
                                YG.Log.Instance.WriteLogAdd($"WMS--->>{responseBody.Json_SerializeObject()}--->>{body}\r\n");

                                writer.Write(responseBody.Json_SerializeObject());
                                writer.Close();
                                response.Close();
                            }

                        }
                        catch (Exception opcex)
                        {
                            AddList(DateTime.Now.ToString(), "POST", request.Url.ToString(), opcex.Message);
                        }
                    }
                }
                else if (request.HttpMethod == "GET")
                {
                    if (!request.Url.ToString().Contains("favicon"))
                    {
                        string ip = request.QueryString["ip"];
                        string port = request.QueryString["port"];
                        string fun = request.QueryString["fun"];

                        AddList(DateTime.Now.ToString(), "GET", ip + port + fun, "OK");

                    }
                }
                response.Close();
            }


        }
        private List<string> readVariables(Server server, string[] variables)
        {
            List<string> nodeIdStrings = new List<string>();
            foreach (string variable in variables)
            {
                NodeId nodeId = new NodeId(variable, (ushort)2);
                nodeIdStrings.Add(nodeId.ToString());
            }
            return server.ReadValues(nodeIdStrings);
        }
        public class DeviceInfo
        {
            public string ConnectMsg
            { get; set; }
            public string ConnectErrorMsg
            { get; set; }
            public string CncSoftVersion
            { get; set; }
            public string CncType
            { get; set; }
            public string CncId
            { get; set; }
            public string CncMode
            { get; set; }
            public string RunStatus
            { get; set; }
            public string Products
            { get; set; }
            public string CycleTime
            { get; set; }
            public string RemainTime
            { get; set; }
            public string MainProg
            { get; set; }
            public string SetFeedSpeed
            { get; set; }
            public string ActFeedSpeed
            { get; set; }
            public string SetSpSpeed
            { get; set; }

            public string ActSpSpeed
            { get; set; }
            public string AxisName
            { get; set; }
            public string FeedRate
            { get; set; }
            public string SpRate
            { get; set; }
            public string MaxPos1
            { get; set; }
            public string MaxPos2
            { get; set; }
            public string MaxPos3
            { get; set; }
            public string RelPos1
            { get; set; }
            public string RelPos2
            { get; set; }
            public string RelPos3
            { get; set; }
            public string RemainPos1
            { get; set; }
            public string RemainPos2
            { get; set; }
            public string RemainPos3
            { get; set; }
            public string ToolNo
            { get; set; }
            public string LenthX
            { get; set; }
            public string LenthZ
            { get; set; }
            public string RadiusCompenNum
            { get; set; }
            public string LengthCompenNum
            { get; set; }
            public string ToolAbradeRadius
            { get; set; }
            public string ToolEdgePos
            { get; set; }
            public string IsAlarm
            { get; set; }
            public List<AlmInfo> AlmMsg { get; set; } = new List<AlmInfo>();

            public string ToolLife
            { get; set; }


        }
        public class AlmInfo
        {
            public string no { get; set; }
            public string msg { get; set; }

        }
        public class Servlet
        {
            public virtual void onGet(System.Net.HttpListenerRequest request, System.Net.HttpListenerResponse response, string info) { }
            public virtual void onPost(System.Net.HttpListenerRequest request, System.Net.HttpListenerResponse response) { }

            public virtual void onCreate()
            {

            }
        }


        public void AddList(string dtime, string type, string url, string res)
        {
            this.Invoke(new Action(delegate ()
            {
                listView1.BeginUpdate();   //数据更新，UI暂时挂起，直到EndUpdate绘制控件，可以有效避免闪烁并大大提高加载速度
                ListViewItem lvi = new ListViewItem();
                lvi.Text = dtime;
                lvi.SubItems.Add(type);
                lvi.SubItems.Add(url);
                lvi.SubItems.Add(res);
                this.listView1.Items.Insert(0, lvi);
                if (this.listView1.Items.Count > 100)
                {
                    this.listView1.Items.Clear();
                }

                this.listView1.EndUpdate();  //结束数据处理，UI界面一次性绘制。}

            }));

        }


        public class MyServlet : Servlet
        {
            public override void onCreate()
            {
                base.onCreate();
            }

            public override void onGet(HttpListenerRequest request, HttpListenerResponse response, string info)
            {
                Console.WriteLine("GET:" + request.Url);


                byte[] buffer = Encoding.UTF8.GetBytes(info);
                //string sss = request.QueryString["ty"];
                System.IO.Stream output = response.OutputStream;
                output.Write(buffer, 0, buffer.Length);
                // You must close the output stream.
                output.Close();
                //listener.Stop();
            }

            public override void onPost(HttpListenerRequest request, HttpListenerResponse response)
            {
                Console.WriteLine("POST:" + request.Url);
                byte[] res = Encoding.UTF8.GetBytes("OK");
                response.OutputStream.Write(res, 0, res.Length);
            }
        }

    }
}
