using System;
using System.Collections.Generic;
using System.Drawing;
using System.Windows.Forms;
using HslCommunication;
using HslCommunication.ModBus;
using System.Threading;
using System.Collections;
using HslCommunication.Controls;
using VzClientSDKDemo;
using System.Runtime.InteropServices;
using System.IO;
using System.Net;
using parkMonitor.entity;
using System.Diagnostics;
using System.Threading.Tasks;
using parkMonitor.model;
using parkMonitor.viewModel.objectTree;
using parkMonitor.server.uiLogServer;
using System.Configuration;
using parkMonitor.LOG;
using parkMonitor.server.broadcastModule;
using BroadcastModule;

namespace parkMonitor.server
{

    /// <summary>
    /// 号牌机通信类
    /// </summary>
    public partial class NumMachineLinker : Form, IEquipments
    {
        /// <summary>
        /// 刷新时间间隔与个数
        /// </summary>
        public const int REFRESHINGTIME = 500, FILTERINGNUMBER = 8;
        ///<summary>通过设备句柄访问pic；链接时add，系统关闭时remove</summary>
        private static Dictionary<int, PictureBox> devPicMap = new Dictionary<int, PictureBox>();
        ///<summary>通过名字获取pic对象；创建pic时add,系统关闭remove</summary>
        private static Dictionary<string, PictureBox> namePicMap = new Dictionary<string, PictureBox>();
        ///<summary>通过ip获取设备id；产生ip时创建</summary>
        private static Dictionary<string, int> ipIdMap = new Dictionary<string, int>();
        ///<summary>通过ip获取设备句柄；产生句柄时创建</summary>
        private static Dictionary<string, int> ipHandleMap = new Dictionary<string, int>();
        /// <summary>句柄到号牌回调映射</summary>
        private static Dictionary<int, VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK> handleCallbackMap = new Dictionary<int, VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK>();
        ///<summary>号牌队列</summary>
        private static Queue<NumberMachineNode> LicBuffer = new Queue<NumberMachineNode>();
        ///<summary>计数Map</summary>
        private static Dictionary<string, Dictionary<NumberMachineNode, int>> filterMap = new Dictionary<string, Dictionary<NumberMachineNode, int>>();
        /// <summary>筛选计数</summary>
        private static int filterCount = 0;
        private static double filterRatio = 0.7;
        /// <summary>系统关闭</summary>
        private static bool isClosing = false;
        /// <summary>开启拍照的设备</summary>
        private static int snapshotDevHandle = -1;
        /// <summary>允许无号牌时拍照</summary>
        private static bool enableEmptySnapshot = true;

        private static NumberMachineMessage nmMsg = new NumberMachineMessage();
        private static VzClientSDK.VZLPRC_FIND_DEVICE_CALLBACK_EX find_DeviceCB = null;
        private const int MSG_PLATE_INFO = 0x901;
        private const int MSG_DEVICE_INFO = 0x902;
        /// <summary>
        /// 用于消息传递机制
        /// </summary>
        public static IntPtr hwndMain;

        /// <summary>
        /// 号牌机类构造函数
        /// </summary>
        public NumMachineLinker()
        {
            Control.CheckForIllegalCrossThreadCalls = false;
            InitializeComponent();

            Thread thread = new Thread(new ThreadStart(DateTimeInfo));
            thread.IsBackground = true;
            thread.Start(); //显示当前时间            

            VzClientSDK.VzLPRClient_Setup();

            hwndMain = this.Handle;

            try
            {
                filterRatio = Double.Parse(ConfigurationManager.AppSettings.Get("filterRatio"));
            }
            catch (Exception) { UILogServer.ins.error("号牌机配置文件异常"); Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "号牌机配置文件异常"); }
            //m_sAppPath = System.IO.Directory.GetCurrentDirectory();
        }

        /// <summary>
        /// 定义时钟委托
        /// </summary>
        public delegate void SetDateTime();

        /// <summary>
        /// 实时采集
        /// </summary>
        public delegate void Begin_Read();

