using Google.Protobuf;
using Message;
using parkMonitor.LOG;
using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using tool;
using Timer = System.Windows.Forms.Timer;

namespace monitor_main_windows
{

    public partial class MonitorMainWindows : Form
    {
        Timer timer = new Timer();

        public static int s_spacesInRow = 18;
        public static int s_floors = 13;
        public static int s_rows = 1;
        public static bool s_isClosing;
        private static object s_map_update_lock;
        private static object s_parkspace_force_update_queue_lock;
        private static object s_parkspace_status_lock;


        //用于保存step控件
        private ConcurrentDictionary<string, StepControl> m_step_map =
        new ConcurrentDictionary<string, StepControl>();
        /// <summary>
        /// 车位id与车位信息映射
        /// </summary>
        private Dictionary<int, Parkspace_info> m_idPssMap;
        /// <summary>
        /// 强制更新反馈消息队列，用于处理同时收到多个反馈消息的情况
        /// </summary>
        private Queue<Parkspace_force_update_response_msg> m_parkspace_force_update_response_queue;

        /// <summary>
        /// 当前所有车位状态，由界面更新线程主动更新
        /// </summary>
        Parkspace_allocation_data_msg m_parkspace_status;
        Thread m_update_display_thread;
        int m_unitid = -1;

        public MonitorMainWindows()
        {
            m_parkspace_status = new Parkspace_allocation_data_msg();
            s_map_update_lock = new object();
            s_parkspace_force_update_queue_lock = new object();
            s_parkspace_status_lock = new object();
            m_parkspace_force_update_response_queue = new Queue<Parkspace_force_update_response_msg>();
            m_idPssMap = new Dictionary<int, Parkspace_info>();
            s_isClosing = false;
            InitializeComponent();
            json_file_operation.Instance.json_file_operation_init("./settings.json");
            Init();
        }
        public void Init()
        {
            //初始化json文件操作
            Monitor_communication.Instance.monitor_communication_init();
            Monitor_communication.Instance.SetParkspaceForceUpdateResponseDelegate(ParkspaceForceUpdateResponseCallback);
            Monitor_communication.Instance.SetParkspace_manual_search_ResponseDelegate(ParkspaceManualSeachResponseCallback);
            Monitor_communication.Instance.SetStoring_process_statu_msgDelegate(StoringProcessStatuCallback);
            Monitor_communication.Instance.SetPicking_process_statu_msgDelegate(PickingProcessStatuCallback);
            // 库位显示
            m_update_display_thread = new Thread(new ThreadStart(UpdateParkingSpaceView));
            m_update_display_thread.Start();
        }
        public void Uninit()
        {
            if(!s_isClosing)
                Monitor_communication.Instance.monitor_communication_uninit();
            s_isClosing = true;
            if (m_update_display_thread != null)
            {
                m_update_display_thread.Abort();
            }
        }

        /// <summary>
        /// 接收到强制更新车位反馈消息回调
        /// </summary>
        /// <param name="response"></param>
        void ParkspaceForceUpdateResponseCallback(Parkspace_force_update_response_msg response)
        {
            lock (s_parkspace_force_update_queue_lock)
            {
                if (m_parkspace_force_update_response_queue != null)
                {
                    m_parkspace_force_update_response_queue.Enqueue(response);
                }
            }
        }
        /// <summary>
        /// 手动查询车位反馈
        /// </summary>
        /// <param name="parkspace_Manual_Search_Response_Msg"></param>
        private void ParkspaceManualSeachResponseCallback(Parkspace_manual_search_response_msg parkspace_Manual_Search_Response_Msg)
        {
            lock (s_parkspace_force_update_queue_lock)
            {
                if (parkspace_Manual_Search_Response_Msg != null)
                {
                    //  MessageBox.Show(parkspace_Manual_Search_Response_Msg.ToString());
                    //查看反馈结果
                    if (parkspace_Manual_Search_Response_Msg.ErrorManager.ErrorCode == 0)
                    {
                        if (this.InvokeRequired)
                        {
                            this.Invoke(new Action(() =>
                            {
                                commendkeyBox.Text = parkspace_Manual_Search_Response_Msg.QueryParkspaceInfoEx[0].CarInfo.License;
                            }));
                        }
                        else
                        {
                            commendkeyBox.Text = parkspace_Manual_Search_Response_Msg.QueryParkspaceInfoEx[0].CarInfo.License;
                        }
                        m_unitid = parkspace_Manual_Search_Response_Msg.QueryParkspaceInfoEx[0].ParkingspaceUnitId;
                    }
                    else
                    {
                        MessageBox.Show(parkspace_Manual_Search_Response_Msg.ErrorManager.ToString());
                    }

                }
            }
        }


