using Adrenak.Unex; using System; using RestSharp; using System.Text; using System.Threading.Tasks; using UnityEngine; namespace Adrenak.UniMap { public class TextSearchRequest { const string k_BaseURL = "https://maps.googleapis.com/maps/api/place/textsearch/json?"; /// /// The Google Maps API key /// public string key; /// /// The query for the search. Eg. "Restaurants in Sydney" /// public string query; /// /// Region from where the results are preferred. This is not a hard filter. Uses ccTLD naming. /// See https://www.ionos.com/digitalguide/domains/domain-extensions/cctlds-a-list-of-every-country-domain/ /// public string region; /// /// The location around which the search is to be done. /// public Location location; /// /// Search distance (in metres) from the given location. Maximum value is 50000 /// public int radius = -1; /// /// The language in which the results are to be returned. Uses ISO naming. /// public string language; /// /// The minimum price level of the results returned /// public PriceLevel minPriceLevel = PriceLevel.Undefined; /// /// The maximum price level of the results return /// public PriceLevel maxPriceLevel = PriceLevel.Undefined; /// /// When set to true, makes sure that only the places that are currently opened are returned /// public bool isOpenNow; /// /// Restricts the results to a particular type of place /// public PlaceType type; // ================================================ // PUBLIC METHODS // ================================================ public TextSearchRequest(string key) { this.key = key; } /// /// Gets the request URL for the set parameters /// public string GetURL() { if (string.IsNullOrEmpty(key)) throw new Exception("Key cannot be null or empty"); if (string.IsNullOrEmpty(query)) throw new Exception("Query cannot be null or empty"); if (radius > 50000) throw new Exception("Radius cannot be larger than 50000"); var sb = new StringBuilder(k_BaseURL) .Append("key=").Append(key) .Append("&query=").Append(query); if (!string.IsNullOrEmpty(region)) sb.Append("®ion=").Append(region); if (location != null) sb.Append("&location=").Append(location.lat).Append(",").Append(location.lng); if (radius >= 0) sb.Append("&radius=").Append(radius); if (!string.IsNullOrEmpty(language)) sb.Append("&language=").Append(language); if (minPriceLevel != PriceLevel.Undefined) sb.Append("&minprice=").Append(minPriceLevel); if (maxPriceLevel != PriceLevel.Undefined) sb.Append("&maxprice=").Append(maxPriceLevel); if (isOpenNow) sb.Append("&opennow"); if (type != PlaceType.Undefined) sb.Append("&type=").Append(EnumToString.From(type)); return sb.ToString(); } /// /// Send the API request and returns the response or exception /// /// The query for the search /// The radius from the location within which the results should be returned /// Action that returns the response as a c# object /// Action that returns the exception encountered in case of an error public void Send(string query, int radius, Action onResponse, Action onException) { string url = string.Empty; try { url = GetURL(); } catch (Exception e) { onException(e); } var client = new RestClient(); var request = new RestRequest(url, Method.GET); client.ExecuteAsync(request, response => { Dispatcher.Enqueue(() => { if (response.IsSuccessful()) { try { var result = JsonUtility.FromJson(response.Content); onResponse?.Invoke(result); } catch (Exception e) { onException?.Invoke(e); } } else onException?.Invoke(response.GetException()); }); }); } /// /// Sends the API request and returns a task for the response /// /// The query for the search /// The radius from the location within which the results should be returned public Task Send(string query, int radius) { var promise = new TaskCompletionSource(); Send( query, radius, result => promise.SetResult(result), exception => promise.SetException(exception) ); return promise.Task; } } }