/// <summary>
        /// Searches WURFL device data using the given WURFL device id for detection.
        /// Throws WmClientException in case any client related problem occurs.
        /// </summary>
        /// <param name="wurflID"></param>
        /// <returns>device data detected using the given WURFL ID</returns>
        public JSONDeviceData LookupDeviceID(string wurflID)
        {
            JSONDeviceData device = null;

            // First, do a cache lookup
            if (devIdCache != null)
            {
                device = devIdCache.GetEntry(wurflID);
                if (device != null)
                {
                    return(device);
                }
            }



            // No device found in cache, let's try a server lookup
            Request req = new Request();

            req.Wurfl_id = wurflID;

            device = internalLookup(req, "/v2/lookupdeviceid/json");
            // check if cache must be cleared before adding device to it
            ClearCachesIfNeeded(device.Ltime);
            SafePutDevice(devIdCache, wurflID, device);

            return(device);
        }
        /// <summary>
        /// Searches WURFL device data using the given user-agent for detection.
        /// Throws WmClientException in case any client related problem occurs.
        /// </summary>
        /// <param name="userAgent">
        /// A user-agent string
        /// </param>
        /// <returns>device data detected using the given user agent</returns>
        public JSONDeviceData LookupUserAgent(string userAgent)
        {
            JSONDeviceData device = null;

            // First, do a cache lookup
            if (uaCache != null)
            {
                device = uaCache.GetEntry(userAgent);
                if (device != null)
                {
                    // Console.WriteLine(device.Capabilities["device_id"]);
                    return(device);
                }
            }

            // Cache does not contain device, try a server lookup
            Request req = new Request();

            addCapabilitiesToRequest(req);

            req.Lookup_headers.Add(UserAgentHeaderName, userAgent);

            HttpResponseMessage response = null;

            try
            {
                response = c.PostAsJsonAsync <Request>(createURL("/v2/lookupuseragent/json"), req).Result;
                if (response != null && response.IsSuccessStatusCode && response.Content != null)
                {
                    device = response.Content.ReadAsAsync <JSONDeviceData>().Result;
                    // Check if cache must be cleared before adding to it
                    ClearCachesIfNeeded(device.Ltime);
                    SafePutDevice(uaCache, userAgent, device);
                }
                return(device);
            }
            catch (Exception e)
            {
                throw new WmException("Error retrieving device data: " + e.Message, e);
            }
            finally
            {
                if (response != null)
                {
                    response.Dispose();
                }
            }
        }
        // Performs server lookup POSTs. It does not use cache, it must be done by caller methods.
        private JSONDeviceData internalLookup(Request req, string routePath)
        {
            JSONDeviceData device = null;

            addCapabilitiesToRequest(req);

            HttpResponseMessage response = null;

            try
            {
                response = c.PostAsJsonAsync <Request>(createURL(routePath), req).Result;
                if (response != null && response.IsSuccessStatusCode && response.Content != null)
                {
                    device = response.Content.ReadAsAsync <JSONDeviceData>().Result;
                    if (device.Error != null && device.Error.Length > 0)
                    {
                        throw new WmException("Received error from WM server: " + device.Error);
                    }
                }
            }
            catch (Exception e)
            {
                if (e is WmException)
                {
                    throw e;
                }
                throw new WmException("Error retrieving device data: " + e.Message, e);
            }
            finally
            {
                if (response != null)
                {
                    response.Dispose();
                }
            }

            return(device);
        }
 private void SafePutDevice(LRUCache <String, JSONDeviceData> cache, String key, JSONDeviceData device)
 {
     if (cache != null)
     {
         cache.PutEntry(key, device);
     }
 }
        /// <summary>
        /// Searches WURFL device data using the given header dictionary for detection.
        /// Header names used as dictionary keys are treated as case insensitive so that
        /// "user-Agent" and "User-Agent" are considered equal.
        /// Throws WmClientException in case any client related problem occurs.
        /// </summary>
        /// <param name="headers"></param>
        /// <returns>A JSONDeviceData object holding all the device detection information or the requested one in case one of the SetRequired*Capabilities method has been used on the client</returns>
        /// <exception cref="WmException"></exception>
        public JSONDeviceData LookupHeaders(IDictionary <String, String> headers)
        {
            JSONDeviceData device = null;

            // Before we begin, let's handle lowercase key headers
            IDictionary <string, string> lowercaseHeaders = ToLowercaseHeaders(headers);

            Request req = new Request();

            if (lowercaseHeaders != null)
            {
                for (int i = 0; i < ImportantHeaders.Length; i++)
                {
                    String name     = ImportantHeaders[i];
                    String lowerKey = name.ToLower();
                    if (lowercaseHeaders.ContainsKey(lowerKey))
                    {
                        String header = lowercaseHeaders[lowerKey];
                        if (header != null && !"".Equals(header))
                        {
                            req.Lookup_headers.Add(name, header);
                        }
                    }
                }
            }

            // Device, not found in cache, let's try a server lookup
            addCapabilitiesToRequest(req);

            // First, do a cache lookup
            var cacheKey = GetHeadersCacheKey(req.Lookup_headers);

            if (uaCache != null)
            {
                device = uaCache.GetEntry(cacheKey);
                if (device != null)
                {
                    return(device);
                }
            }

            HttpResponseMessage response = null;

            try
            {
                response = c.PostAsJsonAsync <Request>(createURL("/v2/lookuprequest/json"), req).Result;
                if (response != null && response.IsSuccessStatusCode && response.Content != null)
                {
                    device = response.Content.ReadAsAsync <JSONDeviceData>().Result;
                    if (device.Error != null && device.Error.Length > 0)
                    {
                        throw new WmException("Received error from WM server: " + device.Error);
                    }
                }

                // Check if cache must be cleaned before adding device to cache
                ClearCachesIfNeeded(device.Ltime);
                SafePutDevice(uaCache, cacheKey, device);

                return(device);
            }
            catch (Exception e)
            {
                if (e is WmException)
                {
                    throw e;
                }
                throw new WmException("Error retrieving device data: " + e.Message, e);
            }
            finally
            {
                if (response != null)
                {
                    response.Dispose();
                }
            }
        }
        public JSONDeviceData LookupRequest(HttpRequest request)