        /// <summary>
        /// 接收到停车流程进度
        /// </summary>
        /// <param name="msg"></param>
        void StoringProcessStatuCallback(Storing_process_statu_msg msg)
        {
            Console.WriteLine(msg.ToString());
            UIMessageData.CommandInfo commandInfo = new UIMessageData.CommandInfo();

            string[] Steps_alloc = new string[] { "开始", "分配车位" };
            string[] Steps_dispatch = new string[] { "开始", "分配车位", "搬运" };
            string[] Steps_confirm = new string[] { "开始", "分配车位", "搬运", "确认车位" };

            string[] Steps = new string[] { "开始", "分配车位", "搬运", "确认车位", "完成" };

            string[] Backsteps_alloc = new string[] { "清除", "异常结束" };
            string[] Backsteps_dispatch = new string[] { "PLC复位", "清除", "异常结束" };
            string[] Backsteps_confirm = new string[] { "取消车位", "PLC复位", "清除", "异常结束" };

            string[] Backsteps = new string[] { };
            int StepIndex = -1;

            //分配车位
            if (msg.AllocSpaceStep?.StepStatu == Step_statu.EWorking)
            {
                StepIndex = 2;
            }
            //调度
            else if (msg.DispatchStep?.StepStatu == Step_statu.EWorking)
            {
                StepIndex = 3;
            }
            //确认车位
            else if (msg.ConfirmSpaceStep?.StepStatu == Step_statu.EWorking)
            {
                StepIndex = 4;
            }
            //完成
            if (msg.Completed)
            {
                StepIndex = 5;
            }

            //确认车位回退
            if (msg.BackConfirmStep?.StepStatu == Step_statu.EWorking)
            {
                Steps = Steps_confirm;
                Backsteps = Backsteps_confirm;
                StepIndex = 5;
            }
            //调度回退   两种情况  1.是从确认车位回退的 2.是从调度步骤开始回退  
            if (msg.BackDispatchStep?.StepStatu == Step_statu.EWorking)
            {
                //1.从确认车位回退
                if (msg.BackConfirmStep?.StepStatu == Step_statu.EFinished)
                {
                    Steps = Steps_confirm;
                    Backsteps = Backsteps_confirm;
                    StepIndex = 6;
                }
                else
                {
                    //2.其他状态说明是从调度开始回退
                    Steps = Steps_dispatch;
                    Backsteps = Backsteps_dispatch;
                    StepIndex = 4;
                }
            }
            //分配车位回退 三种情况 1.确认车位步骤开始回退  2.调度步骤开始回退 3.分配步骤开始回退
            if (msg.BackAllocSpaceStep?.StepStatu == Step_statu.EWorking)
            {
                //若调度和确认回退都未处于完成状态 则是从分配步骤开始回退
                if (msg.BackConfirmStep?.StepStatu != Step_statu.EFinished &&
                    msg.BackDispatchStep?.StepStatu != Step_statu.EFinished)
                {
                    Steps = Steps_alloc;
                    Backsteps = Backsteps_alloc;
                    StepIndex = 3;
                }
                //若是从确认开始回退
                else if (msg.BackConfirmStep?.StepStatu == Step_statu.EFinished &&
                    msg.BackDispatchStep?.StepStatu == Step_statu.EFinished)
                {
                    Steps = Steps_confirm;
                    Backsteps = Backsteps_confirm;
                    //不是从本身开始回退只需要自加
                    StepIndex = 7;
                }
                //若是从调度开始回退
                else if (msg.BackConfirmStep?.StepStatu != Step_statu.EFinished &&
                    msg.BackDispatchStep?.StepStatu == Step_statu.EFinished)
                {
                    Steps = Steps_dispatch;
                    Backsteps = Backsteps_dispatch;
                    //不是从本身开始回退只需要自加
                    StepIndex = 5;
                }
            }
            //异常结束
            if (msg.BackCompleted)
            {
                if (msg.BackAllocSpaceStep?.StepStatu == Step_statu.EFinished)
                {
                    Steps = Steps_alloc;
                    Backsteps = Backsteps_alloc;
                    StepIndex = 4;
                }
                if (msg.BackDispatchStep?.StepStatu == Step_statu.EFinished)
                {
                    Steps = Steps_dispatch;
                    Backsteps = Backsteps_dispatch;
                    StepIndex = 6;
                }
                if (msg.BackConfirmStep?.StepStatu == Step_statu.EFinished)
                {
                    Steps = Steps_confirm;
                    Backsteps = Backsteps_confirm;
                    StepIndex = 8;
                }
            }
            //赋值
            commandInfo.Steps = Steps;
            commandInfo.BackSteps = Backsteps;
            commandInfo.StepIndex = StepIndex;

            string input_key = "";

            switch (msg.IdStruct.TerminalId)
            {
                case 0:
                    {
                        input_key = "input_A1" + "-" + msg.License;
                    }
                    break;
                case 1:
                    {
                        input_key = "input_A2" + "-" + msg.License;
                    }
                    break;
                case 2:
                    {
                        input_key = "input_B1" + "-" + msg.License;
                    }
                    break;
                case 3:
                    {
                        input_key = "input_B2" + "-" + msg.License;
                    }
                    break;
                case 4:
                    {
                        input_key = "input_C1" + "-" + msg.License;
                    }
                    break;
                case 5:
                    {
                        input_key = "input_C2" + "-" + msg.License;
                    }
                    break;
                default:
                    break;
            }
            TimedData<UIMessageData.CommandInfo> timedData = new TimedData<UIMessageData.CommandInfo>(commandInfo);
            UIMessageData.Instance.CommandMap.AddOrUpdate(input_key, timedData, (key, value) => timedData);
        }
        /// <summary>
        /// 接收到取车流程进度
        /// </summary>
        /// <param name="msg"></param>
        void PickingProcessStatuCallback(Picking_process_statu_msg msg)
        {
            Console.WriteLine(msg.ToString());
            UIMessageData.CommandInfo commandInfo = new UIMessageData.CommandInfo();

            string[] Steps_search = new string[] { "开始", "查询车位" };
            string[] Steps_dispatch = new string[] { "开始", "查询车位", "搬运" };
            string[] Steps_release = new string[] { "开始", "查询车位", "搬运", "释放车位" };
            string[] Steps_waitfor = new string[] { "开始", "查询车位", "搬运", "释放车位", "等待离开" };


            string[] Steps = new string[] { "开始", "查询车位", "搬运", "释放车位", "等待离开", "完成" };

            string[] Backsteps_search = new string[] { "清除", "异常结束" };
            string[] Backsteps_dispatch = new string[] { "PLC复位", "清除", "异常结束" };
            string[] Backsteps_waitfor = new string[] { "取消等待", "PLC复位", "清除", "异常结束" };

            string[] Backsteps = new string[] { };
            int StepIndex = -1;
            //查询
            if (msg.SearchSpaceStep?.StepStatu == Step_statu.EWorking)
            {
                StepIndex = 2;
            }
            //调度
            else if (msg.DispatchStep?.StepStatu == Step_statu.EWorking)
            {
                StepIndex = 3;
            }
            //释放
            else if (msg.ReleaseSpaceStep?.StepStatu == Step_statu.EWorking)
            {
                StepIndex = 4;
            }
            //等待离开
            else if (msg.WaitforLeaveStep?.StepStatu == Step_statu.EWorking)
            {
                StepIndex = 5;
            }
            //完成
            if (msg.Completed)
            {
                StepIndex = 6;
            }
            //等待车辆离开回退
            if (msg.BackWaitforLeaveStep?.StepStatu == Step_statu.EWorking)
            {
                Steps = Steps_waitfor;
                Backsteps = Backsteps_waitfor;
                StepIndex = 6;
            }
            //调度回退   两种情况  1.是从确认车位回退的 2.是从调度步骤开始回退  
            if (msg.BackDispatchStep?.StepStatu == Step_statu.EWorking)
            {
                //1.从确认车位回退
                if (msg.BackWaitforLeaveStep?.StepStatu == Step_statu.EFinished)
                {
                    Steps = Steps_waitfor;
                    Backsteps = Backsteps_waitfor;
                    StepIndex = 7;
                }
                else
                {
                    //2.其他状态说明是从调度开始回退
                    Steps = Steps_dispatch;
                    Backsteps = Backsteps_dispatch;
                    StepIndex = 4;
                }
            }
            //查询车位回退 三种情况 1.等待车辆步骤开始回退  2.调度步骤开始回退 
            if (msg.BackSearchSpaceStepStatu?.StepStatu == Step_statu.EWorking)
            {
                //调度和确认回退都未处于完成状态 则是从分配步骤开始回退
                if (msg.BackWaitforLeaveStep?.StepStatu != Step_statu.EFinished &&
                    msg.BackDispatchStep?.StepStatu != Step_statu.EFinished)
                {
                    Steps = Steps_search;
                    Backsteps = Backsteps_search;
                    StepIndex = 3;
                }
                //从等待开始回退
                else if (msg.BackWaitforLeaveStep?.StepStatu == Step_statu.EFinished &&
                    msg.BackDispatchStep?.StepStatu == Step_statu.EFinished)
                {
                    Steps = Steps_waitfor;
                    Backsteps = Backsteps_waitfor;
                    StepIndex = 8;
                }
                //从调度开始回退
                else if (msg.BackWaitforLeaveStep?.StepStatu != Step_statu.EFinished &&
                    msg.BackDispatchStep?.StepStatu == Step_statu.EFinished)
                {
                    Steps = Steps_dispatch;
                    Backsteps = Backsteps_dispatch;
                    StepIndex = 5;
                }
            }
            //异常结束
            if (msg.BackCompleted)
            {
                if (msg.BackSearchSpaceStepStatu?.StepStatu == Step_statu.EFinished)
                {
                    Steps = Steps_search;
                    Backsteps = Backsteps_search;
                    StepIndex = 4;
                }
                if (msg.BackDispatchStep?.StepStatu == Step_statu.EFinished)
                {
                    Steps = Steps_dispatch;
                    Backsteps = Backsteps_dispatch;
                    StepIndex = 6;
                }
                if (msg.BackWaitforLeaveStep?.StepStatu == Step_statu.EFinished)
                {
                    Steps = Steps_waitfor;
                    Backsteps = Backsteps_waitfor;
                    StepIndex = 9;
                }
            }
            //赋值
            commandInfo.Steps = Steps;
            commandInfo.BackSteps = Backsteps;
            commandInfo.StepIndex = StepIndex;

            string output_key = "";

            switch (msg.IdStruct.TerminalId)
            {
                case 0:
                    {
                        output_key = "output_A1" + "-" + msg.License;
                    }
                    break;
                case 1:
                    {
                        output_key = "output_A2" + "-" + msg.License;
                    }
                    break;
                case 2:
                    {
                        output_key = "output_B1" + "-" + msg.License;
                    }
                    break;
                case 3:
                    {
                        output_key = "output_B2" + "-" + msg.License;
                    }
                    break;
                case 4:
                    {
                        output_key = "output_C1" + "-" + msg.License;
                    }
                    break;
                case 5:
                    {
                        output_key = "output_C2" + "-" + msg.License;
                    }
                    break;
                default:
                    break;
            }
            TimedData<UIMessageData.CommandInfo> timedData = new TimedData<UIMessageData.CommandInfo>(commandInfo);
            UIMessageData.Instance.CommandMap.AddOrUpdate(output_key, timedData, (key, value) => timedData);
        }

