using Adrenak.Unex; using System.Text; using System.Threading.Tasks; using System; using UnityEngine; using RestSharp; // NOTE: The "name" key in the URL is left out as Google recommends using the key "keyword" namespace Adrenak.UniMap { public class NearbySearchRequest { /// /// Lists the different ways in which the result can be listed /// public enum RankBy { Prominence, Distance } public const string k_BaseURL = "https://maps.googleapis.com/maps/api/place/nearbysearch/json?"; /// /// The Google Maps API key /// public string Key { get; private set; } /// /// The object that represents the coordinates around which the nearby places should be searched for. /// public Location Location { get; private set; } /// /// The radius (in metres) around the location that should be searched for nearby places /// public int radius = 50; /// /// The minimum price level of the results returned /// public PriceLevel minPriceLevel = PriceLevel.VeryLow; /// /// The maximum price level of the results returned /// public PriceLevel maxPriceLevel = PriceLevel.VeryHigh; /// /// Keyword that should be associated with the nearby places (Recommended over /// including but not limited to name, type, and address, as well as customer reviews and other third-party content /// public string keyword; /// /// The language in which the returls are returned /// public string language; /// /// If trye the results only include the places that are currently opened /// public bool isOpenNow; /// /// Specifies the oerder in which the results are listed. /// public RankBy rankBy = RankBy.Prominence; /// /// The type of the places returned in the results. See /// public PlaceType type = PlaceType.Undefined; // ================================================ // PUBLIC METHODS // ================================================ public NearbySearchRequest(string key) { 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 (Location == null) throw new Exception("Location cannot be null"); var sb = new StringBuilder(k_BaseURL); // Add the parameters that are gaurunteed a value sb.Append("key=").Append(Key) .Append("&location=").Append(Location.lat).Append(",").Append(Location.lng) .Append("&radius=").Append(radius) .Append("&minprice=").Append(minPriceLevel) .Append("&maxprice=").Append(maxPriceLevel) .Append("&rankby=").Append(RankByToString(rankBy)); // Check and add the other parameters if (!string.IsNullOrEmpty(keyword)) sb.Append("&keyword=").Append(keyword); if (!string.IsNullOrEmpty(language)) sb.Append("&language=").Append(language); if (type != PlaceType.Undefined) sb.Append("&type=").Append(EnumToString.From(type)); if (isOpenNow) sb.Append("&opennow"); return sb.ToString(); } /// /// Send the API request and returns the response or exception /// /// public void Send(Location location, Action onResult, Action onException) { Location = location; 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 obj = JsonUtility.FromJson(response.Content); onResult?.Invoke(obj); } catch (Exception e) { onException?.Invoke(e); } } else onException?.Invoke(response.GetException()); }); }); } /// /// Send the API request and return a task for the response /// public Task Send(Location location) { var source = new TaskCompletionSource(); Send( location, result => source.SetResult(result), exception => source.SetException(exception) ); return source.Task; } // ================================================ // INNER METHODS // ================================================ string RankByToString(RankBy rankBy) { switch (rankBy) { case RankBy.Distance: return "distance"; case RankBy.Prominence: return "prominence"; default: return "prominence"; } } } }