1use std::{str::FromStr, sync::OnceLock};
2
3use regex::Regex;
4
5use crate::dexcom::consts;
6
7use super::trends::TrendData;
8
9static TIMEDATE_REGEX: OnceLock<Regex> = OnceLock::new();
10
11#[derive(Debug, Clone)]
12pub struct GlucoseReading<'a> {
13    pub mg_dl: u16,
14    pub mmol_l: f32,
15    pub trend: TrendData<'a>,
16    pub datetime: String,
17}
18
19impl GlucoseReading<'_> {
20    pub fn new<'a>(
21        mg_dl: u16,
22        trend: TrendData<'a>,
23        datetime: String,
24    ) -> Result<GlucoseReading<'a>, &'a str> {
25        let time_regex = TIMEDATE_REGEX.get_or_init(|| {
26            Regex::new(r"Date\((?P<timestamp>\d+)(?P<timezone>[+-]\d{4})\)").unwrap()
27        });
28
29        match time_regex.captures(&datetime) {
30            Some(c) => {
31                let seconds = c
33                    .name("timestamp")
34                    .unwrap()
35                    .as_str()
36                    .parse::<i64>()
37                    .unwrap()
38                    / 1000;
39
40                let timezone = c.name("timezone").unwrap().as_str();
42
43                let timestamp = chrono::DateTime::from_timestamp(seconds, 0).unwrap();
45
46                Ok(GlucoseReading {
47                    mg_dl,
48                    mmol_l: format!("{:.1}", mg_dl as f32 * consts::MMOL_CONVERSION_FACTOR) .parse() .unwrap(), trend,
52                    datetime: timestamp
53                        .with_timezone(&chrono::FixedOffset::from_str(timezone).unwrap())
54                        .format("%Y-%m-%dT%H:%M:%S%Z")
55                        .to_string(), })
57            }
58            None => Err("invalid datetime format"),
59        }
60    }
61}