        /// <summary>
        /// 更新立体停车位显示
        /// </summary>
        private void UpdateParkingSpaceView()
        {
            while (!s_isClosing)
            {


                bool needUpdate = false;
                List<Parkspace_info> psList = null;
                Thread.Sleep(1000);
                bool get_status_result = Monitor_communication.Instance.Get_parkspace_status(ref m_parkspace_status);
              //  bool connect_status = Communicator.Instance.Get_connect_status();
                if (!Monitor_communication.Instance.check_connect())
                {
                    MessageBox.Show("数据库未连接，重新连接中！");
                }
                lock (s_parkspace_status_lock)
                {
                    if (get_status_result && (m_parkspace_status == null || m_parkspace_status.ParkspaceInfoEx == null))
                    {
                        get_status_result = false;
                    }
                }
                if (!get_status_result)
                {
                    lock (s_map_update_lock)
                    {
                        m_idPssMap.Clear();
                    }
                    continue;
                }
                else
                {
                    lock (s_parkspace_status_lock)
                    {
                        psList = m_parkspace_status.ParkspaceInfoEx.ToList();
                    }
                }
                if (psList == null || psList.Count <= 0)
                {
                    Thread.Sleep(1000);
                    continue;
                }
                //更新映射表
                try
                {
                    lock (s_map_update_lock)
                    {
                        if (m_idPssMap.Count != psList.Count)
                        {
                            m_idPssMap.Clear();
                            for (int i = 0; i < psList.Count; i++)
                            {
                                m_idPssMap.Add(psList[i].ParkingspaceIndexId, psList[i]);
                            }
                        }
                        else
                        {
                            for (int i = 0; i < psList.Count; i++)
                            {
                                m_idPssMap[psList[i].ParkingspaceIndexId] = psList[i];
                            }
                        }
                    }
                }
                catch (Exception e) { Console.WriteLine(e.StackTrace); /*Log.WriteLog(LogType.process, LogFile.WARNING, "实时更新所有库位异常");*/ }
                Action action = () =>
                {
                    List<Parkspace_info> psList_unit_0 = new List<Parkspace_info>();
                    List<Parkspace_info> psList_unit_1 = new List<Parkspace_info>();
                    List<Parkspace_info> psList_unit_2 = new List<Parkspace_info>();

                    for (int i=0; i<psList.Count();++i )
                    {
                        if (psList[i].ParkingspaceUnitId == 0)
                        {
                            psList_unit_0.Add(psList[i]);
                        }
                        if (psList[i].ParkingspaceUnitId == 1)
                        {
                            psList_unit_1.Add(psList[i]);
                        }
                        if (psList[i].ParkingspaceUnitId == 2)
                        {
                            psList_unit_2.Add(psList[i]);
                        }
                    }

                    int blockSize = s_spacesInRow * s_floors * s_rows;
                    int offset = (s_rows + 1 - ((blockSize / s_spacesInRow) % s_rows)) * s_spacesInRow;
                    int max_floor = 14;
                    //创建控件
                    if (ParkingSpaceMonitorPanel != null && ParkingSpaceMonitorPanel.Controls.Count == 0 || needUpdate)
                    {
                        TableLayoutPanel tlp = new TableLayoutPanel();
                        tlp.Name = "tlp_ParkingSpace";
                        tlp.ColumnCount = s_rows;
                        tlp.RowCount = 1;
                        tlp.Dock = DockStyle.Fill;
                        tlp.AutoScroll = true;
                        tlp.BackColor = SystemColors.GradientActiveCaption;

                        // 之前s_rows存在问题，默认为1，s_spacesInRow*s_floors构成矩形长宽
                        for (int i = 0; i < s_rows; i++)
                        {
                            TableLayoutPanel temp = new TableLayoutPanel();
                            temp.Name = "tlp_ParkingSpaceSection" + (i + 1).ToString();
                            temp.RowCount = s_floors;
                            temp.ColumnCount = s_spacesInRow;
                            temp.Dock = DockStyle.Fill;
                            temp.AutoSize = true;
                            temp.BackColor = SystemColors.GradientActiveCaption;
                            temp.Margin = new Padding(5, 2, 5, 2);
                             
                            for (int floor = max_floor; floor >= 0 ;floor--)
                            {
                                int num1 = 0;
                                int num2 = 0;
                                int num3 = 0;

                                for (int j = psList_unit_0.Count() - 1 ; j >= 0; j--)
                                {
                                    if (psList_unit_0[j].ParkingspaceFloorId == floor)
                                    {
                                        Button btn = new Button();
                                        btn.Anchor = (AnchorStyles.Left | AnchorStyles.Top);
                                        btn.AutoSize = true;
                                        btn.Location = new Point(5, 5);
                                        btn.Margin = new Padding(1, 2, 1, 2);
                                        btn.Padding = new Padding(5);
                                        btn.Name = "lb_parkingSpace" + j;
                                        btn.TextAlign = ContentAlignment.MiddleCenter;
                                        btn.MouseDown += new MouseEventHandler(Btnvalue_Click);
                                        btn.MouseHover += new EventHandler(Btnvalue_Mouse_Hover);

                                        if (((j % 18) % 6) == 5)
                                        {
                                            btn.Margin = new Padding(120, 2, 5, 2);
                                        }
                                        int index = j - j % 6 + num1;
                                        num1++;
                                        btn.Text = "A库位:" + psList_unit_0[index].ParkingspaceLabelId + "\n\n楼层:" + psList_unit_0[index].ParkingspaceFloorId;
                                        btn.BackColor = GetPSColor(psList_unit_0[index].ParkingspaceStatus);
                                        temp.Controls.Add(btn);
                                    }
                                }
                                for (int j = psList_unit_1.Count() - 1; j >= 0; j--)
                                {
                                    if (psList_unit_1[j].ParkingspaceFloorId == floor)
                                    {
                                        Button btn = new Button();
                                        btn.Anchor = (AnchorStyles.Right | AnchorStyles.Top);
                                        btn.AutoSize = true;
                                        btn.Location = new Point(5, 5);
                                        btn.Margin = new Padding(1, 2, 1, 2);
                                        btn.Padding = new Padding(5);
                                        btn.Name = "lb_parkingSpace" + j;
                                        btn.TextAlign = ContentAlignment.MiddleCenter;
                                        btn.MouseDown += new MouseEventHandler(Btnvalue_Click);
                                        btn.MouseHover += new EventHandler(Btnvalue_Mouse_Hover);

                                        if (((j % 18) % 6) == 5)
                                        {
                                            btn.Margin = new Padding(120, 2, 5, 2);
                                        }
                                        int index = j - j % 6 + num2;
                                        num2++;
                                        btn.Text = "B库位:" + psList_unit_1[index].ParkingspaceLabelId + "\n\n楼层:" + psList_unit_1[index].ParkingspaceFloorId;
                                        btn.BackColor = GetPSColor(psList_unit_1[index].ParkingspaceStatus);
                                        temp.Controls.Add(btn);
                                    }
                                }
                                for (int j = psList_unit_2.Count() - 1; j >= 0; j--)
                                {
                                    if (psList_unit_2[j].ParkingspaceFloorId == floor)
                                    {
                                        Button btn = new Button();
                                        btn.Anchor = (AnchorStyles.Left | AnchorStyles.Top);
                                        btn.AutoSize = true;
                                        btn.Location = new Point(5, 5);
                                        btn.Margin = new Padding(1, 2, 1, 2);
                                        btn.Padding = new Padding(5);
                                        btn.Name = "lb_parkingSpace" + j;
                                        btn.TextAlign = ContentAlignment.MiddleCenter;
                                        btn.MouseDown += new MouseEventHandler(Btnvalue_Click);
                                        btn.MouseHover += new EventHandler(Btnvalue_Mouse_Hover);

                                        if (((j % 18) % 6) == 5)
                                        {
                                            btn.Margin = new Padding(120, 2, 5, 2);
                                        }
                                        int index = j - j % 6 + num3;
                                        num3++;
                                        btn.Text = "C库位:" + psList_unit_2[index].ParkingspaceLabelId + "\n\n楼层:" + psList_unit_2[index].ParkingspaceFloorId;
                                        btn.BackColor = GetPSColor(psList_unit_2[index].ParkingspaceStatus);
                                        temp.Controls.Add(btn);
                                    }
                                }
                            }
                            tlp.Controls.Add(temp);
                            //tlpList.Add(temp);
                        }
                        ParkingSpaceMonitorPanel.Controls.Clear();
                        ParkingSpaceMonitorPanel.Controls.Add(tlp);
                        needUpdate = false;
                    }
                    //更新控件
                    else
                    {                        Control.ControlCollection psCC = ParkingSpaceMonitorPanel.Controls;
                        foreach (Control segment in psCC)
                        {
                            Control.ControlCollection segmentCC = segment.Controls;
                            //Console.WriteLine("seg::"+segmentCC.Count);
                            foreach (Control spaces in segmentCC)
                            {
                                Control.ControlCollection spaceCC = spaces.Controls;
                                //Console.WriteLine("spaces::"+spaceCC.Count);
                                foreach (Control space in spaceCC)
                                {
                                    if (space.GetType() == typeof(Button))
                                    {
                                        int index = -1;
                                        bool result = int.TryParse(System.Text.RegularExpressions.Regex.Match(space.Text, @"\d+(\.\d+)?").Value, out index);
                                        string unit = space.Text.Substring(0,1);
                                        byte[] array = System.Text.Encoding.ASCII.GetBytes(unit);
                                        int asciicode = (int)(array[0]);
                                        index = (asciicode - 'A')*78 +index;
                                        
                                        lock (s_map_update_lock)
                                        {
                                            //Console.WriteLine("text is :" + space.Text+", index:"+index);
                                            if (m_idPssMap.ContainsKey(index))
                                            {
                                                //Console.WriteLine("index:" + index+", status:"+ idPssMap[index].spaceStatus);
                                                space.BackColor = GetPSColor(m_idPssMap[index].ParkingspaceStatus);
                                            }
                                            else if (result)
                                            {
                                                needUpdate = true;
                                                //Console.WriteLine("need update:"+index);
                                                break;
                                            }
                                        }
                                    }
                                }

                            }
                            if (needUpdate)
                            {
                                break;
                            }
                        }
                    }
                };
                if (this != null && this.IsHandleCreated)
                {
                    this.Invoke(action);
                }

            }
        }

