use std::fmt;
use serde::{Deserialize, Serialize};
use sqlx::FromRow;
use thiserror::Error;
use crate::cache::Cache;
pub(crate) mod from_ip;
pub(crate) mod from_postal_code;
use crate::api::Fetchable;
#[derive(Error, Debug, PartialEq)]
pub enum ParseCoordinatesError {
#[error("provided postal code was not found")]
UnknownLocation(String),
}
#[derive(FromRow, Clone, Debug, Default, PartialEq, Deserialize, Serialize)]
pub struct Location {
pub loc: String,
pub latitude: String,
pub longitude: String,
pub postal_code: String,
}
impl fmt::Display for Location {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(
fmt,
"Coordinates: {}\n Postal Code: {}",
self.loc, self.postal_code,
)
}
}
pub async fn get(
cache: &mut Cache,
region: Option<&str>,
) -> eyre::Result<Location> {
let Some(region) = region else {
let location = from_ip::Client::new().fetch()?;
cache.set(&location).await?;
return Ok(location);
};
let Some(location) = cache.get(region).await? else {
let location = from_postal_code::Client::new(region)?.fetch()?;
cache.set(&location).await?;
return Ok(location);
};
Ok(location)
}