use chrono::{DateTime, Utc};
use serde::{Deserialize, Serialize};
use std::fmt;
use strum::EnumString;
use strum_macros::Display;
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WeatherConfig {
pub units: String,
pub location: Option<String>,
pub json_output: bool,
pub animation_enabled: bool,
pub detail_level: DetailLevel,
pub no_charts: bool,
}
impl Default for WeatherConfig {
fn default() -> Self {
Self {
units: "metric".to_string(),
location: None,
json_output: false,
animation_enabled: true,
detail_level: DetailLevel::Standard,
no_charts: false,
}
}
}
#[derive(
Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq, PartialOrd, Ord, Display, EnumString,
)]
pub enum DetailLevel {
#[strum(to_string = "Basic")]
Basic,
#[strum(to_string = "Standard")]
Standard,
#[strum(to_string = "Detailed")]
Detailed,
#[strum(to_string = "Debug")]
Debug,
}
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
pub enum WeatherCondition {
Clear,
Clouds,
Rain,
Drizzle,
Thunderstorm,
Snow,
Mist,
Fog,
Smoke,
Haze,
Dust,
Sand,
Ash,
Squall,
Tornado,
Unknown,
}
impl WeatherCondition {
#[allow(clippy::should_implement_trait)]
#[allow(dead_code)]
pub fn from_str(condition: &str) -> Self {
match condition.to_lowercase().as_str() {
"clear" => WeatherCondition::Clear,
"clouds" => WeatherCondition::Clouds,
"rain" => WeatherCondition::Rain,
"drizzle" => WeatherCondition::Drizzle,
"thunderstorm" => WeatherCondition::Thunderstorm,
"snow" => WeatherCondition::Snow,
"mist" => WeatherCondition::Mist,
"fog" => WeatherCondition::Fog,
"smoke" => WeatherCondition::Smoke,
"haze" => WeatherCondition::Haze,
"dust" => WeatherCondition::Dust,
"sand" => WeatherCondition::Sand,
"ash" => WeatherCondition::Ash,
"squall" => WeatherCondition::Squall,
"tornado" => WeatherCondition::Tornado,
_ => WeatherCondition::Unknown,
}
}
pub fn get_emoji(&self) -> &'static str {
match self {
WeatherCondition::Clear => "☀️",
WeatherCondition::Clouds => "☁️",
WeatherCondition::Rain => "🌧️",
WeatherCondition::Drizzle => "🌦️",
WeatherCondition::Thunderstorm => "⛈️",
WeatherCondition::Snow => "❄️",
WeatherCondition::Mist => "🌫️",
WeatherCondition::Fog => "🌫️",
WeatherCondition::Smoke => "🌫️",
WeatherCondition::Haze => "🌫️",
WeatherCondition::Dust => "🌫️",
WeatherCondition::Sand => "🌫️",
WeatherCondition::Ash => "🌫️",
WeatherCondition::Squall => "💨",
WeatherCondition::Tornado => "🌪️",
WeatherCondition::Unknown => "❓",
}
}
}
impl fmt::Display for WeatherCondition {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let s = match self {
WeatherCondition::Clear => "Clear",
WeatherCondition::Clouds => "Cloudy",
WeatherCondition::Rain => "Rainy",
WeatherCondition::Drizzle => "Drizzle",
WeatherCondition::Thunderstorm => "Thunderstorm",
WeatherCondition::Snow => "Snowy",
WeatherCondition::Mist => "Misty",
WeatherCondition::Fog => "Foggy",
WeatherCondition::Smoke => "Smoky",
WeatherCondition::Haze => "Hazy",
WeatherCondition::Dust => "Dusty",
WeatherCondition::Sand => "Sandy",
WeatherCondition::Ash => "Ashy",
WeatherCondition::Squall => "Squall",
WeatherCondition::Tornado => "Tornado",
WeatherCondition::Unknown => "Unknown",
};
write!(f, "{}", s)
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Location {
pub name: String,
pub country: String,
pub country_code: String,
pub latitude: f64,
pub longitude: f64,
pub timezone: String,
pub region: Option<String>,
pub state: Option<String>,
}
impl Default for Location {
fn default() -> Self {
Self {
name: "Unknown".to_string(),
country: "Unknown".to_string(),
country_code: "UN".to_string(),
latitude: 0.0,
longitude: 0.0,
timezone: "UTC".to_string(),
region: None,
state: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CurrentWeather {
pub timestamp: DateTime<Utc>,
pub temperature: f64,
pub feels_like: f64,
pub humidity: u8,
pub pressure: u32,
pub wind_speed: f64,
pub wind_direction: u16,
pub conditions: Vec<WeatherDescription>,
pub main_condition: WeatherCondition,
pub visibility: u32,
pub clouds: u8,
pub uv_index: f64,
pub sunrise: DateTime<Utc>,
pub sunset: DateTime<Utc>,
pub rain_last_hour: Option<f64>,
pub snow_last_hour: Option<f64>,
pub air_quality_index: Option<u8>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WeatherDescription {
pub id: u32,
pub main: String,
pub description: String,
pub icon: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HourlyForecast {
pub timestamp: DateTime<Utc>,
pub temperature: f64,
pub feels_like: f64,
pub humidity: u8,
pub pressure: u32,
pub wind_speed: f64,
pub wind_direction: u16,
pub conditions: Vec<WeatherDescription>,
pub main_condition: WeatherCondition,
pub pop: f64, pub visibility: u32,
pub clouds: u8,
pub rain: Option<f64>,
pub snow: Option<f64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DailyForecast {
pub date: DateTime<Utc>,
pub sunrise: DateTime<Utc>,
pub sunset: DateTime<Utc>,
pub temp_morning: f64,
pub temp_day: f64,
pub temp_evening: f64,
pub temp_night: f64,
pub temp_min: f64,
pub temp_max: f64,
pub feels_like_day: f64,
pub feels_like_night: f64,
pub pressure: u32,
pub humidity: u8,
pub wind_speed: f64,
pub wind_direction: u16,
pub conditions: Vec<WeatherDescription>,
pub main_condition: WeatherCondition,
pub clouds: u8,
pub pop: f64,
pub rain: Option<f64>,
pub snow: Option<f64>,
pub uv_index: f64,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Forecast {
pub current: Option<CurrentWeather>,
pub hourly: Vec<HourlyForecast>,
pub daily: Vec<DailyForecast>,
pub timezone_offset: i32,
pub units: String,
}
#[allow(dead_code)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AirQuality {
pub aqi: u8, pub co: f64, pub no: f64, pub no2: f64, pub o3: f64, pub so2: f64, pub pm2_5: f64, pub pm10: f64, pub nh3: f64, }
#[allow(dead_code)]
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct WeatherAlert {
pub sender: String,
pub event: String,
pub start: DateTime<Utc>,
pub end: DateTime<Utc>,
pub description: String,
pub tags: Vec<String>,
}