        /// <summary>
        /// 按钮点击事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Btnvalue_Click(object sender, MouseEventArgs e)
        {
            if (e.Button != MouseButtons.Right)
                return;
            Button btn = (Button)sender;
            //实例化窗口，选择待修改状态
            FormStatusSelect formStatusSelect = new FormStatusSelect(btn);
            formStatusSelect.Location = Control.MousePosition;
            formStatusSelect.StartPosition = FormStartPosition.Manual;
            formStatusSelect.SetCallback(ForceUpdateStatusCallback);
            formStatusSelect.ShowDialog();
        }

        private void Btnvalue_Mouse_Hover(object sender, EventArgs e)
        {
            Button btn = (Button)sender;
            // 创建the ToolTip 
            ToolTip toolTip_parkspace_info = new ToolTip();

            // 设置显示样式
            toolTip_parkspace_info.AutoPopDelay = 20000;//提示信息的可见时间
            toolTip_parkspace_info.InitialDelay = 500;//事件触发多久后出现提示
            toolTip_parkspace_info.ReshowDelay = 1000;//指针从一个控件移向另一个控件时，经过多久才会显示下一个提示框
            toolTip_parkspace_info.ShowAlways = false;//是否显示提示框

            // 获取车位信息，处理后显示
            int parkspaceID = GetParkspaceIdFromButton(btn);
            Parkspace_info space_info = null;
            lock (s_parkspace_status_lock)
            {
                if (parkspaceID <= 0 || m_parkspace_status == null || m_parkspace_status.ParkspaceInfoEx == null)
                    return;
                for (int i = 0; i < m_parkspace_status.ParkspaceInfoEx.Count; i++)
                {
                    if (m_parkspace_status.ParkspaceInfoEx[i].ParkingspaceIndexId == parkspaceID)
                    {
                        space_info = m_parkspace_status.ParkspaceInfoEx[i];
                        break;
                    }
                }
            }
            if (space_info == null)
                return;
            //  设置伴随的对象
            toolTip_parkspace_info.SetToolTip(btn, space_info.ToString().Replace(",", "\n"));//设置提示按钮和提示内容
        }

