pub mod prelude {
    pub use {
        crate::bus::bus_arrival::{BusArrivalResp, NextBus, BusArrivalRespRaw},
        crate::bus::bus_routes::{BusRoute, BusRouteResp},
        crate::bus::bus_services::{BusFreq, BusService, BusServiceResp},
        crate::bus::bus_stops::{BusStop, BusStopsResp},
    };
}
pub mod bus_arrival {
    use serde::{Deserialize, Serialize};
    use time::{serde::iso8601, serde::timestamp, OffsetDateTime};
    use crate::bus_enums::{BusFeature, BusLoad, BusType, Operator};
    use crate::utils::de::{from_str, treat_error_as_none};
    #[cfg(feature = "fastfloat")]
    use crate::utils::de::from_str_fast_float;
    #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
    #[serde(rename_all = "PascalCase")]
    pub struct RawArrivalBusService {
        pub service_no: String,
        pub operator: Operator,
        #[serde(deserialize_with = "treat_error_as_none")]
        pub next_bus: Option<NextBusRaw>,
        #[serde(deserialize_with = "treat_error_as_none")]
        pub next_bus_2: Option<NextBusRaw>,
        #[serde(deserialize_with = "treat_error_as_none")]
        pub next_bus_3: Option<NextBusRaw>,
    }
    #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
    pub struct ArrivalBusService {
        pub service_no: String,
        pub operator: Operator,
        pub next_bus: [Option<NextBus>; 3],
    }
    impl From<RawArrivalBusService> for ArrivalBusService {
        fn from(data: RawArrivalBusService) -> Self {
            Self {
                service_no: data.service_no,
                operator: data.operator,
                next_bus: [
                    data.next_bus.map(Into::into),
                    data.next_bus_2.map(Into::into),
                    data.next_bus_3.map(Into::into),
                ],
            }
        }
    }
    #[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize, Serialize)]
    #[serde(rename_all = "PascalCase")]
    pub struct NextBusRaw {
        #[serde(deserialize_with = "from_str")]
        pub origin_code: u32,
        #[serde(deserialize_with = "from_str", rename = "DestinationCode")]
        pub dest_code: u32,
        #[serde(
            rename = "EstimatedArrival",
            deserialize_with = "iso8601::deserialize",
            serialize_with = "iso8601::serialize"
        )]
        pub est_arrival: OffsetDateTime,
        #[serde(rename = "Latitude")]
        #[cfg_attr(not(feature = "fastfloat"), serde(deserialize_with = "from_str"))]
        #[cfg_attr(feature = "fastfloat", serde(deserialize_with = "from_str_fast_float"))]
        pub lat: f64,
        #[serde(rename = "Longitude")]
        #[cfg_attr(not(feature = "fastfloat"), serde(deserialize_with = "from_str"))]
        #[cfg_attr(feature = "fastfloat", serde(deserialize_with = "from_str_fast_float"))]
        pub long: f64,
        #[serde(deserialize_with = "from_str", rename = "VisitNumber")]
        pub visit_no: u8,
        pub load: BusLoad,
        pub feature: BusFeature,
        #[serde(alias = "Type")]
        pub bus_type: BusType,
    }
    #[derive(Debug, Clone, PartialEq, PartialOrd, Deserialize, Serialize)]
    pub struct NextBus {
        pub origin_code: u32,
        pub dest_code: u32,
        #[serde(with = "timestamp")]
        pub est_arrival: OffsetDateTime,
        pub lat: f64,
        pub long: f64,
        pub visit_no: u8,
        pub load: BusLoad,
        pub feature: BusFeature,
        pub bus_type: BusType,
    }
    impl From<NextBusRaw> for NextBus {
        #[inline(always)]
        fn from(r: NextBusRaw) -> Self {
            Self {
                origin_code: r.origin_code,
                dest_code: r.dest_code,
                est_arrival: r.est_arrival,
                lat: r.lat,
                long: r.long,
                visit_no: r.visit_no,
                load: r.load,
                feature: r.feature,
                bus_type: r.bus_type,
            }
        }
    }
    #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
    #[serde(rename_all = "PascalCase")]
    pub struct BusArrivalRespRaw {
        #[serde(deserialize_with = "from_str")]
        pub bus_stop_code: u32,
        pub services: Vec<RawArrivalBusService>,
    }
    #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
    pub struct BusArrivalResp {
        pub bus_stop_code: u32,
        pub services: Vec<ArrivalBusService>,
    }
    impl From<BusArrivalRespRaw> for BusArrivalResp {
        fn from(data: BusArrivalRespRaw) -> Self {
            Self {
                bus_stop_code: data.bus_stop_code,
                services: data.services.into_iter().map(|v| v.into()).collect(),
            }
        }
    }
}
pub mod bus_services {
    use std::num::NonZeroU8;
    use crate::bus_enums::{BusCategory, Operator};
    use crate::utils::de::from_str_error_as_none;
    use crate::utils::regex::BUS_FREQ_RE;
    use serde::{Deserialize, Deserializer, Serialize};
    #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
    pub struct BusFreq {
        pub min: Option<NonZeroU8>,
        pub max: Option<NonZeroU8>,
    }
    impl BusFreq {
        pub fn new(min: u8, max: u8) -> Self {
            BusFreq {
                min: Some(NonZeroU8::new(min).unwrap()),
                max: Some(NonZeroU8::new(max).unwrap()),
            }
        }
        pub fn no_max(min: u8) -> Self {
            BusFreq {
                min: Some(NonZeroU8::new(min).unwrap()),
                max: None,
            }
        }
        pub fn no_timing() -> Self {
            BusFreq {
                min: None,
                max: None,
            }
        }
    }
    impl Default for BusFreq {
        fn default() -> Self {
            BusFreq::new(0, 0)
        }
    }
    #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
    #[serde(rename_all = "PascalCase")]
    pub struct BusServiceRaw {
        pub service_no: String,
        pub operator: Operator,
        #[serde(alias = "Direction")]
        pub no_direction: u8,
        pub category: BusCategory,
        #[serde(deserialize_with = "from_str_error_as_none")]
        pub origin_code: Option<NonZeroU8>,
        #[serde(deserialize_with = "from_str_error_as_none", alias = "DestinationCode")]
        pub dest_code: Option<NonZeroU8>,
        #[serde(alias = "AM_Peak_Freq", deserialize_with = "from_str_to_bus_freq")]
        pub am_peak_freq: BusFreq,
        #[serde(alias = "AM_Offpeak_Freq", deserialize_with = "from_str_to_bus_freq")]
        pub am_offpeak_freq: BusFreq,
        #[serde(alias = "PM_Peak_Freq", deserialize_with = "from_str_to_bus_freq")]
        pub pm_peak_freq: BusFreq,
        #[serde(alias = "PM_Offpeak_Freq", deserialize_with = "from_str_to_bus_freq")]
        pub pm_offpeak_freq: BusFreq,
        pub loop_desc: String,
    }
    #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
    pub struct BusService {
        pub service_no: String,
        pub operator: Operator,
        pub no_direction: u8,
        pub category: BusCategory,
        pub origin_code: Option<NonZeroU8>,
        pub dest_code: Option<NonZeroU8>,
        pub am_peak_freq: BusFreq,
        pub am_offpeak_freq: BusFreq,
        pub pm_peak_freq: BusFreq,
        pub pm_offpeak_freq: BusFreq,
        pub loop_desc: String,
    }
    fn from_str_to_bus_freq<'de, D>(deserializer: D) -> Result<BusFreq, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s: String = String::deserialize(deserializer)?;
        let caps = BUS_FREQ_RE.captures(&s).unwrap();
        let min = caps.get(1).map_or(0, |m| m.as_str().parse().unwrap());
        let max = caps.get(2).map_or(0, |m| m.as_str().parse().unwrap());
        let bus_freq = if min == 0 && max == 0 {
            BusFreq::no_timing()
        } else if min != 0 && max == 0 {
            BusFreq::no_max(min)
        } else {
            BusFreq::new(min, max)
        };
        Ok(bus_freq)
    }
    impl From<BusServiceRaw> for BusService {
        fn from(r: BusServiceRaw) -> Self {
            Self {
                service_no: r.service_no,
                operator: r.operator,
                no_direction: r.no_direction,
                category: r.category,
                origin_code: r.origin_code,
                dest_code: r.dest_code,
                am_offpeak_freq: r.am_offpeak_freq,
                am_peak_freq: r.am_peak_freq,
                pm_offpeak_freq: r.pm_offpeak_freq,
                pm_peak_freq: r.pm_peak_freq,
                loop_desc: r.loop_desc,
            }
        }
    }
    #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
    pub struct BusServiceResp {
        pub value: Vec<BusServiceRaw>,
    }
    impl From<BusServiceResp> for Vec<BusService> {
        fn from(data: BusServiceResp) -> Self {
            data.value.into_iter().map(Into::into).collect()
        }
    }
}
pub mod bus_routes {
    use serde::{Deserialize, Serialize};
    use time::Time;
    use crate::bus_enums::Operator;
    use crate::utils::de::from_str;
    use crate::utils::serde_date::str_time_option::{de_str_time_opt_br, ser_str_time_opt};
    #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
    #[serde(rename_all = "PascalCase")]
    pub struct BusRouteRaw {
        pub service_no: String,
        pub operator: Operator,
        pub direction: u8,
        #[serde(alias = "StopSequence")]
        pub stop_seq: u8,
        #[serde(deserialize_with = "from_str")]
        pub bus_stop_code: u32,
        #[serde(alias = "Distance")]
        pub dist: f64,
        #[serde(
            alias = "WD_FirstBus",
            deserialize_with = "de_str_time_opt_br",
            serialize_with = "ser_str_time_opt"
        )]
        pub wd_first: Option<Time>,
        #[serde(
            alias = "WD_LastBus",
            deserialize_with = "de_str_time_opt_br",
            serialize_with = "ser_str_time_opt"
        )]
        pub wd_last: Option<Time>,
        #[serde(
            alias = "SAT_FirstBus",
            deserialize_with = "de_str_time_opt_br",
            serialize_with = "ser_str_time_opt"
        )]
        pub sat_first: Option<Time>,
        #[serde(
            alias = "SAT_LastBus",
            deserialize_with = "de_str_time_opt_br",
            serialize_with = "ser_str_time_opt"
        )]
        pub sat_last: Option<Time>,
        #[serde(
            alias = "SUN_FirstBus",
            deserialize_with = "de_str_time_opt_br",
            serialize_with = "ser_str_time_opt"
        )]
        pub sun_first: Option<Time>,
        #[serde(
            alias = "SUN_LastBus",
            deserialize_with = "de_str_time_opt_br",
            serialize_with = "ser_str_time_opt"
        )]
        pub sun_last: Option<Time>,
    }
    #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
    pub struct BusRoute {
        pub service_no: String,
        pub operator: Operator,
        pub direction: u8,
        pub stop_seq: u8,
        pub bus_stop_code: u32,
        pub dist: f64,
        pub wd_first: Option<Time>,
        pub wd_last: Option<Time>,
        pub sat_first: Option<Time>,
        pub sat_last: Option<Time>,
        pub sun_first: Option<Time>,
        pub sun_last: Option<Time>,
    }
    impl From<BusRouteRaw> for BusRoute {
        #[inline(always)]
        fn from(r: BusRouteRaw) -> Self {
            Self {
                service_no: r.service_no,
                operator: r.operator,
                direction: r.direction,
                stop_seq: r.stop_seq,
                bus_stop_code: r.bus_stop_code,
                dist: r.dist,
                wd_first: r.wd_first,
                wd_last: r.wd_last,
                sat_first: r.sat_first,
                sat_last: r.sat_last,
                sun_first: r.sun_first,
                sun_last: r.sun_last,
            }
        }
    }
    #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
    pub struct BusRouteResp {
        pub value: Vec<BusRouteRaw>,
    }
    impl From<BusRouteResp> for Vec<BusRoute> {
        fn from(data: BusRouteResp) -> Self {
            data.value.into_iter().map(Into::into).collect()
        }
    }
}
pub mod bus_stops {
    use serde::{Deserialize, Serialize};
    use crate::utils::de::from_str;
    #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
    #[serde(rename_all = "PascalCase")]
    pub struct BusStopRaw {
        #[serde(deserialize_with = "from_str")]
        pub bus_stop_code: u32,
        pub road_name: String,
        #[serde(alias = "Description")]
        pub desc: String,
        #[serde(alias = "Latitude")]
        pub lat: f64,
        #[serde(alias = "Longitude")]
        pub long: f64,
    }
    #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
    pub struct BusStop {
        pub bus_stop_code: u32,
        pub road_name: String,
        pub desc: String,
        pub lat: f64,
        pub long: f64,
    }
    impl From<BusStopRaw> for BusStop {
        #[inline(always)]
        fn from(r: BusStopRaw) -> Self {
            Self {
                bus_stop_code: r.bus_stop_code,
                road_name: r.road_name,
                desc: r.desc,
                lat: r.lat,
                long: r.long,
            }
        }
    }
    #[derive(Debug, Clone, PartialEq, Deserialize, Serialize)]
    pub struct BusStopsResp {
        pub value: Vec<BusStopRaw>,
    }
    impl From<BusStopsResp> for Vec<BusStop> {
        fn from(data: BusStopsResp) -> Self {
            data.value.into_iter().map(Into::into).collect()
        }
    }
}