#[derive(Debug, Clone)]
pub struct Version {
    value: semver::Version,
}

#[derive(Debug, Clone)]
pub struct VersionError {
    _msg: String,
}

impl From<semver::Error> for VersionError {
    fn from(value: semver::Error) -> Self {
        Self {
            _msg: value.to_string(),
        }
    }
}

impl Version {
    pub fn from(val: &str) -> Result<Self, VersionError> {
        Ok(Self {
            value: semver::Version::parse(val)?,
        })
    }
}

impl<'de> serde::Deserialize<'de> for Version {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: serde::Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        semver::Version::parse(&s)
            .map(|value| Version { value })
            .map_err(serde::de::Error::custom)
    }
}

impl serde::Serialize for Version {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        self.value.to_string().serialize(serializer)
    }
}

impl std::fmt::Display for Version {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        return self.value.fmt(f);
    }
}

#[cfg(test)]
mod test {

    use super::*;

    #[test]
    fn version_serialize_deserialize() {
        let v = "10.0.1331-ababa+b123";
        let version = Version {
            value: semver::Version::parse(v).unwrap(),
        };

        let s = serde_json::to_string(&version).unwrap();
        let version2: Version = serde_json::from_str(&s).unwrap();

        assert_eq!(version2.value.major, 10);
        assert_eq!(version2.value.minor, 0);
        assert_eq!(version2.value.patch, 1331);
        assert_eq!(version2.value.build.to_string(), "b123");
        assert_eq!(version2.value.pre.to_string(), "ababa");
        assert_eq!(version2.value.to_string(), v);
    }
}