        /// <summary>
        /// 定义用于发送修改请求，以及修改button状态的回调函数
        /// </summary>
        /// <param name="status"></param>
        private void ForceUpdateStatusCallback(Parkspace_status status, Button btn)
        {
            int parkspaceID = GetParkspaceIdFromButton(btn);
            lock(s_parkspace_status_lock)
            {
                if (parkspaceID <= 0 || m_parkspace_status == null || m_parkspace_status.ParkspaceInfoEx == null)
                {
                    MessageBox.Show("车位号有误！"+ parkspaceID);
                    return;
                }
            }
            SendAndReceive(status, parkspaceID);
        }

        /// <summary>
        /// 发送后接收对应反馈消息
        /// </summary>
        private void SendAndReceive(Parkspace_status status, int parkspaceID)
        {
            // 遍历强制更新反馈队列，清除对应车位已存在的反馈消息，即将非对应车位的消息放回队列
            lock (s_parkspace_force_update_queue_lock)
            {
                for (int i = 0; i < m_parkspace_force_update_response_queue.Count; i++)
                {
                    Parkspace_force_update_response_msg response = m_parkspace_force_update_response_queue.Dequeue();
                    if (response.ManualParkspaceInfoEx != null && response.ManualParkspaceInfoEx.Count > 0 && response.ManualParkspaceInfoEx[0].ParkingspaceIndexId != parkspaceID)
                    {
                        m_parkspace_force_update_response_queue.Enqueue(response);
                    }
                }
            }
            // 发送强制更新请求
            Parkspace_info space_info = null;
            lock (s_parkspace_status_lock)
            {
                //用于清除所有车位状态的特殊指令
                if (parkspaceID == 9999)
                {
                    space_info = new Parkspace_info();
                    if (m_parkspace_status.ParkspaceInfoEx.Count() > 0)
                    {
                        space_info = m_parkspace_status.ParkspaceInfoEx[0];
                    }
                    space_info.ParkingspaceIndexId = 9999;
                }
                else
                {
                    for (int i = 0; i < m_parkspace_status.ParkspaceInfoEx.Count; i++)
                    {
                        if (m_parkspace_status.ParkspaceInfoEx[i].ParkingspaceIndexId == parkspaceID)
                        {
                            space_info = m_parkspace_status.ParkspaceInfoEx[i];
                            break;
                        }
                    }
                }
            }
            DateTime startTime = DateTime.Now;
            string commandKey = startTime.ToString("yyyy-MM-dd_HH:mm:ss:ffff");
            try
            {
                space_info.ParkingspaceStatus = status;
                Parkspace_force_update_request_msg parkspace_force_update_request_msg = new Parkspace_force_update_request_msg();
                Base_info base_Info = new Base_info();
                base_Info.MsgType = Message_type.EParkspaceForceUpdateRequestMsg;
                base_Info.TimeoutMs = 2000;
                base_Info.Sender = Message.Communicator.EParkspace;
                base_Info.Receiver = Message.Communicator.EParkspace;
                parkspace_force_update_request_msg.BaseInfo = base_Info;
                parkspace_force_update_request_msg.CommandKey = commandKey;
                parkspace_force_update_request_msg.ManualParkspaceInfoEx.Add(space_info);
                //MessageBox.Show(parkspace_force_update_request_msg.ToString());
                Monitor_communication.Instance.encapsulate_msg(parkspace_force_update_request_msg.ToByteString());
            }
            catch (Exception ex) { Console.WriteLine(ex.StackTrace); }

            // 遍历强制更新反馈队列，寻找对应反馈消息
            bool get_result = false;
            while ((DateTime.Now - startTime).TotalMilliseconds < Monitor_communication.Instance.m_timeout_milli)
            {
                lock (s_parkspace_force_update_queue_lock)
                {
                    for (int i = 0; i < m_parkspace_force_update_response_queue.Count; i++)
                    {
                        Parkspace_force_update_response_msg response = m_parkspace_force_update_response_queue.Dequeue();
                        if (response.ManualParkspaceInfoEx != null && response.ManualParkspaceInfoEx.Count > 0 && response.CommandKey == commandKey && response.ManualParkspaceInfoEx[0].ParkingspaceIndexId== parkspaceID)
                        {
                            get_result = true;
                            if (response.ErrorManager != null)
                            {
                                if (response.ErrorManager.ErrorCode != 0)
                                {
                                    //btn.BackColor = GetPSColor(status);
                                    Console.WriteLine("force update failed, code: " + response.ErrorManager.ErrorCode + ", description: " + response.ErrorManager.ErrorDescription);
                                }
                            }
                            break;
                        }
                        else
                        {
                            m_parkspace_force_update_response_queue.Enqueue(response);
                        }
                    }
                }
                if (get_result)
                    break;
                Thread.Sleep(50);
            }
            if (!get_result && space_info != null)
            {

                MessageBox.Show("force update get response timeout: " + space_info.ToString());
            }
        }

