use serde::{Deserialize, Serialize};

#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct SchemaVersion {
    pub major: u32,
    pub minor: u32,
}

impl SchemaVersion {
    #[must_use]
    pub const fn new(major: u32, minor: u32) -> Self {
        Self { major, minor }
    }
}

impl core::fmt::Display for SchemaVersion {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "{}.{}", self.major, self.minor)
    }
}

#[derive(Clone, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
#[serde(deny_unknown_fields)]
pub struct SchemaHeader {
    pub name: String,
    pub version: SchemaVersion,
}

impl SchemaHeader {
    pub const BONE_DOCUMENT_NAME: &'static str = "bone-document";
    pub const BONE_DOCUMENT_MAJOR: u32 = 1;
    pub const BONE_DOCUMENT_MINOR: u32 = 0;

    #[must_use]
    pub fn bone_document() -> Self {
        Self {
            name: Self::BONE_DOCUMENT_NAME.to_owned(),
            version: SchemaVersion::new(Self::BONE_DOCUMENT_MAJOR, Self::BONE_DOCUMENT_MINOR),
        }
    }

    #[must_use]
    pub fn is_bone_document(&self) -> bool {
        self.name == Self::BONE_DOCUMENT_NAME
    }
}

impl core::fmt::Display for SchemaHeader {
    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
        write!(f, "{} v{}", self.name, self.version)
    }
}
