using NNanomsg;
using NNanomsg.Protocols;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Google.Protobuf;
using Message;
using tool;
using Newtonsoft.Json.Linq;
using System.Runtime.InteropServices;
using communication_base;

namespace monitor_main_windows
{
    class Monitor_communication : communication_base.Communication_socket_base
    {
        //由于C#不能多继承 就只能直接写成单例模式了
        /// <summary>
        /// 单例
        /// </summary>
        class Nested
        {
            // 创建模板类实例，参数2设为true表示支持私有构造函数
            internal static readonly Monitor_communication instance = Activator.CreateInstance(typeof(Monitor_communication), true) as Monitor_communication;
        }
        private static Monitor_communication instance = null;
        public static Monitor_communication Instance
        {
            get
            {
                return Nested.instance;
            }
        }

        // 各类消息委托，收到对应消息即调用对应委托/回调
        public delegate void parkspaceStatusDelegate(Parkspace_allocation_data_msg parkspace_status);
        public delegate void parkspaceForceUpdateResponseDelegate(Parkspace_force_update_response_msg response);
        public delegate void parkspace_manual_search_ResponseDelegate(Parkspace_manual_search_response_msg response);


        //停车流程进度消息
        public delegate void storing_process_statu_msgDelegate(Storing_process_statu_msg response);
        //取车流程进度消息
        public delegate void picking_process_statu_msgDelegate(Picking_process_statu_msg response);

        // 对应委托/回调句柄
        private parkspaceStatusDelegate m_parkspaceStatusCallback;
        private parkspaceForceUpdateResponseDelegate m_parkspaceForceUpdateResponseCallback;
        private parkspace_manual_search_ResponseDelegate m_parkspacemanual_search_Callback;


        private storing_process_statu_msgDelegate m_storing_process_statu_Callback;
        private picking_process_statu_msgDelegate m_picking_process_statu_Callback;

        // 对应委托/回调句柄设置函数
        public void SetParkspaceStatusDelegate(parkspaceStatusDelegate callback)
        {
            m_parkspaceStatusCallback = callback;
        }
        public void SetParkspaceForceUpdateResponseDelegate(parkspaceForceUpdateResponseDelegate callback)
        {
            m_parkspaceForceUpdateResponseCallback = callback;
        }
        public void SetParkspace_manual_search_ResponseDelegate(parkspace_manual_search_ResponseDelegate callback)
        {
            m_parkspacemanual_search_Callback = callback;
        }
        public void SetStoring_process_statu_msgDelegate(storing_process_statu_msgDelegate callback)
        {
            m_storing_process_statu_Callback = callback;
        }
        public void SetPicking_process_statu_msgDelegate(picking_process_statu_msgDelegate callback)
        {
            m_picking_process_statu_Callback = callback;
        }

        private Monitor_communication()
        {
            m_parkspace_status_access_lock = new object();
            // 设置车位状态回调
            SetParkspaceStatusDelegate(ParkspaceStatusUpdate);
        }

        /// <summary>
        /// 初始化
        /// </summary>
        /// <returns></returns>
        public void monitor_communication_init()
        {
            base.communication_init();
        }
        /// <summary>
        /// 反初始化
        /// </summary>
        /// <returns></returns>
        public void monitor_communication_uninit()
        {
            base.communication_uninit();
        }