        /// <summary>
        /// 通过按钮信息截取车位id，失败返回-1
        /// </summary>
        /// <param name="btn"></param>
        /// <returns></returns>
        private int GetParkspaceIdFromButton(Button btn)
        {
            if (btn == null || btn.Text.Length < 3)
                return -1;
            int parkspaceID = -1;
            bool parse_result = int.TryParse(System.Text.RegularExpressions.Regex.Match(btn.Text, @"\d+(\.\d+)?").Value, out parkspaceID);
            string unit = btn.Text.Substring(0, 1);
            byte[] array = System.Text.Encoding.ASCII.GetBytes(unit);
            int asciicode = (int)(array[0]);
            parkspaceID = (asciicode - 'A') * 78 + parkspaceID;
            Console.WriteLine(parkspaceID.ToString());
            if (parse_result)
            {

                return parkspaceID;
            }
            else
            {
                return -1;
            }
        }

        /// <summary>
        /// 获取状态对应颜色
        /// </summary>
        /// <param name="status"></param>
        /// <returns></returns>
        private Color GetPSColor(Parkspace_status status)
        {
            switch (status)
            {
                case Parkspace_status.EParkspaceEmpty: return Color.White;
                case Parkspace_status.EParkspaceOccupied: return Color.Yellow;
                case Parkspace_status.EParkspaceReserved: return Color.SkyBlue;
                case Parkspace_status.EParkspaceLocked: return Color.LightGreen;
                case Parkspace_status.EParkspaceError: return Color.Red;
                default: return Color.Violet;
            }
        }

