public void AircraftJson_Constructor_Initialises_To_Known_State_And_Properties_Work()
        {
            var aircraftJson = new AircraftJson();

            TestUtilities.TestProperty(aircraftJson, r => r.Altitude, null, 12);
            TestUtilities.TestProperty(aircraftJson, r => r.BearingFromHere, null, 12.3);
            TestUtilities.TestProperty(aircraftJson, r => r.Callsign, null, "ND");
            TestUtilities.TestProperty(aircraftJson, r => r.CallsignIsSuspect, null, true);
            TestUtilities.TestProperty(aircraftJson, r => r.ConstructionNumber, null, "Uu");
            TestUtilities.TestProperty(aircraftJson, r => r.Destination, null, "Bb");
            TestUtilities.TestProperty(aircraftJson, r => r.DistanceFromHere, null, 12.45);
            TestUtilities.TestProperty(aircraftJson, r => r.Emergency, null, false);
            TestUtilities.TestProperty(aircraftJson, r => r.EngineType, null, 1);
            TestUtilities.TestProperty(aircraftJson, r => r.FirstSeen, null, DateTime.UtcNow);
            TestUtilities.TestProperty(aircraftJson, r => r.FullCoordinates, null, new List<double?>() { 1.1, 2.2 });
            TestUtilities.TestProperty(aircraftJson, r => r.GroundSpeed, null, 12.4f);
            TestUtilities.TestProperty(aircraftJson, r => r.HasPicture, null, true);
            TestUtilities.TestProperty(aircraftJson, r => r.Icao24, null, "Hh");
            TestUtilities.TestProperty(aircraftJson, r => r.Icao24Country, null, "Jk");
            TestUtilities.TestProperty(aircraftJson, r => r.Icao24Invalid, null, true);
            TestUtilities.TestProperty(aircraftJson, r => r.IsMilitary, null, false);
            TestUtilities.TestProperty(aircraftJson, r => r.Latitude, null, 1.234);
            TestUtilities.TestProperty(aircraftJson, r => r.Longitude, null, 1.234);
            TestUtilities.TestProperty(aircraftJson, r => r.Model, null, "Mm");
            TestUtilities.TestProperty(aircraftJson, r => r.NumberOfEngines, null, "C");
            TestUtilities.TestProperty(aircraftJson, r => r.OnGround, null, true);
            TestUtilities.TestProperty(aircraftJson, r => r.Operator, null, "Hj");
            TestUtilities.TestProperty(aircraftJson, r => r.OperatorIcao, null, "Ik");
            TestUtilities.TestProperty(aircraftJson, r => r.Origin, null, "Yh");
            TestUtilities.TestProperty(aircraftJson, r => r.PositionTime, null, 1234L);
            TestUtilities.TestProperty(aircraftJson, r => r.Registration, null, "Fd");
            TestUtilities.TestProperty(aircraftJson, r => r.ResetTrail, false);
            TestUtilities.TestProperty(aircraftJson, r => r.ShortCoordinates, null, new List<double?>() { 1.1, 2.2 });
            TestUtilities.TestProperty(aircraftJson, r => r.Species, null, 12);
            TestUtilities.TestProperty(aircraftJson, r => r.Squawk, null, "4721");
            TestUtilities.TestProperty(aircraftJson, r => r.Stopovers, null, new List<string>() { "Hd" });
            TestUtilities.TestProperty(aircraftJson, r => r.Track, null, 12.34f);
            TestUtilities.TestProperty(aircraftJson, r => r.Type, null, "B747");
            TestUtilities.TestProperty(aircraftJson, r => r.UniqueId, 0, 12);
            TestUtilities.TestProperty(aircraftJson, r => r.UserTag, null, "Abc");
            TestUtilities.TestProperty(aircraftJson, r => r.VerticalRate, null, -239);
            TestUtilities.TestProperty(aircraftJson, r => r.WakeTurbulenceCategory, null, 7);
        }
        /// <summary>
        /// Copies the aircraft from the snapshot to the JSON object.
        /// </summary>
        /// <param name="aircraftListJson"></param>
        /// <param name="aircraftListSnapshot"></param>
        /// <param name="args"></param>
        /// <param name="distances"></param>
        private void CopyAircraft(AircraftListJson aircraftListJson, List<IAircraft> aircraftListSnapshot, AircraftListJsonBuilderArgs args, Dictionary<int, double?> distances)
        {
            var now = _Provider.UtcNow;

            foreach(var aircraftSnapshot in aircraftListSnapshot) {
                double? distance;
                if(!distances.TryGetValue(aircraftSnapshot.UniqueId, out distance)) distance = null;

                var aircraftJson = new AircraftJson() {
                    BearingFromHere = GreatCircleMaths.Bearing(args.BrowserLatitude, args.BrowserLongitude, aircraftSnapshot.Latitude, aircraftSnapshot.Longitude, null, false, true),
                    DistanceFromHere = distance == null ? (double?)null : Math.Round(distance.Value, 2),
                    UniqueId = aircraftSnapshot.UniqueId,
                };
                if(aircraftJson.BearingFromHere != null) aircraftJson.BearingFromHere = Math.Round(aircraftJson.BearingFromHere.Value, 1);

                bool firstTimeSeen = !args.PreviousAircraft.Contains(aircraftSnapshot.UniqueId);

                if(firstTimeSeen || aircraftSnapshot.AltitudeChanged > args.PreviousDataVersion)                aircraftJson.Altitude = aircraftSnapshot.Altitude;
                if(firstTimeSeen || aircraftSnapshot.CallsignChanged > args.PreviousDataVersion)                aircraftJson.Callsign = aircraftSnapshot.Callsign;
                if(firstTimeSeen || aircraftSnapshot.CallsignIsSuspectChanged > args.PreviousDataVersion)       aircraftJson.CallsignIsSuspect = aircraftSnapshot.CallsignIsSuspect;
                if(firstTimeSeen || aircraftSnapshot.ConstructionNumberChanged > args.PreviousDataVersion)      aircraftJson.ConstructionNumber = aircraftSnapshot.ConstructionNumber;
                if(firstTimeSeen || aircraftSnapshot.CountMessagesReceivedChanged > args.PreviousDataVersion)   aircraftJson.CountMessagesReceived = aircraftSnapshot.CountMessagesReceived;
                if(firstTimeSeen || aircraftSnapshot.DestinationChanged > args.PreviousDataVersion)             aircraftJson.Destination = aircraftSnapshot.Destination;
                if(firstTimeSeen || aircraftSnapshot.GroundSpeedChanged > args.PreviousDataVersion)             aircraftJson.GroundSpeed = Round.GroundSpeed(aircraftSnapshot.GroundSpeed);
                if(firstTimeSeen || aircraftSnapshot.EmergencyChanged > args.PreviousDataVersion)               aircraftJson.Emergency = aircraftSnapshot.Emergency;
                if(firstTimeSeen || aircraftSnapshot.EngineTypeChanged > args.PreviousDataVersion)              aircraftJson.EngineType = (int)aircraftSnapshot.EngineType;
                if(firstTimeSeen || aircraftSnapshot.FirstSeenChanged > args.PreviousDataVersion)               aircraftJson.FirstSeen = aircraftSnapshot.FirstSeen;
                if(firstTimeSeen || aircraftSnapshot.FlightsCountChanged > args.PreviousDataVersion)            aircraftJson.FlightsCount = aircraftSnapshot.FlightsCount;
                if(firstTimeSeen || aircraftSnapshot.PictureFileNameChanged > args.PreviousDataVersion)         aircraftJson.HasPicture = !String.IsNullOrEmpty(aircraftSnapshot.PictureFileName);
                if(firstTimeSeen || aircraftSnapshot.Icao24Changed > args.PreviousDataVersion)                  aircraftJson.Icao24 = aircraftSnapshot.Icao24;
                if(firstTimeSeen || aircraftSnapshot.Icao24CountryChanged > args.PreviousDataVersion)           aircraftJson.Icao24Country = aircraftSnapshot.Icao24Country;
                if(firstTimeSeen || aircraftSnapshot.Icao24InvalidChanged > args.PreviousDataVersion)           aircraftJson.Icao24Invalid = aircraftSnapshot.Icao24Invalid;
                if(firstTimeSeen || aircraftSnapshot.IsMilitaryChanged > args.PreviousDataVersion)              aircraftJson.IsMilitary = aircraftSnapshot.IsMilitary;
                if(firstTimeSeen || aircraftSnapshot.IsInterestingChanged > args.PreviousDataVersion)           aircraftJson.IsInteresting = aircraftSnapshot.IsInteresting;
                if(firstTimeSeen || aircraftSnapshot.LatitudeChanged > args.PreviousDataVersion)                aircraftJson.Latitude = Round.Coordinate(aircraftSnapshot.Latitude);
                if(firstTimeSeen || aircraftSnapshot.LongitudeChanged > args.PreviousDataVersion)               aircraftJson.Longitude = Round.Coordinate(aircraftSnapshot.Longitude);
                if(firstTimeSeen || aircraftSnapshot.ModelChanged > args.PreviousDataVersion)                   aircraftJson.Model = aircraftSnapshot.Model;
                if(firstTimeSeen || aircraftSnapshot.NumberOfEnginesChanged > args.PreviousDataVersion)         aircraftJson.NumberOfEngines = aircraftSnapshot.NumberOfEngines;
                if(firstTimeSeen || aircraftSnapshot.OnGroundChanged > args.PreviousDataVersion)                aircraftJson.OnGround = aircraftSnapshot.OnGround;
                if(firstTimeSeen || aircraftSnapshot.OperatorChanged > args.PreviousDataVersion)                aircraftJson.Operator = aircraftSnapshot.Operator;
                if(firstTimeSeen || aircraftSnapshot.OperatorIcaoChanged > args.PreviousDataVersion)            aircraftJson.OperatorIcao = aircraftSnapshot.OperatorIcao;
                if(firstTimeSeen || aircraftSnapshot.OriginChanged > args.PreviousDataVersion)                  aircraftJson.Origin = aircraftSnapshot.Origin;
                if(firstTimeSeen || aircraftSnapshot.PositionTimeChanged > args.PreviousDataVersion)            aircraftJson.PositionTime = aircraftSnapshot.PositionTime == null ? (long?)null : JavascriptHelper.ToJavascriptTicks(aircraftSnapshot.PositionTime.Value);
                if(firstTimeSeen || aircraftSnapshot.RegistrationChanged > args.PreviousDataVersion)            aircraftJson.Registration = aircraftSnapshot.Registration;
                if(firstTimeSeen || aircraftSnapshot.SpeciesChanged > args.PreviousDataVersion)                 aircraftJson.Species = (int)aircraftSnapshot.Species;
                if(firstTimeSeen || aircraftSnapshot.SpeedTypeChanged > args.PreviousDataVersion)               aircraftJson.SpeedType = (int)aircraftSnapshot.SpeedType;
                if(firstTimeSeen || aircraftSnapshot.SquawkChanged > args.PreviousDataVersion)                  aircraftJson.Squawk = String.Format("{0:0000}", aircraftSnapshot.Squawk);
                if(firstTimeSeen || aircraftSnapshot.TrackChanged > args.PreviousDataVersion)                   aircraftJson.Track = Round.Track(aircraftSnapshot.Track);
                if(firstTimeSeen || aircraftSnapshot.TypeChanged > args.PreviousDataVersion)                    aircraftJson.Type = aircraftSnapshot.Type;
                if(firstTimeSeen || aircraftSnapshot.UserTagChanged > args.PreviousDataVersion)                 aircraftJson.UserTag = aircraftSnapshot.UserTag;
                if(firstTimeSeen || aircraftSnapshot.VerticalRateChanged > args.PreviousDataVersion)            aircraftJson.VerticalRate = aircraftSnapshot.VerticalRate;
                if(firstTimeSeen || aircraftSnapshot.WakeTurbulenceCategoryChanged > args.PreviousDataVersion)  aircraftJson.WakeTurbulenceCategory = (int)aircraftSnapshot.WakeTurbulenceCategory;

                if(aircraftSnapshot.Stopovers.Count > 0 && (firstTimeSeen || aircraftSnapshot.StopoversChanged > args.PreviousDataVersion)) {
                    aircraftJson.Stopovers = new List<string>();
                    aircraftJson.Stopovers.AddRange(aircraftSnapshot.Stopovers);
                }

                aircraftJson.SecondsTracked = (long)((now - aircraftSnapshot.FirstSeen).TotalSeconds);

                if(args.ShowShortTrail) {
                    if(aircraftSnapshot.ShortCoordinates.Count > 0) {
                        BuildCoordinatesList(true, firstTimeSeen, aircraftJson, aircraftSnapshot, args);
                    }
                } else {
                    if(aircraftSnapshot.FullCoordinates.Count > 0) {
                        BuildCoordinatesList(false, firstTimeSeen, aircraftJson, aircraftSnapshot, args);
                    }
                }

                aircraftListJson.Aircraft.Add(aircraftJson);
            }
        }
        /// <summary>
        /// Builds the full or short coordinates list and attaches it to the aircraft JSON object.
        /// </summary>
        /// <param name="shortCoordinates"></param>
        /// <param name="firstTimeSeen"></param>
        /// <param name="aircraftJson"></param>
        /// <param name="aircraftSnapshot"></param>
        /// <param name="args"></param>
        private void BuildCoordinatesList(bool shortCoordinates, bool firstTimeSeen, AircraftJson aircraftJson, IAircraft aircraftSnapshot, AircraftListJsonBuilderArgs args)
        {
            aircraftJson.ResetTrail = firstTimeSeen || args.ResendTrails || aircraftSnapshot.FirstCoordinateChanged > args.PreviousDataVersion;
            List<double?> list = new List<double?>();

            Coordinate lastCoordinate = null;
            foreach(var coordindate in shortCoordinates ? aircraftSnapshot.ShortCoordinates : aircraftSnapshot.FullCoordinates) {
                if(aircraftJson.ResetTrail || coordindate.DataVersion > args.PreviousDataVersion) {
                    list.Add(Round.Coordinate(coordindate.Latitude));
                    list.Add(Round.Coordinate(coordindate.Longitude));
                    if(shortCoordinates) list.Add(JavascriptHelper.ToJavascriptTicks(coordindate.Tick));
                    else                 list.Add(Round.Track(coordindate.Heading));
                }

                lastCoordinate = coordindate;
            }

            if(aircraftSnapshot.Latitude != null && aircraftSnapshot.Longitude != null &&
               (lastCoordinate.Latitude != aircraftSnapshot.Latitude || lastCoordinate.Longitude != aircraftSnapshot.Longitude) &&
               aircraftSnapshot.PositionTimeChanged > args.PreviousDataVersion) {
                list.Add(Round.Coordinate(aircraftSnapshot.Latitude));
                list.Add(Round.Coordinate(aircraftSnapshot.Longitude));
                if(shortCoordinates) list.Add(JavascriptHelper.ToJavascriptTicks(aircraftSnapshot.PositionTime.Value));
                else                 list.Add(Round.Track(aircraftSnapshot.Track));
            }

            if(list.Count != 0) {
                if(shortCoordinates) aircraftJson.ShortCoordinates = list;
                else                 aircraftJson.FullCoordinates = list;
            }
        }