#endif

        {
            JSONDeviceData device = null;

            // First, do a cache lookup
#if (NETCOREAPP3_1 || NET5_0)
            var cacheKey = GetUserAgentCacheKey(request.Headers); // here it's a IHeaderDictionary
#else
            var cacheKey = GetUserAgentCacheKey(request.Headers);
#endif
            if (uaCache != null)
            {
                device = uaCache.GetEntry(cacheKey);
                if (device != null)
                {
                    return(device);
                }
            }

            // Device, not found in cache, let's try a server lookup
            Request req = new Request();
            addCapabilitiesToRequest(req);

            if (request.Headers != null)
            {
                for (int i = 0; i < ImportantHeaders.Length; i++)
                {
                    String name   = ImportantHeaders[i];
                    String header = request.Headers[name];

                    if (header != null && !"".Equals(header))
                    {
                        req.Lookup_headers.Add(name, header);
                    }
                }
            }

            HttpResponseMessage response = null;
            try
            {
                response = c.PostAsJsonAsync <Request>(createURL("/v2/lookuprequest/json"), req).Result;
                if (response != null && response.IsSuccessStatusCode && response.Content != null)
                {
                    device = response.Content.ReadAsAsync <JSONDeviceData>().Result;
                    if (device.Error != null && device.Error.Length > 0)
                    {
                        throw new WmException("Received error from WM server: " + device.Error);
                    }
                }

                // Check if cache must be cleaned before adding device to cache
                ClearCachesIfNeeded(device.Ltime);
                SafePutDevice(uaCache, cacheKey, device);

                return(device);
            }
            catch (Exception e)
            {
                if (e is WmException)
                {
                    throw e;
                }
                throw new WmException("Error retrieving device data: " + e.Message, e);
            }
            finally
            {
                if (response != null)
                {
                    response.Dispose();
                }
            }
        }