use crate::pattern::{PatternItem, TimeGranularity};
use ::serde::{de, Deserialize, Deserializer};
use alloc::{fmt, format, vec::Vec};
#[cfg(feature = "datagen")]
use ::serde::{ser, Serialize};
mod reference {
    use super::*;
    use crate::pattern::reference::Pattern;
    #[derive(Debug, Clone, PartialEq, Deserialize)]
    #[cfg_attr(feature = "datagen", derive(Serialize))]
    struct PatternForSerde {
        items: Vec<PatternItem>,
        time_granularity: TimeGranularity,
    }
    impl From<PatternForSerde> for Pattern {
        fn from(pfs: PatternForSerde) -> Self {
            Self {
                items: pfs.items,
                time_granularity: pfs.time_granularity,
            }
        }
    }
    impl From<&Pattern> for PatternForSerde {
        fn from(pfs: &Pattern) -> Self {
            Self {
                items: pfs.items.clone(),
                time_granularity: pfs.time_granularity,
            }
        }
    }
    #[allow(clippy::upper_case_acronyms)]
    pub(crate) struct DeserializePatternUTS35String;
    impl<'de> de::Visitor<'de> for DeserializePatternUTS35String {
        type Value = Pattern;
        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            write!(formatter, "a valid pattern.")
        }
        fn visit_str<E>(self, pattern_string: &str) -> Result<Self::Value, E>
        where
            E: de::Error,
        {
            pattern_string.parse().map_err(|err| {
                de::Error::invalid_value(
                    de::Unexpected::Other(&format!("{err}")),
                    &"a valid UTS 35 pattern string",
                )
            })
        }
    }
    impl<'de> Deserialize<'de> for Pattern {
        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where
            D: Deserializer<'de>,
        {
            if deserializer.is_human_readable() {
                deserializer.deserialize_str(DeserializePatternUTS35String)
            } else {
                let pattern = PatternForSerde::deserialize(deserializer)?;
                Ok(Pattern::from(pattern))
            }
        }
    }
    #[cfg(feature = "datagen")]
    impl Serialize for Pattern {
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: ser::Serializer,
        {
            if serializer.is_human_readable() {
                serializer.serialize_str(&self.to_string())
            } else {
                let pfs = PatternForSerde::from(self);
                pfs.serialize(serializer)
            }
        }
    }
    #[cfg(all(test, feature = "datagen"))]
    mod test {
        use super::*;
        #[test]
        fn reference_pattern_serde_human_readable_test() {
            let pattern: Pattern = "Y-m-d HH:mm".parse().expect("Failed to parse pattern");
            let json = serde_json::to_string(&pattern).expect("Failed to serialize pattern");
            let result: Pattern =
                serde_json::from_str(&json).expect("Failed to deserialize pattern");
            assert_eq!(pattern, result);
        }
        #[test]
        fn reference_pattern_serde_bincode_test() {
            let pattern: Pattern = "Y-m-d HH:mm".parse().expect("Failed to parse pattern");
            let bytes = bincode::serialize(&pattern).expect("Failed to serialize pattern");
            let result: Pattern =
                bincode::deserialize(&bytes).expect("Failed to deserialize pattern");
            assert_eq!(pattern, result);
        }
    }
}
mod runtime {
    use super::*;
    use crate::pattern::{runtime::Pattern, PatternItem};
    use zerovec::ZeroVec;
    #[derive(Debug, Clone, PartialEq, Deserialize)]
    #[cfg_attr(feature = "datagen", derive(Serialize))]
    struct PatternForSerde<'data> {
        #[serde(borrow)]
        pub items: ZeroVec<'data, PatternItem>,
        pub time_granularity: TimeGranularity,
    }
    impl<'data> From<PatternForSerde<'data>> for Pattern<'data> {
        fn from(pfs: PatternForSerde<'data>) -> Self {
            Self {
                items: pfs.items,
                time_granularity: pfs.time_granularity,
            }
        }
    }
    #[allow(clippy::upper_case_acronyms)]
    struct DeserializePatternUTS35String;
    impl<'de> de::Visitor<'de> for DeserializePatternUTS35String {
        type Value = Pattern<'de>;
        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            write!(formatter, "a valid pattern.")
        }
        fn visit_str<E>(self, pattern_string: &str) -> Result<Self::Value, E>
        where
            E: de::Error,
        {
            let reference_deserializer = super::reference::DeserializePatternUTS35String;
            let pattern = reference_deserializer.visit_str(pattern_string)?;
            Ok(Self::Value::from(&pattern))
        }
    }
    impl<'de: 'data, 'data> Deserialize<'de> for Pattern<'data> {
        fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
        where
            D: Deserializer<'de>,
        {
            if deserializer.is_human_readable() {
                deserializer.deserialize_str(DeserializePatternUTS35String)
            } else {
                let pattern = PatternForSerde::deserialize(deserializer)?;
                Ok(Pattern::from(pattern))
            }
        }
    }
    #[cfg(feature = "datagen")]
    impl Serialize for Pattern<'_> {
        fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where
            S: ser::Serializer,
        {
            if serializer.is_human_readable() {
                serializer.serialize_str(&self.to_string())
            } else {
                let pfs = PatternForSerde {
                    items: self.items.clone(),
                    time_granularity: self.time_granularity,
                };
                pfs.serialize(serializer)
            }
        }
    }
    #[cfg(all(test, feature = "datagen"))]
    mod test {
        use super::*;
        #[test]
        fn runtime_pattern_serde_human_readable_test() {
            let pattern: Pattern = "Y-m-d HH:mm".parse().expect("Failed to parse pattern");
            let json = serde_json::to_string(&pattern).expect("Failed to serialize pattern");
            let result: Pattern =
                serde_json::from_str(&json).expect("Failed to deserialize pattern");
            assert_eq!(pattern, result);
        }
        #[test]
        fn runtime_pattern_serde_bincode_test() {
            let pattern: Pattern = "Y-m-d HH:mm".parse().expect("Failed to parse pattern");
            let bytes = bincode::serialize(&pattern).expect("Failed to serialize pattern");
            let result: Pattern =
                bincode::deserialize(&bytes).expect("Failed to deserialize pattern");
            assert_eq!(pattern, result);
        }
    }
    mod plural {
        use super::*;
        use crate::pattern::runtime::{PatternPlurals, PluralPattern};
        use core::fmt;
        #[derive(Debug, Clone, PartialEq, Deserialize)]
        #[cfg_attr(feature = "datagen", derive(Serialize))]
        #[allow(clippy::large_enum_variant)]
        enum PatternPluralsForSerde<'data> {
            #[serde(borrow)]
            MultipleVariants(PluralPattern<'data>),
            #[serde(borrow)]
            SinglePattern(Pattern<'data>),
        }
        impl<'data> From<PatternPluralsForSerde<'data>> for PatternPlurals<'data> {
            fn from(pfs: PatternPluralsForSerde<'data>) -> Self {
                match pfs {
                    PatternPluralsForSerde::MultipleVariants(variants) => {
                        Self::MultipleVariants(variants)
                    }
                    PatternPluralsForSerde::SinglePattern(pattern) => Self::SinglePattern(pattern),
                }
            }
        }
        impl<'data> From<&PatternPlurals<'data>> for PatternPluralsForSerde<'data> {
            fn from(pfs: &PatternPlurals<'data>) -> Self {
                match pfs.clone() {
                    PatternPlurals::MultipleVariants(variants) => Self::MultipleVariants(variants),
                    PatternPlurals::SinglePattern(pattern) => Self::SinglePattern(pattern),
                }
            }
        }
        struct DeserializePatternPlurals;
        impl<'de> de::Visitor<'de> for DeserializePatternPlurals {
            type Value = PatternPlurals<'de>;
            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(formatter, "a valid pattern.")
            }
            fn visit_str<E>(self, pattern_string: &str) -> Result<Self::Value, E>
            where
                E: de::Error,
            {
                let reference_deserializer = super::super::reference::DeserializePatternUTS35String;
                let pattern = reference_deserializer.visit_str(pattern_string)?;
                Ok(PatternPlurals::SinglePattern(Pattern::from(&pattern)))
            }
            fn visit_map<V>(self, map: V) -> Result<Self::Value, V::Error>
            where
                V: de::MapAccess<'de>,
            {
                Ok(PatternPlurals::MultipleVariants(
                    PluralPattern::deserialize(de::value::MapAccessDeserializer::new(map))?,
                ))
            }
        }
        impl<'de: 'data, 'data> Deserialize<'de> for PatternPlurals<'data> {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: Deserializer<'de>,
            {
                if deserializer.is_human_readable() {
                    deserializer.deserialize_any(DeserializePatternPlurals)
                } else {
                    let pattern = PatternPluralsForSerde::deserialize(deserializer)?;
                    Ok(Self::from(pattern))
                }
            }
        }
        #[cfg(feature = "datagen")]
        impl Serialize for PatternPlurals<'_> {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: ser::Serializer,
            {
                if serializer.is_human_readable() {
                    match self {
                        Self::SinglePattern(pattern) => {
                            serializer.serialize_str(&pattern.to_string())
                        }
                        Self::MultipleVariants(variants) => variants.serialize(serializer),
                    }
                } else {
                    let pfs: PatternPluralsForSerde = self.into();
                    pfs.serialize(serializer)
                }
            }
        }
        #[cfg(all(test, feature = "datagen"))]
        mod test {
            use super::*;
            use icu_plurals::PluralCategory;
            #[test]
            fn runtime_pattern_plurals_serde_human_readable_test() {
                let pattern_other: Pattern = "Y-m-d w 'other' HH:mm"
                    .parse()
                    .expect("Failed to parse pattern");
                let pattern_two: Pattern = "Y-m-d w 'two' HH:mm"
                    .parse()
                    .expect("Failed to parse pattern");
                let mut plural_pattern =
                    PluralPattern::new(pattern_other).expect("Failed to create PluralPattern");
                plural_pattern.maybe_set_variant(PluralCategory::Two, pattern_two);
                let pattern_plurals = PatternPlurals::from(plural_pattern);
                let json = serde_json::to_string(&pattern_plurals)
                    .expect("Failed to serialize pattern plurals");
                let result: PatternPlurals =
                    serde_json::from_str(&json).expect("Failed to deserialize pattern plurals");
                assert_eq!(pattern_plurals, result);
            }
            #[test]
            fn runtime_pattern_plurals_serde_bincode_test() {
                let pattern_other: Pattern = "Y-m-d w 'other' HH:mm"
                    .parse()
                    .expect("Failed to parse pattern");
                let pattern_two: Pattern = "Y-m-d w 'two' HH:mm"
                    .parse()
                    .expect("Failed to parse pattern");
                let mut plural_pattern =
                    PluralPattern::new(pattern_other).expect("Failed to create PluralPattern");
                plural_pattern.maybe_set_variant(PluralCategory::Two, pattern_two);
                let pattern_plurals = PatternPlurals::from(plural_pattern);
                let bytes = bincode::serialize(&pattern_plurals)
                    .expect("Failed to serialize pattern plurals");
                let result: PatternPlurals =
                    bincode::deserialize(&bytes).expect("Failed to deserialize pattern plurals");
                assert_eq!(pattern_plurals, result);
            }
        }
    }
    mod generic {
        use super::*;
        use crate::pattern::runtime::GenericPattern;
        #[allow(clippy::upper_case_acronyms)]
        struct DeserializeGenericPatternUTS35String;
        impl<'de> de::Visitor<'de> for DeserializeGenericPatternUTS35String {
            type Value = GenericPattern<'de>;
            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                write!(formatter, "a valid pattern.")
            }
            fn visit_str<E>(self, pattern_string: &str) -> Result<Self::Value, E>
            where
                E: de::Error,
            {
                let pattern = pattern_string
                    .parse()
                    .map_err(|_| E::custom("Failed to parse pattern"))?;
                Ok(GenericPattern::from(&pattern))
            }
        }
        impl<'de: 'data, 'data> Deserialize<'de> for GenericPattern<'data> {
            fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
            where
                D: Deserializer<'de>,
            {
                if deserializer.is_human_readable() {
                    deserializer.deserialize_str(DeserializeGenericPatternUTS35String)
                } else {
                    let items = ZeroVec::deserialize(deserializer)?;
                    Ok(Self { items })
                }
            }
        }
        #[cfg(feature = "datagen")]
        impl Serialize for GenericPattern<'_> {
            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
            where
                S: ser::Serializer,
            {
                if serializer.is_human_readable() {
                    let string = self.to_string();
                    serializer.serialize_str(&string)
                } else {
                    self.items.serialize(serializer)
                }
            }
        }
        #[cfg(all(test, feature = "datagen"))]
        mod test {
            use super::*;
            #[test]
            fn runtime_generic_pattern_serde_human_readable_test() {
                let pattern: GenericPattern =
                    "{0} 'and' {1}".parse().expect("Failed to parse pattern");
                let json = serde_json::to_string(&pattern).expect("Failed to serialize pattern");
                let result: GenericPattern =
                    serde_json::from_str(&json).expect("Failed to deserialize pattern");
                assert_eq!(pattern, result);
            }
            #[test]
            fn runtime_generic_pattern_serde_bincode_test() {
                let pattern: GenericPattern =
                    "{0} 'and' {1}".parse().expect("Failed to parse pattern");
                let bytes = bincode::serialize(&pattern).expect("Failed to serialize pattern");
                let result: GenericPattern =
                    bincode::deserialize(&bytes).expect("Failed to deserialize pattern");
                assert_eq!(pattern, result);
            }
        }
    }
}