private Country ParseCountry(IReadOnlyList <string> tokens)
        {
            var regex = new Regex(@"^\d{4}[NS] \d{5}[EW]$");

            var countryId = tokens[1];

            var posToken = tokens.FirstOrDefault(regex.IsMatch);

            var lat = PositionParser.ParseLatitude(posToken);
            var lng = PositionParser.ParseLongitude(posToken);

            if (countryId.Length != 2)
            {
                EmitWarn($"Country with invalid UN/LOCODE found: {countryId}");
            }

            var country = new Country
            {
                Id   = countryId,
                Name = tokens[3].Trim('.')
            };

            if (lat != null && lng != null)
            {
                var position = new Position
                {
                    Lat = lat.Value,
                    Lng = lng.Value
                };

                country.Position = position;
            }

            return(country);
        }
        public Location Parse(string source, out string message)
        {
            message = null;

            var tokens = ExtractTokens(source);

            if (string.IsNullOrWhiteSpace(tokens[2]) && string.IsNullOrWhiteSpace(tokens[6]))
            {
                return(null); // This is a country.
            }
            var regex = new Regex(@"^\d{4}[NS] \d{5}[EW]$");

            var countryId     = tokens[1];
            var locationId    = countryId + tokens[2];
            var functions     = ParseFunction(tokens[6]);
            var changeReason  = ParseChangeReason(tokens[0], out message);
            var changeDetails = ParseChangeDetails(tokens[11], out var remarks);

            var posToken = tokens.FirstOrDefault(regex.IsMatch);

            var lat = PositionParser.ParseLatitude(posToken);
            var lng = PositionParser.ParseLongitude(posToken);

            if (locationId.Length != 5)
            {
                message = $"Location with invalid UN/LOCODE found: {locationId}";
            }

            var location = new Location
            {
                UNLOC         = locationId,
                CountryId     = countryId,
                Name          = tokens[3],
                SpellingName  = tokens[4],
                Functions     = functions,
                ChangeReason  = changeReason,
                ChangeDetails = changeDetails,
                Remarks       = remarks
            };

            if (lat != null && lng != null)
            {
                var position = new Position
                {
                    Lat = lat.Value,
                    Lng = lng.Value
                };

                location.Position = position;
            }

            return(location);
        }