        private void FormSiemens_Load(object sender, EventArgs e)
        {
            Thread thread = new Thread(new ThreadStart(DateTimeInfo));
            thread.IsBackground = true;
            thread.Start(); //显示当前时间            

            VzClientSDK.VzLPRClient_Setup();

            hwndMain = this.Handle;
            //m_sAppPath = System.IO.Directory.GetCurrentDirectory();
            //this.ShowInTaskbar = false;
            //this.Opacity = 0;

        }

        private void FormSiemens_FormClosing(object sender, FormClosingEventArgs e)
        {
            Stop();
        }

        private void DateTimeInfo()
        {
            try
            {
                while (!isClosing)
                {
                    SetDateTime setDate = new SetDateTime(
                    delegate
                    {
                        toolStripStatusLabel2.Text = DateTime.Now.ToString();
                    });
                    setDate();
                    Thread.Sleep(1000);
                }
                // ReSharper disable once FunctionNeverReturns
            }
            catch (Exception e) { Debug.Print(e.StackTrace); }

        }

        //******************************************************************************************************************
        private void UpdateStatus(NumberMachineNode nmn)
        {
            //提示次数计数
            int count = 0;
            while (!isClosing)
            {
                if (GetStatus(nmn.ip) == 1)
                {
                    nmn.status = EnumNumberMachineStatus.Normal;
                    count = 0;
                }
                else
                {
                    count++;
                    //号牌机断线写日志
                    nmn.status = EnumNumberMachineStatus.Offline;
                    if (count == 1)
                    {
                        Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "正在与ip为 " + nmn.ip + " 的号牌机 进行连接。");
                        UILogServer.ins.info("正在与ip为 " + nmn.ip + " 的号牌机 进行连接。");
                    }
                    Thread.Sleep(10000);
                }
                Thread.Sleep(REFRESHINGTIME);
            }
        }

        private void Run()
        {
            try
            {
                while (!isClosing)
                {
                    Thread.Sleep(REFRESHINGTIME);
                    //定时返回号牌
                    lock (devPicMap)
                    {
                        Dictionary<int, PictureBox>.Enumerator devEnumer = devPicMap.GetEnumerator();
                        while (devEnumer.MoveNext())
                        {
                            ActivateSnap(devEnumer.Current.Key);
                            //Debug.WriteLine(lv.data.Count.ToString()+":\n"+ lv.data[lv.data.Count-1].LicenseNum+ lv.data[lv.data.Count - 1].TimeRecord);
                        }
                    }
                    //读取设备ip与id映射关系
                    lock (ipHandleMap)
                    {
                        Dictionary<string, int>.Enumerator ipEnumer = ipHandleMap.GetEnumerator();
                        while (ipEnumer.MoveNext())
                        {
                            //映射关系不存在则读取配置文件
                            lock (ipIdMap)
                            {
                                if (ipEnumer.Current.Key != null && !ipIdMap.ContainsKey(ipEnumer.Current.Key))
                                {
                                    try
                                    {
                                        int id = Int32.Parse(ConfigurationManager.AppSettings.Get(ipEnumer.Current.Key));
                                        ipIdMap.Add(ipEnumer.Current.Key, id);
                                    }
                                    catch (Exception) { UILogServer.ins.log("读取号牌机编号映射失败，配置文件填写有误"); Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "读取号牌机编号映射失败"); }
                                }
                            }
                        }
                    }
                    lock (LicBuffer)
                    {
                        //删除已停好车的号牌
                        for (int i = 0; i < LicBuffer.Count; i++)
                        {
                            NumberMachineNode n = (NumberMachineNode)LicBuffer.Dequeue().Clone();
                            if (n.ip != "")
                            {
                                LicBuffer.Enqueue((NumberMachineNode)n.Clone());
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.WriteLine(ex.ToString());
            }
        }

        ///<summary>寻找设备回调函数</summary>
        private void FIND_DEVICE_CALLBACK_EX(string pStrDevName, string pStrIPAddr, ushort usPort1, ushort usPort2, uint SL, uint SH, string netmask, string gateway, IntPtr pUserData)
        {
            string pStrDev = pStrIPAddr.ToString() + ":" + usPort1.ToString();
            string serialNO = SL.ToString() + ":" + SH.ToString() + ":" + netmask + ":" + gateway;

            VzClientSDK.VZ_LPR_DEVICE_INFO device_info = new VzClientSDK.VZ_LPR_DEVICE_INFO();
            device_info.device_ip = pStrDev;
            device_info.serial_no = serialNO;
            DeviceLink(pStrDev, serialNO);
        }

        ///<summary>与设备连接，启动更新设备状态线程，输出视频</summary>
        private void DeviceLink(string pStrDev, string serialNO)
        {
            IPEndPoint ipe;
            GetIpEndPoint(pStrDev, out ipe);
            string ip = ipe.Address.ToString();
            if (ipHandleMap.ContainsKey(ip))
            {
                //MessageBox.Show("设备已分配句柄");
                return;
            }
            int handle = 0;
            //找到设备，加入list
            NumberMachineNode node = new NumberMachineNode(ip, 0, "", "", 1);
            nmMsg.data.Add(node);
            handle = VzClientSDK.VzLPRClient_Open(ip, (ushort)80, "admin", "admin");
            Task.Factory.StartNew(() =>
            {
                UpdateStatus(node);
            });
            if (handle == 0)
            {
                return;
            }

            VzClientSDK.VzLPRClient_SetVideoEncodeType(handle, 0);
            //将句柄加入
            lock (ipHandleMap)
            {
                ipHandleMap.Add(ip, handle);
            }
            //MessageBox.Show("摄像头打开成功");
            lock (handleCallbackMap)
            {
                handleCallbackMap.Add(handle, null);
            }
            //链接句柄到新PictureBox
            VideoOutput(handle);
        }

        ///<summary>视频输出</summary>
        private void VideoOutput(int handle)
        {
            try
            {
                lock (devPicMap)
                {
                    lock (handleCallbackMap)
                    {
                        //存在设备则复位并在原pic上输出
                        if (devPicMap.ContainsKey(handle))
                        {
                            VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, null, IntPtr.Zero, 0);
                            PictureBox pic;
                            if (devPicMap.TryGetValue(handle, out pic) && handleCallbackMap.ContainsKey(handle))
                            {
                                int playHandle = VzClientSDK.VzLPRClient_StartRealPlay(handle, pic.Handle);
                                // 设置车牌识别结果回调
                                handleCallbackMap[handle] = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
                                VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, handleCallbackMap[handle], IntPtr.Zero, 1);
                                //m_PlateResultCB = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
                                //VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, m_PlateResultCB, IntPtr.Zero, 1);
                                //VzClientSDK.VzLPRClient_StopRealPlay(handle);
                            }
                        }
                        else//否则找一个空位加pic
                        {
                            for (int i = 0; i < 20; i++)
                            {
                                string str = "PictureBox" + Convert.ToString(i);
                                //该名称对应控件不存在,则创建并链接pic
                                lock (namePicMap)
                                {
                                    if (!namePicMap.ContainsKey(str) && handleCallbackMap.ContainsKey(handle))
                                    {
                                        PictureBox pic;
                                        if (CreatePic(i, out pic))
                                        {
                                            devPicMap.Add(handle, pic);
                                            //ipIdMap.Add(Get_IP(handle), i);
                                            VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, null, IntPtr.Zero, 0);
                                            int playHandle = VzClientSDK.VzLPRClient_StartRealPlay(handle, pic.Handle);
                                            // 设置车牌识别结果回调
                                            handleCallbackMap[handle] = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
                                            VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, handleCallbackMap[handle], IntPtr.Zero, 1);
                                            //m_PlateResultCB = new VzClientSDK.VZLPRC_PLATE_INFO_CALLBACK(OnPlateResult);
                                            //VzClientSDK.VzLPRClient_SetPlateInfoCallBack(handle, m_PlateResultCB, IntPtr.Zero, 1);
                                            //VzClientSDK.VzLPRClient_StopRealPlay(handle);
                                            break;
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception)
            {
                Debug.WriteLine("jumped out");
            }
        }

        ///<summary>号牌信息回调</summary>
        private int OnPlateResult(int handle, IntPtr pUserData,
                                                IntPtr pResult, uint uNumPlates,
                                                VzClientSDK.VZ_LPRC_RESULT_TYPE eResultType,
                                                IntPtr pImgFull,
                                                IntPtr pImgPlateClip)
        {
            if (eResultType != VzClientSDK.VZ_LPRC_RESULT_TYPE.VZ_LPRC_RESULT_REALTIME)
            {
                VzClientSDK.TH_PlateResult result = (VzClientSDK.TH_PlateResult)Marshal.PtrToStructure(pResult, typeof(VzClientSDK.TH_PlateResult));
                string strLicense = (new string(result.license)).Split('\0')[0];

                VzClientSDK.VZ_LPR_MSG_PLATE_INFO plateInfo = new VzClientSDK.VZ_LPR_MSG_PLATE_INFO();
                plateInfo.plate = strLicense;
                SetDetail(plateInfo, Get_IP(handle));

                //根据setMessage中通过id信息找到的handle保存图片
                if (handle == snapshotDevHandle)
                {
                    if (enableEmptySnapshot || !strLicense.Contains("_无_"))
                    {
                        string strFilePath = ConfigurationManager.AppSettings["LogPath"] + DateTime.Now.ToString("yyyyMMdd") + "\\";
                        if (!Directory.Exists(strFilePath))
                        {
                            Directory.CreateDirectory(strFilePath);
                        }
                        string ip = Get_IP(handle);
                        string path = strFilePath + ip + "-" + DateTime.Now.ToString("hh_mm_ss") + ".jpg";
                        int temp = VzClientSDK.VzLPRClient_ImageSaveToJpeg(pImgFull, path, 50);
                        if (temp != -1)
                        {
                            Log.WriteLog(LogType.NOT_DATABASE, LogFile.LOG, "号牌机" + ip + "已拍照，图片保存于 " + strFilePath);
                            UILogServer.ins.info("号牌机" + ip + "已拍照，图片保存于 " + strFilePath);
                        }
                        else
                        {
                            UILogServer.ins.info("图片保存失败");
                            Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "图片保存失败");
                        }
                    }
                    snapshotDevHandle = -1;
                }
            }

            return 0;
        }

        ///<summary>记录车牌，时间，状态信息；刷新本地entity，并且入buffer</summary>
        private void SetDetail(VzClientSDK.VZ_LPR_MSG_PLATE_INFO plateInformation, string strIP)
        {
            int stat = GetStatus(strIP);
            bool found = false;
            int id = 0;
            lock (ipIdMap)
            {
                if (!ipIdMap.ContainsKey(strIP))
                {
                    try
                    {
                        id = Int32.Parse(ConfigurationManager.AppSettings.Get(strIP));
                        ipIdMap.Add(strIP, id);
                    }
                    catch (Exception) { UILogServer.ins.error("读取号牌机编号映射失败，配置文件填写有误"); Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "读取号牌机编号映射失败"); }
                }
            }
            //检查设备是否存在
            foreach (NumberMachineNode nmn in nmMsg.data)
            {
                //相同设备
                if (nmn.ip == strIP)
                {
                    found = true;
                    //号牌不为空
                    if (!(plateInformation.plate.Contains("_无_")))
                    {
                        nmn.SetLic(strIP, nmn.id, plateInformation.plate, DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss"), GetStatus(strIP));
                        FilterLic(strIP, (NumberMachineNode)nmn.Clone());
                    }
                    //号牌为空
                    else
                    {
                        nmn.SetLic(strIP, nmn.id, "", "", GetStatus(strIP));
                    }
                }
            }
            //新设备
            if (!found)
            {
                lock (ipIdMap)
                {
                    if (!(plateInformation.plate.Contains("_无_")) && ipIdMap.TryGetValue(strIP, out id))
                    {
                        NumberMachineNode nmn = new NumberMachineNode(strIP, id, plateInformation.plate, DateTime.Now.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss"), GetStatus(strIP));
                        NumberMachineNode nmnc = (NumberMachineNode)nmn.Clone();
                        nmMsg.data.Add(nmnc);
                        FilterLic(strIP, nmnc);
                    }
                    else
                    {
                        nmMsg.data.Add(new NumberMachineNode(strIP, id, "", "", GetStatus(strIP)));
                    }
                }
            }
        }

        ///<summary>筛选号牌</summary>
        private void FilterLic(string ip, NumberMachineNode nmn)
        {
            Dictionary<NumberMachineNode, int> filter;
            //该filter不存在则创建
            if (!filterMap.ContainsKey(ip))
            {
                filter = new Dictionary<NumberMachineNode, int>();
                filterMap.Add(ip, filter);
            }
            //计数器异常
            else if (!filterMap.TryGetValue(ip, out filter))
            {
                return;
            }

            //filter计数
            int count = 0;
            if (filter.ContainsKey(nmn) && filter.TryGetValue(nmn, out count))//存在则数量+1
            {
                filter[nmn] = count + 1;
            }
            else//不存在则计数1
            {
                filter.Add(nmn, 1);
            }

            //计算总数
            filterCount = 0;
            Dictionary<NumberMachineNode, int>.Enumerator countEnumer = filter.GetEnumerator();
            while (countEnumer.MoveNext())
            {
                filterCount += countEnumer.Current.Value;
            }

            //达到计数限制，计算众数是否达标，达标则入队
            if (filterCount >= FILTERINGNUMBER)
            {
                lock (LicBuffer)
                {
                    Dictionary<NumberMachineNode, int>.Enumerator enumer = filter.GetEnumerator();
                    while (enumer.MoveNext())
                    {
                        //遍历，筛到号牌则入队
                        if (enumer.Current.Value >= (int)(filterCount * filterRatio) && enumer.Current.Key != null && !LicBuffer.Contains(enumer.Current.Key))
                        {
                            if (nmMsg.aNode == null || nmMsg.aNode.LicenseNum == null || nmMsg.aNode.LicenseNum != enumer.Current.Key.LicenseNum)
                            {
                                NumberMachineNode node = (NumberMachineNode)enumer.Current.Key.Clone();
                                if (ipIdMap.TryGetValue(node.ip, out node.id))
                                {
                                    LicBuffer.Enqueue((NumberMachineNode)node.Clone());
                                    if (node.id == 1)
                                    {
                                        if (BroadcastLinker.ins != null)
                                        {
                                            BroadcastLinker.ins.Play(1, BroadcastBoard.PlayMode.temporary, node.LicenseNum, 15);
                                            BroadcastLinker.ins.Play(0, BroadcastBoard.PlayMode.audio, node.LicenseNum + "，入场");
                                        }
                                    }
                                }
                            }
                        }
                    };
                    filterCount = 0;
                    filter.Clear();
                }
            }
        }

        ///<summary>停止播放与设备句柄关联的视频</summary>
        private void StopPlay(int handleInput)
        {
            if (handleInput != 0)
            {
                int ret = VzClientSDK.VzLPRClient_StopRealPlay(handleInput);
            }
        }

        ///<summary>强制获取号牌</summary>
        private void ActivateSnap(int handle)
        {
            if (handle > 0)
            {
                VzClientSDK.VzLPRClient_ForceTrigger(handle);
            }

        }

        ///<summary>ip+port字符串转ipe</summary>
        private void GetIpEndPoint(string ipp, out IPEndPoint ipe)
        {
            IPAddress myIP = IPAddress.Parse(ipp.Remove(ipp.LastIndexOf(':')) + "");
            string myPort = ipp.Substring(ipp.IndexOf(':') + 1);
            ipe = new IPEndPoint(myIP, int.Parse(myPort));
        }

        ///<summary>创建新pic并记录在picNameMap</summary>
        private bool CreatePic(int index, out PictureBox pb)
        {
            pb = new PictureBox
            {
                Width = 230,
                Height = 180,
                AutoSize = false,
                Name = "PictureBox" + Convert.ToString(index)
            };
            lock (namePicMap)
            {
                if (!namePicMap.ContainsKey(pb.Name))
                {
                    flowLayoutPanel1.Controls.Add(pb);
                    namePicMap.Add(pb.Name, pb);
                    return true;
                }
                else
                    return false;
            }
        }

        ///<summary>更新设备状态</summary>
        private int GetStatus(string devIP)
        {
            int myHandle;
            byte stat = 0;
            if (ipHandleMap.TryGetValue(devIP, out myHandle))
            {
                VzClientSDK.VzLPRClient_IsConnected(myHandle, ref stat);
                return stat;
            }
            return -1;
        }

        private string Get_IP(int lprHandle)
        {
            byte[] strDecIP = new byte[32];
            int max_count = 32;
            int ret = VzClientSDK.VzLPRClient_GetDeviceIP(lprHandle, ref strDecIP[0], max_count);
            string strIP = System.Text.Encoding.Default.GetString(strDecIP);
            strIP = strIP.TrimEnd('\0');
            return strIP;
        }

        private bool NodeValidation(NumberMachineNode node)
        {
            return (node != null && node.ip != null && node.ip != "" && node.ip != "used" && node.LicenseNum != null && node.LicenseNum != "") ? true : false;
        }

        /// <summary>
        /// 系统启动
        /// </summary>
        public void Start()
        {

            Task.Factory.StartNew(() =>
            {
                isClosing = false;

                try
                {
                    VzClientSDK.VZLPRClient_StopFindDevice();

                    find_DeviceCB = new VzClientSDK.VZLPRC_FIND_DEVICE_CALLBACK_EX(FIND_DEVICE_CALLBACK_EX);
                    int ret = VzClientSDK.VZLPRClient_StartFindDeviceEx(find_DeviceCB, IntPtr.Zero);
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.ToString());
                }
            });

            Task.Factory.StartNew(() =>
            {
                Run();
            });

            //Task imgTest = Task.Factory.StartNew(() =>
            //{
            //    while (!isClosing)
            //    {
            //        Command cmd = new Command
            //        {
            //            id = 1
            //        };
            //        SetMessage(cmd);
            //        Thread.Sleep(30000);
            //        Command cmd2 = new Command
            //        {
            //            id = 2
            //        };
            //        SetMessage(cmd2);
            //        Thread.Sleep(30000);
            //    }
            //});

        }

        /// <summary>
        /// 系统关闭
        /// </summary>
        public void Stop()
        {
            VzClientSDK.VZLPRClient_StopFindDevice();
            lock (devPicMap)
            {
                Dictionary<int, PictureBox>.Enumerator enumer = devPicMap.GetEnumerator();
                while (enumer.MoveNext())
                {
                    if (enumer.Current.Key != 0)
                    {
                        StopPlay(enumer.Current.Key);
                        VzClientSDK.VzLPRClient_Close(enumer.Current.Key);
                        flowLayoutPanel1.Controls.Remove(enumer.Current.Value);
                    }
                }
                isClosing = true;
                devPicMap.Clear();
            }
            lock (namePicMap) { namePicMap.Clear(); }
            lock (ipIdMap) { ipIdMap.Clear(); }
            lock (ipHandleMap) { ipHandleMap.Clear(); }
            //this.Close();
        }

        /// <summary>
        /// 监控线程获取号牌机信息，核心线程获取号牌信息
        /// </summary>
        public AbstractMessage GetMessage()
        {
            lock (LicBuffer)
            {
                //准备输出的数据中存在非法Node，且LicBuffer可出队产生一个合法Node，则替换该非法Node
                if (!NodeValidation(nmMsg.aNode))
                {
                    for (int i = 0; i < LicBuffer.Count; i++)
                    {
                        NumberMachineNode n = LicBuffer.Dequeue();
                        if (NodeValidation(n))
                        {
                            if (nmMsg.aNode != null && nmMsg.aNode.ip != null)
                            {
                                LicBuffer.Enqueue((NumberMachineNode)nmMsg.aNode.Clone());
                            }
                            nmMsg.aNode = n;
                            break;
                        }
                        else
                        {
                            LicBuffer.Enqueue(n);
                        }
                    }
                    //遍历licBuffer后仍不合法，则丢入队列，将node置为null
                    if (!NodeValidation(nmMsg.aNode))
                    {
                        if (nmMsg.aNode != null && nmMsg.aNode.ip != null)
                        {
                            LicBuffer.Enqueue((NumberMachineNode)nmMsg.aNode.Clone());
                        }
                        nmMsg.aNode = null;
                    }
                }
            }
            return nmMsg;
        }

        /// <summary>
        /// 一次停车流程完成时调用该方法，发送已完成车辆号牌信息
        /// </summary>
        /// <param name="message">已完成车辆的号牌相关信息存于message的aNode中,用于标记需清空的号牌</param>
        public void SetMessage(AbstractMessage message)
        {
            if (message.GetType().Equals(typeof(NumberMachineMessage)))
            {
                NumberMachineNode n = ((NumberMachineMessage)message).aNode;
                lock (LicBuffer)
                {
                    //输入号牌格式无误
                    if (n != null && n.ip != null && n.ip == "")
                    {
                        //与类成员变量中aNode号牌相同，将其ip复位表示已使用，重新入队等待清除
                        if (nmMsg != null && nmMsg.aNode != null && nmMsg.aNode.LicenseNum == n.LicenseNum)
                        {
                            nmMsg.aNode.ip = "";
                            LicBuffer.Enqueue((NumberMachineNode)nmMsg.aNode.Clone());
                            nmMsg.aNode = null;
                        }
                        //搜索号牌队列，将相应号牌置空，准备清除
                        else
                        {
                            for (int i = 0; i < LicBuffer.Count; i++)
                            {
                                NumberMachineNode temp = LicBuffer.Dequeue();
                                //已匹配上，ip置空
                                if (temp.LicenseNum == n.LicenseNum)
                                {
                                    temp.ip = "";
                                    LicBuffer.Enqueue(temp);
                                    break;
                                }
                                LicBuffer.Enqueue(temp);
                            }
                        }
                    }
                }
            }
            //传入异常号牌，根据ip找到handle，改变snapshotDevHandle的值在回调函数中截图
            if (message.GetType().Equals(typeof(Command)))
            {
                Command cmd = (Command)message;
                if (cmd != null && cmd.id != 0)
                {
                    lock (ipIdMap)
                    {
                        Dictionary<string, int>.Enumerator enumerator = ipIdMap.GetEnumerator();
                        while (enumerator.MoveNext())
                        {
                            // if (enumerator.Current.Value == cmd.id && ipHandleMap.TryGetValue(enumerator.Current.Key, out int handle))
                            int handle = 0;
                            if (enumerator.Current.Value == cmd.id && ipHandleMap.TryGetValue(enumerator.Current.Key, out handle))
                            {
                                snapshotDevHandle = handle;
                                break;
                            }
                        }
                    }
                }
                else
                {
                    UILogServer.ins.error("参数错误，图片未保存");
                    Log.WriteLog(LogType.NOT_DATABASE, LogFile.ERROR, "参数错误，图片未保存");
                }
            }

        }
    }

    public class NumMachineManager : IEquipments
    {
        public static NumMachineLinker ins;
        public AbstractMessage GetMessage()
        {
            if (ins != null)
            {
                return ins.GetMessage();
            }
            return null;
        }

        public void SetMessage(AbstractMessage message)
        {
            if (ins != null)
            {
                ins.SetMessage(message);
            }
        }

        public void Start()
        {
            Task.Factory.StartNew(() =>
            {
                ins = new NumMachineLinker();
                Task.Factory.StartNew(() =>
                {
                    ins.Start();
                    //ins.Bounds = new Rectangle(0, 0, 0, 0);
                    //ins.ShowDialog();
                });
                //ins.WindowState = FormWindowState.Minimized;
                ins.Hide();
            });
        }

        public void Stop()
        {
            Task.Factory.StartNew(() =>
            {
                ins.Close();
                ins.Stop();
            });
        }
    }

}
