using ProjectBase.Data.Logs;
using ProjectBase.Data.Redis;
using ProjectBase.Util;
using SIASUN.Autopilot.Device;
using SIASUN.Autopilot.EventMessage;
using SIASUN.Autopilot.GNSS;
using System;

namespace SIASUN.Autopilot.BLL
{
    /// <summary>
    /// GNSS定位导航信息感知模块
    /// </summary>
    public class BlGNSSPerception
    {
        public static SerialPortBase GNSSSerialPort; 

       // public event EventGNSSInfoHandler GNSSHandler;
        public event EventHandler<GNSSInfoEventArgs> GNSSHandler;

        public static BlGNSSPerception Instance { get; private set; }

        private string lastLatitude = "0000.00000000";

        private string lastlongitude = "00000.00000000";

      

        static BlGNSSPerception()
        {
            Instance = new BlGNSSPerception();
        }

        public void Init()
        {
            string PortNumber = System.Configuration.ConfigurationManager.AppSettings["PortNumber"];
            int baudRate = int.Parse(System.Configuration.ConfigurationManager.AppSettings["baudRate"]);
            int DataBits = int.Parse(System.Configuration.ConfigurationManager.AppSettings["DataBits"]);
            GNSSSerialPort = new SerialPortBase(PortNumber, baudRate, DataBits);
            GNSSSerialPort.serialDataReceived += GNSSSerialPort_serialDataReceived;
        }

        private void GNSSSerialPort_serialDataReceived(SerialPortDataReceiveEventArgs e)
        {
            LogHelper.log.Debug("接收的报文为：" + e.Value);
            string[] split = e.Value.Split('$');  
            if (split.Length != 4)
            {
                LogHelper.log.Error("接收到的GNSS信号格式出现错误");
                return;
            }
            NMEA0183 nmea = new NMEA0183();
            if (!GetNMEA0183(ref split, out nmea))
            {
                return;
            }
            GNSSInfoEventArgs gnss = new GNSSInfoEventArgs(nmea);
            gnss.Raise(this,ref GNSSHandler);
            //GNSSHandler(gnss);
        }

        /// <summary>
        /// 解析NMEA0183协议
        /// </summary> 
        /// <param name="protocol"></param>  
        /// <param name="nmea"></param> 
        private bool GetNMEA0183(ref string[] strNMEA, out NMEA0183 nmea)
        {
            try 
            {
                string[] strValues = strNMEA;
                NMEA0183 temp = new NMEA0183();
                for (int i = 1; i < strValues.Length; i++)
                {
                    string[] protocol = strValues[i].Split('*');
                    string[] value = protocol[0].Split(',');
                    if (value[0].Equals("GPGGA"))
                    {
                        if (value[2].Contains(lastLatitude.Substring(0, 9)))// 精确到分米
                        {
                            LogHelper.log.Debug("通过纬度去掉重复点");
                            lastLatitude = value[2];
                            nmea = null;
                            return false;
                        }
                        lastLatitude = value[2];
                        if (value[4].Contains(lastlongitude.Substring(0, 10)))// 精确到分米
                        {
                            LogHelper.log.Debug("通过经度去掉重复点");
                            lastlongitude = value[4];
                            nmea = null;
                            return false;
                        }
                        lastlongitude = value[4];
                        GPGGA gpgga = new GPGGA();
                        GetGPGGA(value, out gpgga);
                        temp.gpgga = gpgga;
                    }
                    else if (value[0].Equals("GPRMC"))
                    {
                        GPRMC gprmc = new GPRMC();
                        GetGPRMC(value, out gprmc);
                        temp.gprmc = gprmc;
                    }
                    else
                    {
                        string pashr = protocol[0];
                        temp.pashr = pashr;
                    }
                }            
                nmea = temp;
                return true;
            }
            catch(Exception ex)
            {
                LogHelper.log.Error("nmea协议解析出现错误",ex);
                nmea = null;
                return false;
            }
        }

        /// <summary>
        /// 解析GPGGA协议
        /// </summary>
        private void GetGPGGA(string [] value, out GPGGA nmea)
        {
            GPGGA temp = new GPGGA();
            temp.utcTime = value[1];
            temp.Latitude = GetDegrees(value[2], 2);
            temp.LatType = value[3];
            temp.Longitude = GetDegrees(value[4], 3);
            temp.LonType = value[5];
            temp.GPSStatus = Convert.ToInt32(value[6]);
            temp.SatelliteNumber = Convert.ToInt32(value[7]);
            temp.Hdop = Convert.ToDecimal(value[8]);
            temp.Height = Convert.ToDecimal(value[9]);
            temp.ReleaveHeight = value[10];
            temp.CTKTime = value[11];
            temp.Check = value[12];
            nmea = temp;
        }


        /// <summary>
        /// 解析GPRMC协议
        /// </summary> 
        private void GetGPRMC(string[] value, out GPRMC nmea)
        {
            GPRMC temp = new GPRMC();
            temp.utcTime = value[1];
            temp.locationStatus = value[2];
            temp.Latitude = GetDegrees(value[3], 2);
            temp.LatType = value[4];
            temp.Longitude = GetDegrees(value[5], 3);
            temp.LonType = value[6];
            temp.Speed = Convert.ToDecimal(value[7]);
            temp.Deviated = Convert.ToDecimal(value[8]);
            temp.Date = value[9];
            temp.Magnetic = Convert.ToDecimal(value[10]);
            temp.MagneticDirection = value[11];
            temp.Mode = value[12];
            nmea = temp;
        }

        /// <summary>
        /// 把经度和纬度坐标转换成度
        /// </summary>
        /// <param name="para">ddmm.mmmmmmmm</param>
        private decimal GetDegrees(string para, int pos)
        {
            decimal degrees = 0;
            try
            {
                degrees = Convert.ToDecimal(para.Substring(0, pos)) + 
                    Convert.ToDecimal(para.Substring(pos, para.Length - pos))/60;
            }
            catch (Exception ex)
            {
                LogHelper.log.Error("经纬度坐标转换出现错误", ex);
            }
            return degrees;
        }



        public void Close()
        {
            GNSSSerialPort.Close();
        }
    }

    /// <summary>
    /// 串口接收数据 
    /// </summary> 
    public delegate void EventGNSSInfoHandler(GNSSInfoEventArgs e);

    public class GNSSInfoEventArgs : EventArgs  
    {
        public NMEA0183 Nmea { get; set; } 

        public GNSSInfoEventArgs(NMEA0183 value)
        {
            this.Nmea = value;
        }
    }
}