        private void MonitorMainWindows_FormClosing(object sender, FormClosingEventArgs e)
        {
            Uninit();
            e.Cancel = true;
            this.Visible = false;

        }

        private void MonitorMainWindows_FormClosed(object sender, FormClosedEventArgs e)
        {
            try
            {
                if (m_update_display_thread != null)
                {
                    m_update_display_thread.Abort();
                }
            }
            catch { Console.WriteLine("线程退出"); }
            //s_isClosing = true;
            ////if (m_update_display_thread != null)
            ////{
            ////    m_update_display_thread.Join();
            ////}
            //Communicator.Instance.Uninit();
        }

        /// <summary>
        /// 一键清除所有号牌，车位全部设置空闲，调试用
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btn_clear_Click(object sender, EventArgs e)
        {
            SendAndReceive(Parkspace_status.EParkspaceEmpty, 9999);
        }

        private void MonitorMainWindows_Load(object sender, EventArgs e)
        {
            timer.Enabled = true;
            timer.Interval = 500;
            timer.Tick += Timer_Tick;
        }

        private void button_find_Click(object sender, EventArgs e)
        {
            string license = licenseBox.Text;
            try
            {

                Message.Parkspace_manual_search_request_msg parkspace_Manual_Search_Request_Msg = new Parkspace_manual_search_request_msg();
                Message.Base_info base_Info = new Base_info();
                base_Info.MsgType = Message_type.EParkspaceManualSearchRequestMsg;
                base_Info.Sender = Message.Communicator.EEmpty;
                base_Info.Receiver = Message.Communicator.EParkspace;
                base_Info.TimeoutMs = 1000;
                Message.Car_info car_Info = new Car_info();
                car_Info.CarNumberPlate = license;
                parkspace_Manual_Search_Request_Msg.BaseInfo = base_Info;
                parkspace_Manual_Search_Request_Msg.CarInfo = car_Info;
                parkspace_Manual_Search_Request_Msg.CommandKey = DateTime.Now.ToString("yyyyMMddHHmmssfff");
                DateTime dateTime = DateTime.Now;
                Monitor_communication.Instance.encapsulate_msg(parkspace_Manual_Search_Request_Msg.ToByteString());

            }
            catch (Exception ex) { Console.WriteLine(ex.StackTrace); }
        }

