using parkMonitor.entity;
using parkMonitor.server.NumMachine;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace parkMonitor.server
{
    class NumMachineSimul : IEquipments
    {
        private const int licInterval = 5000;//90秒
        ///<summary>号牌队列</summary>
        private Queue<NumberMachineNode> LicBuffer = new Queue<NumberMachineNode>();
        /// <summary>
        /// 号牌信息
        /// </summary>
        private NumberMachineMessage nmMsg = new NumberMachineMessage();
        private const string header = "鄂A";
        /// <summary>
        /// 号牌数组
        /// </summary>
        private List<string> NumExamples = new List<string>();
        /// <summary>
        /// 号牌对象数组
        /// </summary>
        private List<NumberMachineNode> NumNodes = new List<NumberMachineNode>();
        private bool closing = false;

        /// <summary>
        /// 主逻辑
        /// </summary>
        private void Run()
        {
            while (!closing)
            {
                lock (NumNodes)
                {
                    foreach (NumberMachineNode n in NumNodes)
                    {
                        lock (LicBuffer)
                        {
                            if (!LicBuffer.Contains(n) && (nmMsg.aNode==null || nmMsg.aNode.LicenseNum!=n.LicenseNum))
                            {
                                n.TimeRecord = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                                LicBuffer.Enqueue((NumberMachineNode)n.Clone());
                            }
                            //除去已停车完成的号牌
                            NumberMachineNode temp = null;
                            for (int i = 0; i < LicBuffer.Count; i++)
                            {
                                temp = (NumberMachineNode)LicBuffer.Dequeue().Clone();
                                if (temp.ip != "")
                                {
                                    LicBuffer.Enqueue(temp);
                                }
                            }
                        }
                        Thread.Sleep(licInterval);
                    }
                }
                Thread.Sleep(200);
            }
        }

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

        /// <summary>
        /// 监控线程获取号牌机信息，核心线程获取号牌信息
        /// </summary>
        public AbstractMessage GetMessage()
        {
            lock (LicBuffer)
            {
                //准备输出的数据中存在非法Node，且LicBuffer可出队产生一个合法Node，则替换该非法Node，否则让Node=null
                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后仍不合法，则置为null
                    if (!NodeValidation(nmMsg.aNode))
                    {
                        if (nmMsg.aNode != null && nmMsg.aNode.ip != null)
                        {
                            LicBuffer.Enqueue((NumberMachineNode)nmMsg.aNode.Clone());
                        }
                        nmMsg.aNode = null;
                    }
                }
            }
            //if (NodeValidation(nmMsg.aNode) && ipIdMap.TryGetValue(nmMsg.aNode.ip, out int id))
            //{
            //    nmMsg.aNode.id = id;
            //}
            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 == "")
                    {
                        //与类成员变量中aNode号牌相同，将其ip复位表示已使用，重新入队等待清除
                        if (nmMsg != null && nmMsg.aNode != null && nmMsg.aNode.LicenseNum.Equals(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.Equals(n.LicenseNum))
                                {
                                    temp.ip = "";
                                    LicBuffer.Enqueue(temp);
                                    break;
                                }
                                LicBuffer.Enqueue(temp);
                            }
                        }
                    }
                }
            }
        }

        public void Start()
        {
            closing = false;
            //创建模拟号牌
            int temp = 0;
            for (int i = 0; i < 10; i++)
            {
                temp = i*11111;
                NumExamples.Add(header + temp.ToString("D5"));
            }
            foreach (string str in NumExamples)
            {
                NumberMachineNode node = new NumberMachineNode("192.168.0.20", 1, str, DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"), 1);
                NumNodes.Add((NumberMachineNode)node.Clone());
            }

            Task.Factory.StartNew(() =>
            {
                Run();
            });
            Task.Factory.StartNew(() =>
            {
                //ManualParkingSimul.ins = new ManualParkingSimul();
                ParkingSimul.ins = new ParkingSimul();
            });
           
        }

        public void Stop()
        {
            closing = true;
        }
    }
}
