use serde::{Deserialize, Serialize};

#[derive(Clone, Copy, Debug, Deserialize, Hash, PartialEq, PartialOrd, Serialize)]
#[serde(from = "u8")]
#[repr(u8)]
pub enum RelatedMangaType {
    Prequel = 1,
    Sequel = 2,
    AdaptedFrom = 3,
    SpinOff = 4,
    SideStory = 5,
    MainStory = 6,
    AlternateStory = 7,
    Doujinshi = 8,
    BasedOn = 9,
    Coloured = 10,
    Monochrome = 11,
    SharedUniverse = 12,
    SameFranchise = 13,
    PreSerialization = 14,
    Serialization = 15,
    #[serde(other)]
    Other = 0,
}

impl Default for RelatedMangaType {
    fn default() -> Self {
        0u8.into()
    }
}

impl From<u8> for RelatedMangaType {
    fn from(value: u8) -> Self {
        match value {
            1 => Self::Prequel,
            2 => Self::Sequel,
            3 => Self::AdaptedFrom,
            4 => Self::SpinOff,
            5 => Self::SideStory,
            6 => Self::MainStory,
            7 => Self::AlternateStory,
            8 => Self::Doujinshi,
            9 => Self::BasedOn,
            10 => Self::Coloured,
            11 => Self::Monochrome,
            12 => Self::SharedUniverse,
            13 => Self::SameFranchise,
            14 => Self::PreSerialization,
            15 => Self::Serialization,
            _ => Self::Other,
        }
    }
}

impl From<u16> for RelatedMangaType {
    fn from(value: u16) -> Self {
        match value {
            1 => Self::Prequel,
            2 => Self::Sequel,
            3 => Self::AdaptedFrom,
            4 => Self::SpinOff,
            5 => Self::SideStory,
            6 => Self::MainStory,
            7 => Self::AlternateStory,
            8 => Self::Doujinshi,
            9 => Self::BasedOn,
            10 => Self::Coloured,
            11 => Self::Monochrome,
            12 => Self::SharedUniverse,
            13 => Self::SameFranchise,
            14 => Self::PreSerialization,
            15 => Self::Serialization,
            _ => Self::Other,
        }
    }
}

impl From<u32> for RelatedMangaType {
    fn from(value: u32) -> Self {
        match value {
            1 => Self::Prequel,
            2 => Self::Sequel,
            3 => Self::AdaptedFrom,
            4 => Self::SpinOff,
            5 => Self::SideStory,
            6 => Self::MainStory,
            7 => Self::AlternateStory,
            8 => Self::Doujinshi,
            9 => Self::BasedOn,
            10 => Self::Coloured,
            11 => Self::Monochrome,
            12 => Self::SharedUniverse,
            13 => Self::SameFranchise,
            14 => Self::PreSerialization,
            15 => Self::Serialization,
            _ => Self::Other,
        }
    }
}

impl From<u64> for RelatedMangaType {
    fn from(value: u64) -> Self {
        match value {
            1 => Self::Prequel,
            2 => Self::Sequel,
            3 => Self::AdaptedFrom,
            4 => Self::SpinOff,
            5 => Self::SideStory,
            6 => Self::MainStory,
            7 => Self::AlternateStory,
            8 => Self::Doujinshi,
            9 => Self::BasedOn,
            10 => Self::Coloured,
            11 => Self::Monochrome,
            12 => Self::SharedUniverse,
            13 => Self::SameFranchise,
            14 => Self::PreSerialization,
            15 => Self::Serialization,
            _ => Self::Other,
        }
    }
}

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

    #[test]
    fn related_type_produces_other_from_0() {
        let related_type = RelatedMangaType::from(0u8);
        assert_eq!(related_type, RelatedMangaType::Other);
    }

    #[test]
    fn related_type_produces_sequel_from_2() {
        let related_type = RelatedMangaType::from(2u8);
        assert_eq!(related_type, RelatedMangaType::Sequel);
    }
}
