1use std::fmt::Display;
2use chrono::{DateTime, TimeZone, Timelike};
3
4use super::BaseApi;
5use crate::{Client, Query, Language, Forecast};
6
7
8pub struct ForecastApi<'a, Tz: TimeZone>
9where
10 Tz::Offset: Display
11{
12 client: &'a Client,
13 query: Option<Query>,
14 days: Option<u8>,
15 dt: Option<DateTime<Tz>>,
16 hour: bool,
17 alerts: bool,
18 aqi: bool,
19 lang: Option<Language>
20}
21
22impl<'a, Tz: TimeZone> ForecastApi<'a, Tz>
23where
24 Tz::Offset: Display,
25{
26 /// Use [`crate::Client`]
27 pub fn new(client: &'a Client) -> Self {
28 Self {
29 client,
30 query: None,
31 days: None,
32 dt: None,
33 hour: false,
34 alerts: false,
35 aqi: false,
36 lang: None
37 }
38 }
39
40 /// Set up the query
41 ///
42 /// Query parameter based on which data is sent back
43 pub fn query(mut self, query: Query) -> Self {
44 self.query = Some(query);
45 self
46 }
47
48 /// Set up a days
49 ///
50 /// Days parameter value ranges between 1 and 14. e.g: days=5
51 ///
52 /// If no days parameter is provided then only today's weather is returned.
53 pub fn days(mut self, days: u8) -> Self {
54 self.days = Some(days);
55 self
56 }
57
58 /// Set up a datetime
59 ///
60 /// `dt` should be between today and next 14 day
61 pub fn dt(mut self, dt: DateTime<Tz>) -> Self {
62 self.dt = Some(dt);
63 self
64 }
65
66 /// Set up use hour
67 ///
68 /// Time is extracted from dt
69 pub fn hour(mut self) -> Self {
70 self.hour = true;
71 self
72 }
73
74 /// Set up alerts
75 pub fn alerts(mut self) -> Self {
76 self.alerts = true;
77 self
78 }
79
80 /// Set up Air Quality Data
81 ///
82 /// Air quality data is not passed by default.
83 pub fn aqi(mut self) -> Self {
84 self.aqi = true;
85 self
86 }
87
88 /// Set up language
89 ///
90 /// `condition:text` field in API in the desired language
91 pub fn lang(mut self, lang: Language) -> Self {
92 self.lang = Some(lang);
93 self
94 }
95}
96
97impl<'a, Tz: TimeZone> BaseApi<'a> for ForecastApi<'a, Tz>
98where
99 Tz::Offset: Display,
100{
101 type Model = Forecast;
102
103 fn path(&self) -> &str {
104 "forecast"
105 }
106
107 fn client(&self) -> &'a Client {
108 self.client
109 }
110
111 fn params(&self) -> Vec<(&str, String)> {
112 let query = self.query.as_ref().unwrap();
113 let dt = self.dt.as_ref().unwrap();
114
115 let mut params = vec![
116 ("key", self.client.api_key.clone()), ("q", query.to_string()), ("dt", format!("{}", dt.format("%Y-%m-%d"))),
117 ("alerts", if self.alerts { "yes".to_string() } else { "no".to_string() }),
118 ("aqi", if self.aqi { "yes".to_string() } else { "no".to_string() })
119 ];
120
121 if let Some(days) = self.days {
122 params.push(("days", days.to_string()))
123 }
124
125 if self.hour {
126 params.push(("hour", dt.hour().to_string()))
127 }
128
129 if let Some(lang) = &self.lang {
130 params.push(("lang", lang.to_string()))
131 }
132
133 params
134 }
135}
136