use std::{
    fmt::{
        Display,
        Formatter,
    },
    hash::{
        Hash,
        Hasher,
    },
};
use twox_hash::XxHash3_64;

const PREFIX: &'static str = "decal";

#[derive(Debug, Hash, Eq, PartialEq, Copy, Clone)]
pub(crate) struct Iri(u64);

pub(crate) trait ResourceIri: Hash {
    fn iri(&self) -> Iri {
        let mut hasher = XxHash3_64::with_seed(0);
        self.hash(&mut hasher);
        Iri(hasher.finish())
    }
}

impl Display for Iri {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        write!(f, "{PREFIX}-{:x}", self.0)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[derive(Debug, Hash, Eq, PartialEq)]
    struct Stub(u32);

    impl ResourceIri for Stub {}

    #[test]
    fn renders_iri() {
        assert_eq!(Iri(0xdeadbeef).to_string(), "decal-deadbeef");
    }

    #[test]
    fn iri_is_deterministic() {
        assert_eq!(Stub(45).iri(), Stub(45).iri());
    }
}
