use common::CultureCode;
use client::Client;
use error::Error;
use response::Response;
use serde_qs as qs;
use std::collections::HashMap;
#[derive(Debug, Deserialize)]
pub struct Point {
pub coordinates: Vec<f64>,
}
#[derive(Debug, Deserialize, Serialize, PartialEq, Clone, Copy)]
pub enum EntityType {
Address,
Neighborhood,
PopulatedPlace,
Postcode1,
AdminDivision1,
AdminDivision2,
CountryRegion,
Lake, River, Postcode2, }
#[derive(Debug, Deserialize)]
pub struct Address {
#[serde(rename = "addressLine")]
pub address_line: Option<String>,
#[serde(rename = "neighborhood")]
pub neighborhood: Option<String>,
#[serde(rename = "locality")]
pub locality: Option<String>,
#[serde(rename = "postalCode")]
pub postal_code: Option<String>,
#[serde(rename = "adminDistrict")]
pub admin_district1: Option<String>,
#[serde(rename = "adminDistrict2")]
pub admin_district2: Option<String>,
#[serde(rename = "countryRegion")]
pub country: Option<String>,
#[serde(rename = "countryRegionIso2")]
pub country_iso: Option<String>,
#[serde(rename = "landmark")]
pub landmark: Option<String>,
#[serde(rename = "formattedAddress")]
pub formatted: Option<String>,
}
#[derive(Debug, Deserialize, PartialEq, Clone, Copy)]
pub enum Confidence {
High,
Medium,
Low,
}
#[derive(Debug, Deserialize, PartialEq, Clone, Copy)]
pub enum MatchCode {
Good,
Ambiguous,
UpHierarchy,
}
#[derive(Default, Serialize)]
pub struct FindPoint {
pub point: String,
pub include_entity_types: Vec<EntityType>,
pub include_neighborhood: bool,
pub include_ciso2: bool,
}
impl FindPoint {
pub fn from_latlng(lat: f64, lng: f64) -> FindPoint {
let mut params = FindPoint::default();
params.point = format!("{:.5},{:.5}", lat, lng);
params
}
pub fn from_str(latlng: &str) -> FindPoint {
let mut params = FindPoint::default();
params.point = latlng.to_owned();
params
}
}
#[derive(Default, Serialize)]
pub struct ContextParams {
pub culture: Option<CultureCode>,
pub user_map_view: Option<Vec<f64>>,
pub user_location: Option<Vec<f64>>,
pub user_ip: Option<String>,
pub user_region: Option<String>,
}
#[derive(Debug, Deserialize)]
pub struct Location {
pub name: String,
pub point: Point,
pub bbox: Vec<f64>,
#[serde(rename = "entityType")]
pub entity_type: EntityType,
pub address: Address,
pub confidence: Confidence,
#[serde(rename = "matchCodes")]
pub match_codes: Vec<MatchCode>,
}
impl Location {
pub fn find_by_point(client: &Client, find: FindPoint, opts: Option<ContextParams>) -> Result<Vec<Location>, Error> {
let path = format!("/Locations/{}", find.point);
let entity_types: String;
let culture: String;
let user_map_view: String;
let user_location: String;
let mut params = HashMap::<&str, &str>::new();
if find.include_entity_types.len() > 0 {
let types: Vec<String> = find.include_entity_types.iter().map(|el| format!("{:?}", el)).collect();
entity_types = types.join(",");
params.insert("include_entity_types", &entity_types);
}
if find.include_neighborhood {
params.insert("inclnb", "1");
}
if find.include_ciso2 {
params.insert("incl", "ciso2");
}
if let Some(ref ctx) = opts {
if let Some(ref c) = ctx.culture {
culture = qs::to_string(&c).map_err(|err| Error::from(err))?;
params.insert("c", &culture);
}
if let Some(ref umv) = ctx.user_map_view {
user_map_view = umv.iter().map(|n| n.to_string()).collect::<Vec<String>>().join(",");
params.insert("umv", &user_map_view);
}
if let Some(ref ul) = ctx.user_location {
user_location = ul.iter().map(|n| n.to_string()).collect::<Vec<String>>().join(",");
params.insert("ul", &user_location);
}
if let Some(ref uip) = ctx.user_ip { params.insert("uip", &uip); }
if let Some(ref ur) = ctx.user_region { params.insert("ur", &ur); }
}
let response: Response<Location> = client.get(&path, &mut params)?;
let resource_set = response.resource_sets.into_iter().next();
if let Some(set) = resource_set {
Ok(set.resources)
} else {
Ok(Vec::new())
}
}
pub fn find_by_query(client: &Client, query: &str, opts: Option<ContextParams>) -> Result<Vec<Location>, Error> {
let culture: String;
let user_map_view: String;
let user_location: String;
let mut params = HashMap::new();
params.insert("q", query);
if let Some(ref ctx) = opts {
if let Some(ref c) = ctx.culture {
culture = qs::to_string(&c).map_err(|err| Error::from(err))?;
params.insert("c", &culture);
}
if let Some(ref umv) = ctx.user_map_view {
user_map_view = umv.iter().map(|n| n.to_string()).collect::<Vec<String>>().join(",");
params.insert("umv", &user_map_view);
}
if let Some(ref ul) = ctx.user_location {
user_location = ul.iter().map(|n| n.to_string()).collect::<Vec<String>>().join(",");
params.insert("ul", &user_location);
}
if let Some(ref uip) = ctx.user_ip { params.insert("uip", &uip); }
if let Some(ref ur) = ctx.user_region { params.insert("ur", &ur); }
}
let response: Response<Location> = client.get("/Locations", &mut params)?;
let resource_set = response.resource_sets.into_iter().next();
if let Some(set) = resource_set {
Ok(set.resources)
} else {
Ok(Vec::new())
}
}
}