// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

//! Extensions for `fidl_fuchsia_ui_focus`.

use {
    fidl_fuchsia_ui_focus::{FocusChain, FocusKoidChain},
    fidl_fuchsia_ui_views_ext::ViewRefExt,
    fuchsia_scenic as scenic,
    fuchsia_zircon::{Koid, Status},
};

/// Extension trait for [`fidl_fuchsia_ui_focus::FocusChain`] and
/// [`fidl_fuchsia_ui_focus::FocusKoidChain`].
pub trait FocusChainExt
where
    Self: Sized,
{
    /// Returns the number of views in the chain.
    fn len(&self) -> usize;

    /// Returns true if there are no views in the chain.
    fn is_empty(&self) -> bool {
        self.len() == 0
    }

    /// Creates a new chain, in which all of the `ViewRef`s (or koids) have been duplicated from the
    /// original. Returns an error if duplicating any of the `ViewRef`s fails.
    fn duplicate(&self) -> Result<Self, Status>;

    /// Returns a fallible iterator over the chain's koids. If any koid cannot be retrieved, the
    /// iterator yields an error in its place.
    fn koids(&self) -> Box<dyn ExactSizeIterator<Item = Result<Koid, Status>> + '_>;

    /// Returns true if the two chains' `ViewRef`s correspond to the same koids, in the same
    /// order. If any of the koids cannot be retrieved, returns an error.
    fn equivalent<O: FocusChainExt>(&self, other: &O) -> Result<bool, Status> {
        let self_len = self.len();
        if self_len != other.len() {
            return Ok(false);
        }
        if self_len == 0 {
            return Ok(true);
        }

        let mut zipped = std::iter::zip(self.koids(), other.koids());
        while let Some((a, b)) = zipped.next() {
            if a? != b? {
                return Ok(false);
            }
        }
        Ok(true)
    }

    /// Converts this chain into a [`FocusKoidChain`], which contains just koids instead of
    /// [`ViewRef`]s.
    fn to_focus_koid_chain(&self) -> Result<FocusKoidChain, Status>;
}

impl FocusChainExt for FocusChain {
    fn len(&self) -> usize {
        match self.focus_chain.as_ref() {
            None => 0,
            Some(v) => v.len(),
        }
    }

    fn duplicate(&self) -> Result<Self, Status> {
        let v = match self.focus_chain.as_ref() {
            None => None,
            Some(v) => Some(
                v.iter().map(|vr| scenic::duplicate_view_ref(vr)).collect::<Result<Vec<_>, _>>()?,
            ),
        };
        let output = FocusChain { focus_chain: v, ..Default::default() };
        Ok(output)
    }

    fn koids(&self) -> Box<dyn ExactSizeIterator<Item = Result<Koid, Status>> + '_> {
        match &self.focus_chain {
            None => Box::new(std::iter::empty()),
            Some(v) => Box::new(v.iter().map(|vr| vr.get_koid())),
        }
    }

    fn to_focus_koid_chain(&self) -> Result<FocusKoidChain, Status> {
        let raw_koids = match self.focus_chain.as_ref() {
            None => None,
            Some(_) => Some(
                self.koids()
                    .map(|result| -> Result<u64, Status> { result.map(|koid| koid.raw_koid()) })
                    .collect::<Result<Vec<_>, _>>()?,
            ),
        };
        Ok(FocusKoidChain { focus_chain: raw_koids, ..Default::default() })
    }
}

impl FocusChainExt for FocusKoidChain {
    fn len(&self) -> usize {
        match self.focus_chain.as_ref() {
            None => 0,
            Some(v) => v.len(),
        }
    }

    /// Clones this `FocusKoidChain`.
    fn duplicate(&self) -> Result<Self, Status> {
        Ok(self.clone())
    }

    fn koids(&self) -> Box<dyn ExactSizeIterator<Item = Result<Koid, Status>> + '_> {
        match &self.focus_chain {
            None => Box::new(std::iter::empty()),
            Some(v) => Box::new(v.iter().map(|raw| Ok(Koid::from_raw(*raw)))),
        }
    }

    /// Clones this `FocusKoidChain`.
    fn to_focus_koid_chain(&self) -> Result<FocusKoidChain, Status> {
        self.duplicate()
    }
}

#[cfg(test)]
mod tests {
    use {super::*, fidl_fuchsia_ui_focus_test_helpers::make_focus_chain};

    #[test]
    fn focus_chain_duplicate() {
        let (source, _control_refs) = make_focus_chain(2);
        let target = source.duplicate().expect("error in duplicate()");

        let source_koids = source.koids().collect::<Result<Vec<_>, _>>().unwrap();
        let target_koids = target.koids().collect::<Result<Vec<_>, _>>().unwrap();

        assert_eq!(source_koids, target_koids,);
    }

    #[test]
    fn focus_chain_duplicate_empty() {
        let source = FocusChain::default();
        let target = source.duplicate().expect("error in duplicate()");

        assert_eq!(target.focus_chain, None);
    }

    #[test]
    fn focus_chain_equivalent_empty() {
        let a = FocusChain::default();
        let b = FocusChain::default();
        assert!(a.equivalent(&b).unwrap());

        let (a, _) = make_focus_chain(0);
        let (b, _) = make_focus_chain(0);
        assert!(a.equivalent(&b).unwrap());
    }

    #[test]
    fn focus_chain_equivalent_same_lengths() {
        let (a, _a) = make_focus_chain(3);
        let (b, _b) = make_focus_chain(3);
        assert!(!a.equivalent(&b).unwrap());
    }

    #[test]
    fn focus_chain_equivalent_different_lengths() {
        let (a, _a) = make_focus_chain(3);
        let (b, _b) = make_focus_chain(5);
        assert!(!a.equivalent(&b).unwrap());
    }

    #[test]
    fn focus_chain_equivalent_duplicates() {
        let (a, _a) = make_focus_chain(3);
        let b = a.duplicate().expect("duplicate");
        assert!(a.equivalent(&b).unwrap());
    }

    #[test]
    fn focus_chain_to_focus_koid_chain() {
        let (focus_chain, _view_control_refs) = make_focus_chain(2);
        let raw_koids = vec![
            focus_chain.focus_chain.as_ref().unwrap()[0].get_koid().unwrap().raw_koid(),
            focus_chain.focus_chain.as_ref().unwrap()[1].get_koid().unwrap().raw_koid(),
        ];

        let expected = FocusKoidChain { focus_chain: Some(raw_koids), ..Default::default() };

        let actual = focus_chain.to_focus_koid_chain().unwrap();

        assert_eq!(expected, actual);
    }

    #[test]
    fn focus_chain_equivalent_focus_koid_chain() {
        let (chain_a, _vcr_a) = make_focus_chain(2);
        let (chain_b, _vcr_b) = make_focus_chain(2);

        let koid_chain_a = chain_a.to_focus_koid_chain().unwrap();
        let koid_chain_b = chain_b.to_focus_koid_chain().unwrap();

        assert!(chain_a.equivalent(&koid_chain_a).unwrap());
        assert!(!chain_a.equivalent(&koid_chain_b).unwrap())
    }
}
