/// <summary>
        /// Tries to retrieve the geolocation information online.
        /// </summary>
        /// <returns>The retrieved geolocation information if successful, otherwise <c>null</c>.</returns>
        private GeoInformation TryRetrieveOnline()
        {
            try
            {
                HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://tools.keycdn.com/geo.json");
                request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0";
                request.Proxy     = null;
                request.Timeout   = 15000;

                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    using (Stream dataStream = response.GetResponseStream())
                    {
                        var geoInfo = JsonHelper.Deserialize <GeoResponse>(dataStream);

                        GeoInformation g = new GeoInformation
                        {
                            IPv4Address = geoInfo.Data.Geo.Ip,
                            Country     = geoInfo.Data.Geo.CountryName,
                            CountryCode = geoInfo.Data.Geo.CountryCode,
                            Timezone    = geoInfo.Data.Geo.Timezone,
                            Asn         = geoInfo.Data.Geo.Asn.ToString(),
                            Isp         = geoInfo.Data.Geo.Isp
                        };

                        return(g);
                    }
                }
            }
            catch (Exception)
            {
                return(null);
            }
        }
        /// <summary>
        /// Gets the IP geolocation information, either cached or freshly retrieved if more than <see cref="MINIMUM_VALID_TIME"/> minutes have passed.
        /// </summary>
        /// <returns>The latest IP geolocation information.</returns>
        public static GeoInformation GetGeoInformation()
        {
            var passedTime = new TimeSpan(DateTime.UtcNow.Ticks - _lastSuccessfulLocation.Ticks);

            if (_geoInformation == null || passedTime.TotalMinutes > MINIMUM_VALID_TIME)
            {
                _geoInformation         = Retriever.Retrieve();
                _lastSuccessfulLocation = DateTime.UtcNow;
            }

            return(_geoInformation);
        }
        /// <summary>
        /// Tries to retrieve the geolocation information online.
        /// </summary>
        /// <returns>The retrieved geolocation information if successful, otherwise <c>null</c>.</returns>
        private GeoInformation TryRetrieveOnline()
        {
            try
            {
                DataContractJsonSerializer jsonSerializer = new DataContractJsonSerializer(typeof(GeoResponse));

                HttpWebRequest request = (HttpWebRequest)WebRequest.Create("https://tools.keycdn.com/geo.json");
                request.UserAgent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0";
                request.Proxy     = null;
                request.Timeout   = 10000;

                using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
                {
                    using (Stream dataStream = response.GetResponseStream())
                    {
                        using (StreamReader reader = new StreamReader(dataStream))
                        {
                            string responseString = reader.ReadToEnd();

                            using (MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(responseString)))
                            {
                                var geoInfo = (GeoResponse)jsonSerializer.ReadObject(ms);

                                GeoInformation g = new GeoInformation
                                {
                                    IpAddress   = geoInfo.Data.Geo.Ip,
                                    Country     = geoInfo.Data.Geo.CountryName,
                                    CountryCode = geoInfo.Data.Geo.CountryCode,
                                    Timezone    = geoInfo.Data.Geo.Timezone,
                                    Asn         = geoInfo.Data.Geo.Asn.ToString(),
                                    Isp         = geoInfo.Data.Geo.Isp
                                };

                                return(g);
                            }
                        }
                    }
                }
            }
            catch
            {
                return(null);
            }
        }
        /// <summary>
        /// Tries to retrieve the geolocation information locally.
        /// </summary>
        /// <returns>The retrieved geolocation information if successful, otherwise <c>null</c>.</returns>
        private GeoInformation TryRetrieveLocally()
        {
            try
            {
                GeoInformation g = new GeoInformation();

                // use local information
                var cultureInfo = CultureInfo.CurrentUICulture;
                var region      = new RegionInfo(cultureInfo.LCID);

                g.Country     = region.DisplayName;
                g.CountryCode = region.TwoLetterISORegionName;
                g.Timezone    = DateTimeHelper.GetLocalTimeZone();

                return(g);
            }
            catch (Exception)
            {
                return(null);
            }
        }