use std::collections::BTreeMap;
use ruma_common::{
    api::{request, response, MatrixVersion, Metadata},
    metadata,
};
const METADATA: Metadata = metadata! {
    method: GET,
    rate_limited: false,
    authentication: None,
    history: {
        1.0 => "/_matrix/client/versions",
    }
};
#[request(error = crate::Error)]
#[derive(Default)]
pub struct Request {}
#[response(error = crate::Error)]
pub struct Response {
    pub versions: Vec<String>,
    #[serde(default, skip_serializing_if = "BTreeMap::is_empty")]
    pub unstable_features: BTreeMap<String, bool>,
}
impl Request {
    pub fn new() -> Self {
        Self {}
    }
}
impl Response {
    pub fn new(versions: Vec<String>) -> Self {
        Self { versions, unstable_features: BTreeMap::new() }
    }
    pub fn known_versions(&self) -> impl Iterator<Item = MatrixVersion> + DoubleEndedIterator {
        self.versions
            .iter()
            .flat_map(|s| s.parse::<MatrixVersion>())
            .map(|v| (v.into_parts(), v))
            .collect::<BTreeMap<_, _>>()
            .into_values()
    }
}
#[cfg(test)]
mod tests {
    use ruma_common::api::MatrixVersion;
    use super::Response;
    #[test]
    fn known_versions() {
        let none = Response::new(vec![]);
        assert_eq!(none.known_versions().next(), None);
        let single_known = Response::new(vec!["r0.6.0".to_owned()]);
        assert_eq!(single_known.known_versions().collect::<Vec<_>>(), vec![MatrixVersion::V1_0]);
        let single_unknown = Response::new(vec!["v0.0".to_owned()]);
        assert_eq!(single_unknown.known_versions().next(), None);
    }
    #[test]
    fn known_versions_order() {
        let sorted = Response::new(vec![
            "r0.0.1".to_owned(),
            "r0.5.0".to_owned(),
            "r0.6.0".to_owned(),
            "r0.6.1".to_owned(),
            "v1.1".to_owned(),
            "v1.2".to_owned(),
        ]);
        assert_eq!(
            sorted.known_versions().collect::<Vec<_>>(),
            vec![MatrixVersion::V1_0, MatrixVersion::V1_1, MatrixVersion::V1_2],
        );
        let sorted_reverse = Response::new(vec![
            "v1.2".to_owned(),
            "v1.1".to_owned(),
            "r0.6.1".to_owned(),
            "r0.6.0".to_owned(),
            "r0.5.0".to_owned(),
            "r0.0.1".to_owned(),
        ]);
        assert_eq!(
            sorted_reverse.known_versions().collect::<Vec<_>>(),
            vec![MatrixVersion::V1_0, MatrixVersion::V1_1, MatrixVersion::V1_2],
        );
        let random_order = Response::new(vec![
            "v1.1".to_owned(),
            "r0.6.1".to_owned(),
            "r0.5.0".to_owned(),
            "r0.6.0".to_owned(),
            "r0.0.1".to_owned(),
            "v1.2".to_owned(),
        ]);
        assert_eq!(
            random_order.known_versions().collect::<Vec<_>>(),
            vec![MatrixVersion::V1_0, MatrixVersion::V1_1, MatrixVersion::V1_2],
        );
    }
}