/// <summary>
 /// Calculates the signal strength based off Block Error Rate thresholds
 /// </summary>
 /// <returns></returns>
 private static void CalculateSignalStrength(StatsPacketModel Packet)
 {
     if (Packet.BlockError < 11)      // 0-10
         Packet.SignalStrength = 5;
     else if (Packet.BlockError < 31) // 11-30
         Packet.SignalStrength = 4;
     else if (Packet.BlockError < 51) // 31-50
         Packet.SignalStrength = 3;
     else if (Packet.BlockError < 71) // 51-70
         Packet.SignalStrength = 2;
     else if (Packet.BlockError < 91) // 71-90
         Packet.SignalStrength = 1;
     else                             // 91-100
         Packet.SignalStrength = 0;
 }
		/// <summary>
		/// Updates the current info with the given stats information
		/// </summary>
		/// <param name="Stats"></param>
		public void Update(StatsPacketModel Stats)
		{
			if (Stats != null)
			{
				this.MACAddress = Stats.MACAddress;
				this.SignalStrength = Stats.SignalStrength;
				this.QualityLED = Stats.QualityLED;
				this.Ethernet = Stats.Ethernet;
			}
		}
        /// <summary>
        /// Parses The Stats Response UDP packet from a radio control
        /// little endian: Network ID, Total packets, Failed Packets, Passed Packets, Broadcast Packets, Unicast Packets, AverageTX, 
        /// AverageRX, BER, and RSSI will look backwards
        /// </summary>
        /// <param name="packet">Packet received from Stats request on radio</param>
        public static StatsPacketModel ParseStatsPacket(byte[] packet)
        {
            StatsPacketModel Info = new StatsPacketModel();
            int offset = 3;

            // Offset 3 MAC Address - 6 bytes
            Info.MACAddress = ParseMAC(packet, ref offset);

            // Offset 9 Network ID - 4 bytes
            byte[] network = Encoding.Convert(Encoding.BigEndianUnicode, Encoding.Unicode, packet, offset, 4); // change to little endian
            Info.NetworkID = BitConverter.ToString(network);
            offset += 4;

            // Offset 13 Radio Status, RF Connected/RadioActive/RFChannel - 1 byte
            #region Bit Checking
            int temp = packet[offset] >> 6;
            if (temp >= 2)
            {
                Info.RFConnect = true; // Bit 7 of RadioStatus byte is T/F RF Connected
                temp -= 2;
            }
            else
            {
                Info.RFConnect = false;
            }
            if (temp == 1)
            {
                Info.RadioActive = true; // Bit 6 of RadioStatus byte is T/F RFActive
            }
            else
            {
                Info.RadioActive = false;
            }
            #endregion
            Info.RFChannel = ((byte)(packet[offset++] << 2) >> 2); // bit 5:0 is RFChannel - cut off bit 7:6

            // Offset 14 Ethernet Status, Link Up/Full Duplex/10 Mbps - 1 byte
            #region Bit Checking
            temp = packet[offset++] >> 5;
            if (temp >= 4)
            {
                Info.EthernetLink = true; // bit 7 is T/F Link Up
                temp -= 4;
            }
            else
            {
                Info.EthernetLink = false;
            }
            if (temp >= 2)
            {
                Info.EthernetDuplex = true; // bit 6 is T/F Full Duplex
                temp -= 2;
            }
            else
            {
                Info.EthernetDuplex = false;
            }
            if (temp == 1)
            {
                Info.EthernetSpeed = true; // bit 5 is T/F 100 Mbps
            }
            else
            {
                Info.EthernetSpeed = false;
            }
            #endregion
            if (Info.EthernetLink)
            {
                if (Info.EthernetSpeed)
                {
                    Info.Ethernet = "100 Mbps";
                    if (Info.EthernetDuplex)
                    {
                        Info.Ethernet += " Full Duplex";
                    }
                }
                else if (Info.EthernetDuplex)
                {
                    Info.Ethernet = "Full Duplex";
                }
            }
            else
            {
                Info.Ethernet = "Disconnected";
            }

            // Offset 15 Device ID, Server/Client/(Number of IDs or Device ID) - 1 byte
            temp = packet[offset] >> 6;
            if (temp == 3) // b7:b6 = 1:1 is Client
            {
                Info.Device = StatsPacketModel.DeviceType.Client;
            }
            else if (temp == 0) // b7:b6 = 0:0 is Device Not Configured
            {
                Info.Device = StatsPacketModel.DeviceType.NotConfigured;
            }
            else // b7:b6 = 1:0 or 0:1 is Server
            {
                Info.Device = StatsPacketModel.DeviceType.Server;
            }
            Info.DeviceID = ((byte)(packet[offset++] << 2) >> 2); // Device ID/Number of Clients

			// Offset 16 byte 7 - Determine if set to manual or automatic channel mode
			Info.IsManualChannelMode = (packet[offset] & (1 << 7)) != 0;

			// Offset 16 bytes 6:0 Number of connected Client - only Server will have number other than 0
            Info.ConnectedDevices = packet[offset++] & 127; // bitwise AND with value 127 since we only want bits 6:0 (not bit 7)

            // Offset 17 Total Packets
            Info.TotalPackets = BitConverter.ToUInt32(packet, offset); // 4 bytes - little endian
            offset += 4;

            // Offset 21 Failed Packets
            Info.FailedPackets = BitConverter.ToUInt32(packet, offset); // 4 bytes - little endian
            offset += 4;

            // Offset 25 Passed Packets
            Info.PassedPackets = BitConverter.ToUInt32(packet, offset); // 4 bytes - little endian
            offset += 4;

            // Offset 29 Broadcast Packets
            Info.BroadcastPackets = BitConverter.ToUInt32(packet, offset); // 4 bytes - little endian
            offset += 4;

            // Offset 33 Unicast Packets
            Info.UnicastPackets = BitConverter.ToUInt32(packet, offset); // 4 bytes - little endian
            offset += 4;

            // Offset 37 AverageTXSize
            Info.AverageTXSize = BitConverter.ToUInt16(packet, offset); // 2 bytes - little endian
            offset += 2;

            // Offset 39 AverageRXSize
            Info.AverageRXSize = BitConverter.ToUInt16(packet, offset); // 2 bytes - little endian
            offset += 2;

            // Offset 41 Block Error Rate - invert from 0-100 to 100-0
            // 2 bytes (first is 0-100)
            Info.BlockError = (float)(packet[offset]) + (float)(packet[offset + 1]) / 100;
            // Second byte is 0-99 hundrendths)
            Info.SignalPercent = (-(Info.BlockError - 101) - 1).ToString() + "%";
            offset += 2; // increment offset
            CalculateSignalStrength(Info); // Calculate Signal Strength bars

            // Offset 43 RSSI - 1 byte
            Info.RSSI = ((sbyte)packet[offset++]).ToString() + " dBm";

            // Offset 44 RFVersion - 3 bytes
            // Byte 1 RF Protocol (4 = multipoint)
            Info.RFProtocol = (StatsPacketModel.ProtocolType)packet[offset++];
            // Byte 2 Frequency (3 = 900 Mhz full band, 4 = 5800 MHz, 5 = 900 Mhz Half Band, 6 = 2400 MHz)
            Info.RadioVersion = (StatsPacketModel.RadioVersions)packet[offset++];
            // Byte 3 Firmware Release Number
            Info.RadioFirmware = Convert.ToString(packet[offset++], 16);

            // Offset 47 Ethernet Version - ASCII string with '.' separation between major, minor, and build numbers
            Info.Version = ASCIIEncoding.ASCII.GetString(packet, offset, 9);
			offset += 9;

			// Offset 56 Quality LEDs
			#region LED selector
			switch (packet[offset])
			{
				case 63:
					{
						Info.QualityLED = 6;
						break;
					}
				case 31:
					{
						Info.QualityLED = 5;
						break;
					}
				case 15:
					{
						Info.QualityLED = 4;
						break;
					}
				case 7:
					{
						Info.QualityLED = 3;
						break;
					}
				case 3:
					{
						Info.QualityLED = 2;
						break;
					}
				case 1:
					{
						Info.QualityLED = 1;
						break;
					}
				default:
					{
						Info.QualityLED = 0;
						break;
					}
			}
			offset += 1;
			#endregion

			// Offset 58 Radio Uptime
			if (packet.Length >= offset + 4)
			{
				var seconds = BitConverter.ToUInt32(packet, offset);
				Info.Uptime = TimeSpan.FromSeconds(seconds);
				offset += 4;
			}

			// Current time
			Info.LastUpdate = DateTime.Now;
            
            //Spews info into a Text file --DEVELOPMENT
            return Info;
        }