        private void button_pickupcar_Click(object sender, EventArgs e)
        {
            try
            {
                //取车请求
                Message.Pickup_command_request_msg t_pickup_command_request_msg = new Message.Pickup_command_request_msg();
                //消息头
                Message.Base_info baseInfo = new Message.Base_info();
                baseInfo.MsgType = Message.Message_type.EPickupCommandRequestMsg;
                baseInfo.Sender = Message.Communicator.ETerminor;
                baseInfo.Receiver = Message.Communicator.EMain;

                //车辆信息--只需填充车牌号
                Message.Car_info car_Info = new Message.Car_info();
                car_Info.License = commendkeyBox.Text;
                car_Info.CarNumberPlate = licenseBox.Text;

                //填充信息
                t_pickup_command_request_msg.BaseInfo = baseInfo;
                t_pickup_command_request_msg.IdStruct = new Id_struct();
                if (m_unitid != -1)
                {
                    t_pickup_command_request_msg.IdStruct.UnitId = m_unitid;
                    t_pickup_command_request_msg.CarInfo = car_Info;
                    //发送取车请求
                    Monitor_communication.Instance.encapsulate_msg(t_pickup_command_request_msg.ToByteString());
                    MessageBox.Show("取车指令已发送!" + t_pickup_command_request_msg.ToString());
                }
                else
                {
                    MessageBox.Show("单元号错误，请重新查询!" );
                }
                m_unitid = -1;
            }
            catch (Exception ex) { Console.WriteLine(ex.StackTrace); }
        }
        private void Timer_Tick(object sender, EventArgs e)
        {
            led_A_plc.Statu = UIMessageData.Instance.PLCStatuA.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.PLCStatuA.Value;
            led_B_plc.Statu = UIMessageData.Instance.PLCStatuB.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.PLCStatuB.Value;
            led_C_plc.Statu = UIMessageData.Instance.PLCStatuC.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.PLCStatuC.Value;

            led_A1_terminal.Statu = UIMessageData.Instance.TerminalStatuA1.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.TerminalStatuA1.Value;
            led_A2_terminal.Statu = UIMessageData.Instance.TerminalStatuA2.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.TerminalStatuA2.Value;
            led_B1_terminal.Statu = UIMessageData.Instance.TerminalStatuB1.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.TerminalStatuB1.Value;
            led_B2_terminal.Statu = UIMessageData.Instance.TerminalStatuB2.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.TerminalStatuB2.Value;
            led_C1_terminal.Statu = UIMessageData.Instance.TerminalStatuC1.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.TerminalStatuC1.Value;
            led_C2_terminal.Statu = UIMessageData.Instance.TerminalStatuC2.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.TerminalStatuC2.Value;

            led_A1_lidar.Statu = UIMessageData.Instance.LidarStatuA1.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.LidarStatuA1.Value;
            led_A2_lidar.Statu = UIMessageData.Instance.LidarStatuA2.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.LidarStatuA2.Value;
            led_B1_lidar.Statu = UIMessageData.Instance.LidarStatuB1.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.LidarStatuB1.Value;
            led_B2_lidar.Statu = UIMessageData.Instance.LidarStatuB2.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.LidarStatuB2.Value;
            led_C1_lidar.Statu = UIMessageData.Instance.LidarStatuC1.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.LidarStatuC1.Value;
            led_C2_lidar.Statu = UIMessageData.Instance.LidarStatuC2.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.LidarStatuC2.Value;

            led_main.Statu = UIMessageData.Instance.MainNodeStatu.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.MainNodeStatu.Value;
            led_database.Statu = UIMessageData.Instance.DatabaseNodeStatu.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.DatabaseNodeStatu.Value;
            led_out_terminal1.Statu = UIMessageData.Instance.OutputTerminal1Statu.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.OutputTerminal1Statu.Value;
            led_out_terminal2.Statu = UIMessageData.Instance.OutputTerminal2Statu.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.OutputTerminal2Statu.Value;
            led_out_unnormal.Statu = UIMessageData.Instance.OutputUnnormalNodeStatu.IsTimeout() ?  LED.LED_Statu.Disconnected :
                ( LED.LED_Statu)UIMessageData.Instance.OutputUnnormalNodeStatu.Value;
            UpdataCommand();
        }

        public void UpdataCommand()
        {

            foreach (var item in UIMessageData.Instance.CommandMap)
            {
                if (item.Value.IsTimeout())
                {
                    //指令已经结束,删除控件
                    if (m_step_map.ContainsKey(item.Key))
                    {
                        StepControl control = new StepControl();
                        m_step_map.TryRemove(item.Key, out control);
                        control.Dispose();
                    }
                    //删除指令数据
                    TimedData<UIMessageData.CommandInfo> Cmd =
                        new TimedData<UIMessageData.CommandInfo>(new UIMessageData.CommandInfo());
                    if (UIMessageData.Instance.CommandMap.TryRemove(item.Key, out Cmd) == false)
                    {
                        Console.WriteLine(" remove error");
                    }
                }
                else if (m_step_map.ContainsKey(item.Key))
                {
                    //存在对应的控件， 直接更新
                    StepControl control = m_step_map[item.Key];
                    UIMessageData.CommandInfo command_info = item.Value.Value;
                    control.Steps = command_info.Steps;
                    control.BackSteps = command_info.BackSteps;
                    control.StepIndex = command_info.StepIndex;
                }
                else
                {
                    //控件不存在，创建
                    UIMessageData.CommandInfo command_info = item.Value.Value;
                    StepControl control = new StepControl();
                    control.Steps = command_info.Steps;
                    control.BackSteps = command_info.BackSteps;
                    control.StepIndex = command_info.StepIndex;
                    control.Dock = DockStyle.Top;

                    //截取控件所在位置及车牌号
                    string[] labels = item.Key.Split('-'); //入口 标签格式 input_A1-车牌号,出口output_A1-车牌号
                    if (labels.Length != 2)
                    {
                        //key格式错误
                        continue;
                    }
                    control.Label = labels[1];
                    string location = labels[0];//位置
                                                //入口
                    if (location == "input_A1")
                        panel_input_A1.Controls.Add(control);
                    if (location == "input_A2")
                        panel_input_A2.Controls.Add(control);
                    if (location == "input_B1")
                        panel_input_B1.Controls.Add(control);
                    if (location == "input_B2")
                        panel_input_B2.Controls.Add(control);
                    if (location == "input_C1")
                        panel_input_C1.Controls.Add(control);
                    if (location == "input_C2")
                        panel_input_C2.Controls.Add(control);
                    //出口
                    if (location == "output_A1")
                        panel_output_A1.Controls.Add(control);
                    if (location == "output_A2")
                        panel_output_A2.Controls.Add(control);
                    if (location == "output_B1")
                        panel_output_B1.Controls.Add(control);
                    if (location == "output_B2")
                        panel_output_B2.Controls.Add(control);
                    if (location == "output_C1")
                        panel_output_C1.Controls.Add(control);
                    if (location == "output_C2")
                        panel_output_C2.Controls.Add(control);
                    m_step_map[item.Key] = control;
                }
            }
        }

        private void init_btn_Click(object sender, EventArgs e)
        {
            Uninit();
            Init();
        }
    }
}
