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;
}
}
}