use rudof_config::TomlConfig;
use rudof_iri::IriS;
use serde::{Deserialize, Serialize};

/// This struct can be used to define configuration of RDF data readers
#[derive(PartialEq, Debug, Clone, Serialize, Deserialize)]
#[serde(default)]
pub struct ServiceConfig {
    /// Default base to resolve relative IRIs, if it is `None` relative IRIs will be marked as errors`
    #[serde(rename = "base_iri", skip_serializing_if = "Option::is_none")]
    pub(crate) base: Option<IriS>,
}

impl ServiceConfig {
    pub fn new() -> Self {
        Self {
            base: Self::default_iri(),
        }
    }

    pub fn with_base(mut self, iri: Option<IriS>) -> Self {
        self.base = iri;
        self
    }
}

impl ServiceConfig {
    pub fn base(&self) -> Option<&IriS> {
        self.base.as_ref()
    }
}

/// Serde stuff
#[allow(dead_code)]
#[rustfmt::skip]
impl ServiceConfig {
    #[inline] fn default_iri() -> Option<IriS> { None }
}

impl Default for ServiceConfig {
    fn default() -> Self {
        Self::new()
    }
}

impl TomlConfig for ServiceConfig {}

#[cfg(test)]
mod tests {
    use super::ServiceConfig;
    use rudof_config::TomlConfig;

    #[test]
    fn defaults() {
        assert_eq!(ServiceConfig::default().base(), ServiceConfig::default_iri().as_ref());
    }

    #[test]
    fn partial_toml_fills_remaining_defaults() {
        let c = ServiceConfig::from_toml_str(r#"base_iri = "http://ex/""#).unwrap();
        assert_eq!(c.base().map(|i| i.as_str()), Some("http://ex/"));
    }

    #[test]
    fn toml_round_trip() {
        let c = ServiceConfig::new().with_base(Some(rudof_iri::IriS::new_unchecked("http://ex/")));
        let s = c.to_toml_string().unwrap();
        let d = ServiceConfig::from_toml_str(&s).unwrap();
        assert_eq!(c, d);
    }
}