        /// <summary>
        /// 车位更新回调内部定义
        /// </summary>
        /// <param name="parkspace_status"></param>
        private void ParkspaceStatusUpdate(Parkspace_allocation_data_msg parkspace_status)
        {
            lock (m_parkspace_status_access_lock)
            {
                m_parkspace_data_msg = parkspace_status;
                //comm.m_parkspace_current_status.MergeFrom(parkspace_status);
                m_last_parkspace_status_time = DateTime.Now;
            }
        }
        /// <summary>
        /// 获取当前车位状态
        /// </summary>
        public bool Get_parkspace_status(ref Parkspace_allocation_data_msg msg)
        {
            lock (m_parkspace_status_access_lock)
            {
                msg = new Parkspace_allocation_data_msg();
                msg.MergeFrom(m_parkspace_data_msg);
            }
            if ((DateTime.Now - m_last_parkspace_status_time).TotalMilliseconds > m_timeout_milli)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        //重载检查消息--检查是否给终端的消息
        /// <summary>
        /// 检查消息
        /// </summary>
        /// <param name="header"></param>
        /// <returns></returns>
        public override bool check_msg(ByteString message)
        {
            return true;
        }
        /// <summary>
        /// 检查执行器状态
        /// </summary>
        /// <param name="header"></param>
        /// <param name="receiveTime"></param>
        /// <returns></returns>
        public override bool check_executer()
        {
            return base.check_executer();
        }
        /// <summary>
        /// 检查连接状态
        /// </summary>
        /// <param name="header"></param>
        /// <param name="receiveTime"></param>
        /// <returns></returns>
        public  bool check_connect()
        {
            if ((DateTime.Now.Ticks / 10000 - m_recv_parkspace_status_time.Ticks / 10000) > m_timeout_milli)
            {
                return false;
            }
            else
            {
                return true;
            }
        }
        /// <summary>
        /// 发送消息
        /// </summary>
        /// <param name="msg"></param>
        public override void encapsulate_msg(ByteString msg)
        {
            base.encapsulate_msg(msg);
        }
        /// <summary>
        /// 定时封装发送消息, 一般为心跳和状态信
        /// </summary>
        public override void encapsulate_send_data()
        {
            Parkspace_refresh_request_msg t_refresh_req = new Parkspace_refresh_request_msg();
            t_refresh_req.BaseInfo = new Base_info();
            t_refresh_req.BaseInfo.MsgType = Message_type.EParkspaceRefreshRequestMsg;
            t_refresh_req.BaseInfo.TimeoutMs = 5000;
            t_refresh_req.BaseInfo.Sender = Message.Communicator.EEmpty;
            t_refresh_req.BaseInfo.Receiver = Message.Communicator.EParkspace;

            encapsulate_msg(t_refresh_req.ToByteString());
            //   Console.WriteLine(terminal_Status_Msg.ToString());
        }
        //重载处理消息
        public override void execute_msg(ByteString messgae)
        {

            Base_msg base_msg = new Base_msg();
            try
            {
                base_msg = Base_msg.Parser.ParseFrom(messgae);
            }
            catch (Exception ex)
            {
                Console.WriteLine("message analysis error ! ");
            }
            if (base_msg.BaseInfo != null)
            {
                switch (base_msg.BaseInfo.MsgType)
                {
                    //车位数据反馈消息
                    case Message_type.EParkspaceAllocationDataResponseMsg:
                        {
                            Parkspace_allocation_data_msg parkspace_status_msg = Parkspace_allocation_data_msg.Parser.ParseFrom(messgae);
                            m_parkspaceStatusCallback?.Invoke(parkspace_status_msg);
                        }
                        break;
                    //手动修改车位反馈消息
                    case Message_type.EParkspaceForceUpdateResponseMsg:
                        {
                            Parkspace_force_update_response_msg parkspace_force_update_msg = Parkspace_force_update_response_msg.Parser.ParseFrom(messgae);
                            m_parkspaceForceUpdateResponseCallback?.Invoke(parkspace_force_update_msg);
                        }
                        break;
                    //手动查询车位反馈消息
                    case Message_type.EParkspaceManualSearchResponseMsg:
                        {
                            Parkspace_manual_search_response_msg parkspace_Manual_Search_Response_Msg = Parkspace_manual_search_response_msg.Parser.ParseFrom(messgae);
                            m_parkspacemanual_search_Callback?.Invoke(parkspace_Manual_Search_Response_Msg);
                        }
                        break;
                    //数据库状态消息，包括车位信息
                    case Message_type.EParkspaceAllocationStatusMsg:
                        {
                            m_recv_parkspace_status_time = DateTime.Now;
                            Parkspace_allocation_data_msg parkspace_allocation_data_msg = Parkspace_allocation_data_msg.Parser.ParseFrom(messgae);
                            if (parkspace_allocation_data_msg.ErrorManager.ErrorCode == 0)
                            {
                                UIMessageData.Instance.DatabaseNodeStatu = UIMessageData.NodeStatu.Normal;
                            }
                            else
                            {
                                UIMessageData.Instance.DatabaseNodeStatu = UIMessageData.NodeStatu.Error;
                            }
                        }
                        break;
                    //停车指令进度条消息
                    case Message_type.EStoringProcessStatuMsg:
                        {
                            Storing_process_statu_msg storing_Process_Statu_Msg = Storing_process_statu_msg.Parser.ParseFrom(messgae);
                            m_storing_process_statu_Callback?.Invoke(storing_Process_Statu_Msg);
                        }
                        break;
                    //取车指令进度条消息
                    case Message_type.EPickingProcessStatuMsg:
                        {
                            Picking_process_statu_msg picking_Process_Statu_Msg = Picking_process_statu_msg.Parser.ParseFrom(messgae);
                            m_picking_process_statu_Callback?.Invoke(picking_Process_Statu_Msg);
                        }
                        break;
                    //中控系统状态消息
                    case Message_type.ECentralControllerStatuMsg:
                        {
                            UIMessageData.Instance.MainNodeStatu = UIMessageData.NodeStatu.Normal;
                        }
                        break;
                    //出口LED系统状态消息
                    case Message_type.ENotifyStatusMsg:
                        {
                            UIMessageData.Instance.OutputUnnormalNodeStatu = UIMessageData.NodeStatu.Normal;
                        }
                        break;
                    //调度模块硬件状态消息
                    case Message_type.EDispatchStatusMsg:
                        {
                            Dispatch_terminal_status_msg dispatch_Terminal_Status_Msg = Dispatch_terminal_status_msg.Parser.ParseFrom(messgae);
                            UIMessageData.NodeStatu nodeStatu = UIMessageData.NodeStatu.Error;
                            if (dispatch_Terminal_Status_Msg.TerminalStatus != Terminal_status.ETerminalFault &&
                                dispatch_Terminal_Status_Msg.TerminalStatus != Terminal_status.ETerminalUnknow)
                            {
                                nodeStatu = UIMessageData.NodeStatu.Normal;
                            }
                            else
                            {
                                nodeStatu = UIMessageData.NodeStatu.Error;
                            }
                            switch (dispatch_Terminal_Status_Msg.IdStruct.UnitId)
                            {
                                case 0:
                                {
                                    UIMessageData.Instance.PLCStatuA = nodeStatu;
                                }
                                break;
                                case 1:
                                {
                                    UIMessageData.Instance.PLCStatuB = nodeStatu;
                                }
                                break;
                                case 2:
                                {
                                    UIMessageData.Instance.PLCStatuC = nodeStatu;
                                }
                                break;
                                default:
                                    break;
                            }
                        }
                        break;
                    //终端状态消息
                    case Message_type.ETerminalStatusMsg:
                        {
                            Terminal_status_msg terminal_Status_Msg = Terminal_status_msg.Parser.ParseFrom(messgae);
                            //Console.WriteLine(terminal_Status_Msg.ToString());
                            switch (terminal_Status_Msg.IdStruct.TerminalId)
                            {
                                case 0:
                                {
                                    UIMessageData.Instance.TerminalStatuA1 = UIMessageData.NodeStatu.Normal;
                                }
                                break;
                                case 1:
                                {
                                    UIMessageData.Instance.TerminalStatuA2 = UIMessageData.NodeStatu.Normal;
                                }
                                break;
                                case 2:
                                {
                                    UIMessageData.Instance.TerminalStatuB1 = UIMessageData.NodeStatu.Normal;
                                }
                                break;
                                case 3:
                                {
                                    UIMessageData.Instance.TerminalStatuB2 = UIMessageData.NodeStatu.Normal;
                                }
                                break;
                                case 4:
                                {
                                    UIMessageData.Instance.TerminalStatuC1 = UIMessageData.NodeStatu.Normal;
                                }
                                break;
                                case 5:
                                {
                                    UIMessageData.Instance.TerminalStatuC2 = UIMessageData.NodeStatu.Normal;
                                }
                                break;
                                case 6:
                                {
                                    UIMessageData.Instance.OutputTerminal1Statu = UIMessageData.NodeStatu.Normal;
                                }
                                break;
                                case 7:
                                {
                                    UIMessageData.Instance.OutputTerminal2Statu = UIMessageData.NodeStatu.Normal;
                                }
                                break;
                                default:
                                    break;
                            }
                        }
                        break;
                    //地面雷达状态消息
                    case Message_type.EGroundStatusMsg:
                    {
                        Ground_status_msg ground_Statu_Msg = Ground_status_msg.Parser.ParseFrom(messgae);
                        UIMessageData.NodeStatu nodeStatu = UIMessageData.NodeStatu.Error;
                        if (ground_Statu_Msg.ErrorManager.ErrorLevel == Error_level.MinorError ||
                            ground_Statu_Msg.ErrorManager.ErrorLevel == Error_level.NegligibleError ||
                            ground_Statu_Msg.ErrorManager.ErrorCode == 0)
                        {
                            nodeStatu = UIMessageData.NodeStatu.Normal;
                        }
                        else
                        {
                            nodeStatu = UIMessageData.NodeStatu.Error;
                        }
                        switch (ground_Statu_Msg.IdStruct.TerminalId)
                        {
                            case 0:
                            {
                                UIMessageData.Instance.LidarStatuA1 = nodeStatu;
                            }
                            break;
                            case 1:
                            {
                                UIMessageData.Instance.LidarStatuA2 = nodeStatu;
                            }
                            break;
                            case 2:
                            {
                                UIMessageData.Instance.LidarStatuB1 = nodeStatu;
                            }
                            break;
                            case 3:
                            {
                                UIMessageData.Instance.LidarStatuB2 = nodeStatu;
                            }
                            break;
                            case 4:
                            {
                                UIMessageData.Instance.LidarStatuC1 = nodeStatu;
                            }
                            break;
                            case 5:
                            {
                                UIMessageData.Instance.LidarStatuC2 = nodeStatu;
                            }
                            break;
                            default:
                                break;
                        }
                    }
                    break;
                    default:
                        //Console.WriteLine("unrecognized message received");
                        break;
                }
            }
        }


        private DateTime m_recv_parkspace_status_time;                  //接收车位状态时间
        private Parkspace_allocation_data_msg m_parkspace_data_msg;     //车位数据
        /// <summary>
        /// 车位状态访问锁
        /// </summary>
        private object m_parkspace_status_access_lock;
        /// <summary>
        /// 当前时间
        /// </summary>
        private DateTime m_last_parkspace_status_time;
        public int      m_timeout_milli = 3000;
    }
}
