using Communication;
using Google.Protobuf;
using Message;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace communicate_module.communication
{
    class TerminalSimul : Communication.Communicator
    {
        protected TerminalSimul() : base()
        {
            map_lock = new object();
            license_status_map = new Dictionary<string, CAR_STATUS>();
            for (int i = 0; i < 11; i++)
            {
                string str = String.Format("鄂A{0:D5}", i);
                license_status_map.Add(str, CAR_STATUS.eCAR_IDEL);
                //Console.WriteLine(str);
            }

            park_terminal_status_map = new Dictionary<int, int>();
            for (int i = 0; i < 6; i++)
            {
                park_terminal_status_map.Add(i, 0);
            }

            fetch_terminal_status_map = new Dictionary<int, int>();
            for (int i = 0; i < 6; i++)
            {
                fetch_terminal_status_map.Add(i, 0);
            }

            park_license_map = new Dictionary<int, string>();
            fetch_license_map = new Dictionary<int, string>();
        }

        /// <summary>
        /// 单例访问
        /// </summary>
        public new static TerminalSimul GetInstance()
        {
            if (instance == null)
            {
                lock (lockObj)
                {
                    if (instance == null)
                    {
                        instance = new TerminalSimul();
                    }
                }
            }
            return (TerminalSimul)instance;
        }

        /// <summary>
        /// 检查消息
        /// </summary>
        /// <param name="header"></param>
        /// <returns></returns>
        public override bool CheckMsg(Base_info header)
        {
            if (header.HasMsgType && header.HasSender
                && ((header.MsgType == Message_type.EStoreCommandResponseMsg && header.Sender == Message.Communicator.EMain)
                    || (header.MsgType == Message_type.EPickupCommandResponseMsg && header.Sender == Message.Communicator.EMain)
                    || (header.MsgType == Message_type.EStoringProcessStatuMsg && header.Sender == Message.Communicator.EMain)
                    || (header.MsgType == Message_type.EPickingProcessStatuMsg && header.Sender == Message.Communicator.EMain)
                    )
                )
                return true;
            else
                return false;
        }

        /// <summary>
        /// 检查执行器状态
        /// </summary>
        /// <param name="header"></param>
        /// <param name="receiveTime"></param>
        /// <returns></returns>
        public override CheckExecuterReturn CheckExecuter(Base_info header, DateTime receiveTime)
        {
            if ((DateTime.Now - receiveTime).Milliseconds > header.TimeoutMs)
                return CheckExecuterReturn.MSG_TIMEOUT;
            else
                return CheckExecuterReturn.EXECUTER_READY;
        }

        /// <summary>
        /// 执行消息
        /// </summary>
        /// <param name="msgStamped"></param>
        /// <returns></returns>
        public override bool ExecuteMsg(MsgStamped msgStamped)
        {
            if (msgStamped == null || msgStamped.header==null)
                return false;

            //Console.WriteLine("接收消息："+msgStamped.header.ToString());
            switch(msgStamped.header.MsgType)
            {
                case Message_type.EStoreCommandResponseMsg:
                    Store_command_response_msg store_Command_Response_Msg = Store_command_response_msg.Parser.ParseFrom(msgStamped.msg);
                    lock (map_lock)
                    {
                        if (park_license_map.ContainsKey(store_Command_Response_Msg.TerminalId))
                        {
                            string park_lic = park_license_map[store_Command_Response_Msg.TerminalId];
                            // 失败不将车辆复位，由状态消息复位
                            if (store_Command_Response_Msg.Code.ErrorCode != 0)
                            {
                                if (license_status_map.ContainsKey(park_lic))
                                {
                                    //license_status_map[park_lic] = CAR_STATUS.eCAR_IDEL;
                                    Console.WriteLine(store_Command_Response_Msg.TerminalId + "停车签收失败已将" + park_lic + "置为空闲");
                                }
                                else
                                {
                                    Console.WriteLine(store_Command_Response_Msg.TerminalId + "!!!!!停车签收未找到终端对应号牌车辆状态");
                                }
                            }
                            else
                            {
                                Console.WriteLine("停车终端 " + store_Command_Response_Msg.TerminalId + " 签收! 号牌 "+ park_lic);
                            }
                        }
                        else
                        {
                            Console.WriteLine(store_Command_Response_Msg.TerminalId + "!!!!!停车签收未找到终端对应号牌");
                        }
                    }
                    break;
                case Message_type.EPickupCommandResponseMsg:
                    Pickup_command_response_msg pickup_Command_Response_Msg = Pickup_command_response_msg.Parser.ParseFrom(msgStamped.msg);
                    lock (map_lock)
                    {
                        if (fetch_license_map.ContainsKey(pickup_Command_Response_Msg.TerminalId))
                        {
                            string fetch_lic = fetch_license_map[pickup_Command_Response_Msg.TerminalId];
                            // 失败不将车辆复位，由状态消息复位
                            if (pickup_Command_Response_Msg.Code.ErrorCode != 0)
                            {
                                if (license_status_map.ContainsKey(fetch_lic))
                                {
                                    //license_status_map[fetch_lic] = CAR_STATUS.eCAR_PARKED;
                                    Console.WriteLine(pickup_Command_Response_Msg.TerminalId + "取车签收失败已将" + fetch_lic + "置为占用");
                                }
                                else
                                {
                                    Console.WriteLine(pickup_Command_Response_Msg.TerminalId + "!!!!!取车签收未找到终端对应号牌车辆状态");
                                }
                            }
                            else
                            {
                                Console.WriteLine("取车终端 " + pickup_Command_Response_Msg.TerminalId + " 签收! 号牌 " + fetch_lic);
                            }
                        }
                        else
                        {
                            Console.WriteLine(pickup_Command_Response_Msg.TerminalId + "!!!!!取车签收未找到终端对应号牌");
                        }
                    }
                    break;
                case Message_type.EStoringProcessStatuMsg:
                    Storing_process_statu_msg storing_Process_Statu_Msg = Storing_process_statu_msg.Parser.ParseFrom(msgStamped.msg);
                    if (storing_Process_Statu_Msg.Completed || storing_Process_Statu_Msg.BackCompleted)
                    {
                        bool forward = storing_Process_Statu_Msg.Completed;
                        lock (map_lock)
                        {
                            if (park_license_map.ContainsKey(storing_Process_Statu_Msg.TerminalId))
                            {
                                string lic = park_license_map[storing_Process_Statu_Msg.TerminalId];
                                if (license_status_map.ContainsKey(lic) && lic == storing_Process_Statu_Msg.License)
                                {
                                    string whether_success = "";
                                    if (forward)
                                    {
                                        // 车辆状态修改
                                        license_status_map[lic] = CAR_STATUS.eCAR_PARKED;
                                        whether_success = "成功";
                                    }
                                    else
                                    {
                                        license_status_map[lic] = CAR_STATUS.eCAR_IDEL;
                                        whether_success = "失败";
                                    }
                                    // 停车流程结束，删除记录
                                    park_license_map.Remove(storing_Process_Statu_Msg.TerminalId);
                                    // 停车终端复位
                                    park_terminal_status_map[storing_Process_Statu_Msg.TerminalId] = 0;
                                    Console.WriteLine(storing_Process_Statu_Msg.TerminalId+"停车 " + lic + " 完成, " + whether_success);
                                }
                            }
                            else
                            {
                                //Console.WriteLine("未找到与反馈对应停车流程？？？");
                            }
                        }
                    }
                    break;
                case Message_type.EPickingProcessStatuMsg:
                    Picking_process_statu_msg picking_Process_Statu_Msg = Picking_process_statu_msg.Parser.ParseFrom(msgStamped.msg);
                    if (picking_Process_Statu_Msg.Completed || picking_Process_Statu_Msg.BackCompleted)
                    {
                        bool forward = picking_Process_Statu_Msg.Completed;
                        lock (map_lock)
                        {
                            if (fetch_license_map.ContainsKey(picking_Process_Statu_Msg.TerminalId))
                            {
                                string lic = fetch_license_map[picking_Process_Statu_Msg.TerminalId];
                                if (license_status_map.ContainsKey(lic) && lic == picking_Process_Statu_Msg.License)
                                {
                                    string whether_success = "";
                                    if (forward)
                                    {
                                        license_status_map[lic] = CAR_STATUS.eCAR_IDEL;
                                        whether_success = "成功";
                                    }
                                    else
                                    {
                                        license_status_map[lic] = CAR_STATUS.eCAR_PARKED;
                                        whether_success = "失败";
                                    }
                                    fetch_license_map.Remove(picking_Process_Statu_Msg.TerminalId);
                                    fetch_terminal_status_map[picking_Process_Statu_Msg.TerminalId] = 0;
                                    Console.WriteLine(picking_Process_Statu_Msg.TerminalId+"取车 " + lic + " 完成， " + whether_success);
                                }
                            }
                            else
                            {
                                //Console.WriteLine("未找到与反馈对应取车流程？？？");
                            }
                        }
                    }
                    break;
            }
            return true;
        }

        /// <summary>
        /// 模拟终端与主控发送消息
        /// </summary>
        public void CreateSimulThread()
        {
            Task.Factory.StartNew(()=> {
                Random rnd = new Random();
                while(!mb_exit)
                {
                    int act = rnd.Next(1, 4);
                    lock (map_lock) {
                        switch (act)
                        {
                            // 停车
                            case 1:
                                // 找一辆空闲车发送停车指令
                                string park_lic = "";
                                KeyValuePair<string, CAR_STATUS> t_park_lic_pair;
                                for (int i = 0; i < license_status_map.Count; i++)
                                {
                                    t_park_lic_pair = license_status_map.ElementAt(i);
                                    if (t_park_lic_pair.Value == CAR_STATUS.eCAR_IDEL)
                                    {
                                        park_lic = t_park_lic_pair.Key;
                                        break;
                                    }
                                }
                                if(park_lic != "")
                                {
                                    Store_command_request_msg t_store_req = new Store_command_request_msg();
                                    t_store_req.BaseInfo = new Base_info();
                                    t_store_req.BaseInfo.MsgType = Message_type.EStoreCommandRequestMsg;
                                    t_store_req.BaseInfo.TimeoutMs = 5000;
                                    t_store_req.BaseInfo.Sender = Message.Communicator.ETerminor;
                                    t_store_req.BaseInfo.Receiver = Message.Communicator.EMain;
                                    // 寻找空闲终端
                                    int termId = GetParkTerminalId();
                                    if(termId>=0)
                                    {
                                        t_store_req.TerminalId = termId;
                                        t_store_req.LocateInformation = new Locate_information();
                                        t_store_req.LocateInformation.LocateX = 0.01f;
                                        t_store_req.LocateInformation.LocateY = 0.01f;
                                        t_store_req.LocateInformation.LocateAngle = 90.5f;
                                        t_store_req.LocateInformation.LocateLength = 0f;
                                        t_store_req.LocateInformation.LocateWidth = 0f;
                                        t_store_req.LocateInformation.LocateHeight = 0f;
                                        t_store_req.LocateInformation.LocateWheelBase = 2.64f;
                                        t_store_req.LocateInformation.LocateWheelWidth = 1.65f;
                                        t_store_req.LocateInformation.LocateCorrect = true;
                                        t_store_req.LocateInformation.LocateFrontTheta = 0f;
                                        t_store_req.CarInfo = new Car_info();
                                        t_store_req.CarInfo.License = park_lic;
                                        t_store_req.CarInfo.CarHeight = 1.8f+(float)(rnd.NextDouble()-0.5)*0.6f;
                                        t_store_req.CarInfo.CarWheelWidth = t_store_req.LocateInformation.LocateWheelWidth;
                                        t_store_req.CarInfo.CarWheelBase = t_store_req.LocateInformation.LocateWheelBase;
                                        // 发送停车指令
                                        Console.WriteLine(termId+"停车指令 " +park_lic);
                                        Send_msg(t_store_req.ToByteString());
                                        license_status_map[park_lic] = CAR_STATUS.eCAR_PARKING;
                                        park_license_map.Add(termId, park_lic);
                                    }
                                }
                                break;
                            // 取车
                            case 2:
                                // 找一辆占用车发送取车指令
                                string fetch_lic = "";
                                KeyValuePair<string, CAR_STATUS> t_fetch_lic_pair;
                                for (int i = 0; i < license_status_map.Count; i++)
                                {
                                    t_fetch_lic_pair = license_status_map.ElementAt(i);
                                    if (t_fetch_lic_pair.Value == CAR_STATUS.eCAR_PARKED)
                                    {
                                        fetch_lic = t_fetch_lic_pair.Key;
                                        break;
                                    }
                                }
                                if(fetch_lic!="")
                                {
                                    Pickup_command_request_msg pick_req = new Pickup_command_request_msg();
                                    pick_req.BaseInfo = new Base_info();
                                    pick_req.BaseInfo.MsgType = Message_type.EPickupCommandRequestMsg;
                                    pick_req.BaseInfo.TimeoutMs = 5000;
                                    pick_req.BaseInfo.Sender = Message.Communicator.ETerminor;
                                    pick_req.BaseInfo.Receiver = Message.Communicator.EMain;
                                    // 寻找空闲终端
                                    int termId = GetFetchTerminalId();
                                    if(termId >=0)
                                    {
                                        pick_req.TerminalId = termId;
                                        pick_req.CarInfo = new Car_info();
                                        pick_req.CarInfo.License = fetch_lic;
                                        // 发送取车指令
                                        Console.WriteLine(termId+"取车指令 " + fetch_lic);
                                        Send_msg(pick_req.ToByteString());
                                        license_status_map[fetch_lic] = CAR_STATUS.eCAR_FETCHING;
                                        fetch_license_map.Add(termId, fetch_lic);
                                    }
                                }
                                break;
                            // 不处理
                            case 3:
                                break;
                        }
                        
                    }
                    Thread.Sleep(1000);
                }
            });
        }

        protected int GetParkTerminalId()
        {
            int termId = -1;
            KeyValuePair<int, int> t_res;
            for (int i = 0; i < park_terminal_status_map.Count; i++)
            {
                t_res = park_terminal_status_map.ElementAt(i);
                // 停取终端同时空闲
                if (t_res.Value == 0)
                {
                    termId = t_res.Key;
                    break;
                }
            }
            if(termId>=0)
                park_terminal_status_map[termId] = 1;
            return termId;
        }

        protected int GetFetchTerminalId()
        {
            int termId = -1;
            KeyValuePair<int, int> t_res;
            for (int i = 0; i < fetch_terminal_status_map.Count; i++)
            {
                t_res = fetch_terminal_status_map.ElementAt(i);
                if (t_res.Value == 0)
                {
                    termId = t_res.Key;
                    break;
                }
            }
            if (termId >= 0)
                fetch_terminal_status_map[termId] = 1;
            return termId;
        }

        public enum CAR_STATUS
        {
            eCAR_IDEL,
            eCAR_PARKED,
            eCAR_PARKING,
            eCAR_FETCHING,
        }

        protected object map_lock;
        // 车辆状态表
        protected Dictionary<string, CAR_STATUS> license_status_map;
        // 记录停车终端当前号牌
        protected Dictionary<int, string> park_license_map;
        // 记录取车终端当前号牌
        protected Dictionary<int, string> fetch_license_map;


        // 0空闲，非零占用
        protected Dictionary<int, int> park_terminal_status_map;
        // 0空闲，非零占用
        protected Dictionary<int, int> fetch_terminal_status_map;
    }
}
