// Copyright 2019 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.

use {
    pretty::{BoxAllocator, DocAllocator},
    std::{
        fmt::{self, Debug, Display, Formatter},
        sync::Arc,
    },
};

/// Asynchronous extensions to Expectation Predicates
pub mod asynchronous;
/// Expectations for the host driver
pub mod host_driver;
/// Expectations for remote peers
pub mod peer;
/// Useful convenience methods and macros for working with expectations
#[macro_use]
pub mod prelude;
/// Tests for the expectation module
#[cfg(test)]
pub mod test;

/// A String whose `Debug` implementation pretty-prints. Used when we need to return a string which
/// we know will be printed through it's 'Debug' implementation, but we want to ensure that it is
/// not further escaped (for example, because it already is escaped, or because it contains
/// characters that we do not want to be escaped).
///
/// Essentially, formatting a DebugString with '{:?}' formats as if it was '{}'
#[derive(Clone, PartialEq)]
pub struct DebugString(String);

// The default formatting width for pretty printing output
const FMT_CHAR_WIDTH: usize = 100;

impl fmt::Debug for DebugString {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.0)
    }
}

/// Simplified `DocBuilder` alias used in this file
type DocBuilder<'a> = pretty::DocBuilder<'a, BoxAllocator>;

fn parens<'a>(alloc: &'a BoxAllocator, doc: DocBuilder<'a>) -> DocBuilder<'a> {
    alloc.text("(").append(doc).append(alloc.text(")"))
}

/// Functionalized Standard Debug Formatting
fn show_debug<T: Debug>(t: &T) -> String {
    format!("{:?}", t)
}

/// Function to compare two `T`s
type Comparison<T> = Arc<dyn Fn(&T, &T) -> bool + Send + Sync + 'static>;
/// Function to show a representation of a given `T`
type Show<T> = Arc<dyn Fn(&T) -> String + Send + Sync + 'static>;

/// A Boolean predicate on type `T`. Predicate functions are a boolean algebra
/// just as raw boolean values are; they an be ANDed, ORed, NOTed. This allows
/// a clear and concise language for declaring test expectations.
pub enum Predicate<T> {
    Equal(Arc<T>, Comparison<T>, Show<T>),
    And(Box<Predicate<T>>, Box<Predicate<T>>),
    Or(Box<Predicate<T>>, Box<Predicate<T>>),
    Not(Box<Predicate<T>>),
    Predicate(Arc<dyn Fn(&T) -> bool + Send + Sync>, String),
    // Since we can't use an existential:
    //  for<U> Over(Predicate<U>, Fn(&T) -> &U)
    // we use the trait `IsOver` to hide the type `U` of the intermediary
    Over(Arc<dyn IsOver<T> + Send + Sync>),
    // Since we can't use an existential:
    //  for<I> Any(Fn(&T) -> I, Predicate<I::Elem>)
    //  where I::Elem: Debug
    // we use the trait `IsAny` to hide the type `I` of the iterator
    Any(Arc<dyn IsAny<T> + Send + Sync + 'static>),
    // Since we can't use an existential:
    //  for<I> All(Fn(&T) -> I, Predicate<I::Elem>)
    //  where I::Elem: Debug
    // we use the trait `IsAll` to hide the type `I` of the iterator
    All(Arc<dyn IsAll<T> + Send + Sync + 'static>),
}

// Bespoke clone implementation. This implementation is equivalent to the one that would be derived
// by #[derive(Clone)] _except_ for the trait bounds. The derived impl would automatically require
// `T: Clone`, when actually `Predicate<T>` is `Clone` for _all_ `T`, even those that are not
// `Clone`.
impl<T> Clone for Predicate<T> {
    fn clone(&self) -> Self {
        match self {
            Predicate::Equal(t, comp, repr) => {
                Predicate::Equal(t.clone(), comp.clone(), repr.clone())
            }
            Predicate::And(l, r) => Predicate::And(l.clone(), r.clone()),
            Predicate::Or(l, r) => Predicate::Or(l.clone(), r.clone()),
            Predicate::Not(x) => Predicate::Not(x.clone()),
            Predicate::Predicate(p, msg) => Predicate::Predicate(p.clone(), msg.clone()),
            Predicate::Over(x) => Predicate::Over(x.clone()),
            Predicate::Any(x) => Predicate::Any(x.clone()),
            Predicate::All(x) => Predicate::All(x.clone()),
        }
    }
}

impl<T> Debug for Predicate<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.describe(&BoxAllocator).1.pretty(FMT_CHAR_WIDTH).fmt(f)
    }
}

/// At most how many elements of an iterator to show in a falsification, when falsifying `any` or
/// `all`
const MAX_ITER_FALSIFICATIONS: usize = 5;

fn falsify_elem<'p, 't, 'd, T: Debug>(
    pred: &'p Predicate<T>,
    index: usize,
    el: &'t T,
    doc: &'d BoxAllocator,
) -> Option<DocBuilder<'d>> {
    pred.falsify(el, doc).map(move |falsification| {
        doc.text(format!("[{}]", index))
            .append(doc.space().append(doc.text(show_debug(el))).nest(2))
            .append(doc.space().append(doc.text("BECAUSE")))
            .append(doc.space().append(falsification.group()).nest(2))
            .append(doc.text(","))
            .group()
    })
}

fn fmt_falsifications<'d>(
    i: impl Iterator<Item = DocBuilder<'d>>,
    doc: &'d BoxAllocator,
) -> Option<DocBuilder<'d>> {
    i.take(MAX_ITER_FALSIFICATIONS).fold(None, |acc: Option<DocBuilder<'d>>, falsification| {
        Some(acc.map_or(doc.nil(), |d| d.append(doc.space())).append(falsification))
    })
}

/// Trait representation of a Predicate on members of an existential iterator type
pub trait IsAny<T> {
    fn describe<'d>(&self, doc: &'d BoxAllocator) -> DocBuilder<'d>;
    fn falsify_any<'d>(&self, t: &T, doc: &'d BoxAllocator) -> Option<DocBuilder<'d>>;
}

impl<T: 'static, Elem: Debug + 'static> IsAny<T> for Predicate<Elem>
where
    for<'a> &'a T: IntoIterator<Item = &'a Elem>,
{
    fn describe<'d>(&self, doc: &'d BoxAllocator) -> DocBuilder<'d> {
        doc.text("ANY").append(doc.space().append(self.describe(doc)).nest(2)).group()
    }
    fn falsify_any<'d>(&self, t: &T, doc: &'d BoxAllocator) -> Option<DocBuilder<'d>> {
        if t.into_iter().any(|e| self.satisfied(e)) {
            None
        } else {
            // All are falsifications, so display all (up to MAX_ITER_FALSIFICATIONS)
            fmt_falsifications(
                t.into_iter().enumerate().filter_map(|(i, el)| falsify_elem(&self, i, &el, doc)),
                doc,
            )
            .or(Some(doc.text("<empty>")))
        }
    }
}

/// Trait representation of a Predicate on members of an existential iterator type
pub trait IsAll<T> {
    fn describe<'d>(&self, doc: &'d BoxAllocator) -> DocBuilder<'d>;
    fn falsify_all<'d>(&self, t: &T, doc: &'d BoxAllocator) -> Option<DocBuilder<'d>>;
}

impl<T: 'static, Elem: Debug + 'static> IsAll<T> for Predicate<Elem>
where
    for<'a> &'a T: IntoIterator<Item = &'a Elem>,
{
    fn describe<'d>(&self, doc: &'d BoxAllocator) -> DocBuilder<'d> {
        doc.text("ALL").append(doc.space().append(self.describe(doc)).nest(2)).group()
    }

    fn falsify_all<'d>(&self, t: &T, doc: &'d BoxAllocator) -> Option<DocBuilder<'d>> {
        fmt_falsifications(
            t.into_iter().enumerate().filter_map(|(i, el)| falsify_elem(&self, i, &el, doc)),
            doc,
        )
    }
}

/// A wrapping newtype to differentiate those types which are iterators themselves, from those that
/// implement `IntoIterator`.
struct OverIterator<Elem>(Predicate<Elem>);

impl<'e, Iter, Elem> IsAll<Iter> for OverIterator<Elem>
where
    Elem: Debug + 'static,
    Iter: Iterator<Item = &'e Elem> + Clone,
{
    fn describe<'d>(&self, doc: &'d BoxAllocator) -> DocBuilder<'d> {
        doc.text("ALL").append(doc.space().append(self.0.describe(doc)).nest(2)).group()
    }

    fn falsify_all<'d>(&self, iter: &Iter, doc: &'d BoxAllocator) -> Option<DocBuilder<'d>> {
        fmt_falsifications(
            iter.clone().enumerate().filter_map(|(i, el)| falsify_elem(&self.0, i, &el, doc)),
            doc,
        )
    }
}

impl<'e, Iter, Elem> IsAny<Iter> for OverIterator<Elem>
where
    Elem: Debug + 'static,
    Iter: Iterator<Item = &'e Elem> + Clone,
{
    fn describe<'d>(&self, doc: &'d BoxAllocator) -> DocBuilder<'d> {
        doc.text("ANY").append(doc.space().append(self.0.describe(doc)).nest(2)).group()
    }

    fn falsify_any<'d>(&self, iter: &Iter, doc: &'d BoxAllocator) -> Option<DocBuilder<'d>> {
        if iter.clone().any(|e| self.0.satisfied(e)) {
            None
        } else {
            // All are falsifications, so display all (up to MAX_ITER_FALSIFICATIONS)
            fmt_falsifications(
                iter.clone().enumerate().filter_map(|(i, el)| falsify_elem(&self.0, i, &el, doc)),
                doc,
            )
            .or(Some(doc.text("<empty>")))
        }
    }
}

/// A Predicate lifted over a mapping function from `T` to `U`. Such mappings allow converting a
/// predicate from one type - say, a struct field - to an upper type - such as a whole struct -
/// whilst maintaining information about the relationship.
enum OverPred<T, U> {
    ByRef(Predicate<U>, Arc<dyn Fn(&T) -> &U + Send + Sync + 'static>, String),
    ByValue(Predicate<U>, Arc<dyn Fn(&T) -> U + Send + Sync + 'static>, String),
}

/// Trait representation of OverPred where `U` is existential
pub trait IsOver<T> {
    fn describe<'d>(&self, doc: &'d BoxAllocator) -> DocBuilder<'d>;
    fn falsify_over<'d>(&self, t: &T, doc: &'d BoxAllocator) -> Option<DocBuilder<'d>>;
}

impl<T, U> IsOver<T> for OverPred<T, U> {
    fn describe<'a>(&self, doc: &'a BoxAllocator) -> DocBuilder<'a> {
        let (pred, path) = match self {
            OverPred::ByRef(pred, _, path) => (pred, path),
            OverPred::ByValue(pred, _, path) => (pred, path),
        };
        doc.as_string(path).append(doc.space()).append(pred.describe(doc)).group()
    }
    fn falsify_over<'d>(&self, t: &T, doc: &'d BoxAllocator) -> Option<DocBuilder<'d>> {
        let (d, path) = match self {
            OverPred::ByRef(pred, project, path) => (pred.falsify((project)(t), doc), path),
            OverPred::ByValue(pred, project, path) => (pred.falsify(&(project)(t), doc), path),
        };
        d.map(|falsification| {
            doc.as_string(path).append(doc.space().append(falsification).nest(2)).group()
        })
    }
}

impl<T> Predicate<T> {
    fn is_equal(&self) -> bool {
        if let Predicate::Equal(_, _, _) = self {
            true
        } else {
            false
        }
    }
    pub fn describe<'a>(&self, doc: &'a BoxAllocator) -> DocBuilder<'a> {
        match self {
            Predicate::Equal(expected, _, repr) => {
                doc.text("==").append(doc.space()).append(doc.text(repr(expected))).group()
            }
            Predicate::And(left, right) => parens(doc, left.describe(doc))
                .append(doc.space())
                .append(doc.text("AND"))
                .append(doc.space())
                .append(parens(doc, right.describe(doc)))
                .group(),
            Predicate::Or(left, right) => parens(doc, left.describe(doc))
                .nest(2)
                .append(doc.space())
                .append(doc.text("OR"))
                .append(doc.space())
                .append(parens(doc, right.describe(doc)).nest(2))
                .group(),
            // Succinct override for NOT-Equal cases
            Predicate::Not(inner) if inner.is_equal() => {
                if let Predicate::Equal(expected, _, repr) = &**inner {
                    doc.text("!=").append(doc.space()).append(doc.text(repr(&*expected))).group()
                } else {
                    // This branch is guarded by inner.is_equal()
                    unreachable!()
                }
            }
            Predicate::Not(inner) => {
                doc.text("NOT").append(doc.space().append(inner.describe(doc)).nest(2)).group()
            }
            Predicate::Predicate(_, desc) => doc.as_string(desc).group(),
            Predicate::Over(over) => over.describe(doc),
            Predicate::Any(any) => any.describe(doc),
            Predicate::All(all) => all.describe(doc),
        }
    }
    /// Provide a minimized falsification of the predicate, if possible
    pub fn falsify<'d>(&self, t: &T, doc: &'d BoxAllocator) -> Option<DocBuilder<'d>> {
        match self {
            Predicate::Equal(expected, are_eq, repr) => {
                if are_eq(expected, t) {
                    None
                } else {
                    Some(
                        doc.text(repr(t))
                            .append(doc.space())
                            .append(doc.text("!="))
                            .append(doc.space())
                            .append(doc.text(repr(expected)))
                            .group(),
                    )
                }
            }
            Predicate::And(left, right) => match (left.falsify(t, doc), right.falsify(t, doc)) {
                (Some(l), Some(r)) => Some(
                    parens(doc, l)
                        .append(doc.space())
                        .append(doc.text("AND"))
                        .append(doc.space())
                        .append(parens(doc, r))
                        .group(),
                ),
                (Some(l), None) => Some(l),
                (None, Some(r)) => Some(r),
                (None, None) => None,
            },
            Predicate::Or(left, right) => left
                .falsify(t, doc)
                .and_then(|l| right.falsify(t, doc).map(|r| parens(doc, l).append(parens(doc, r)))),
            Predicate::Not(inner) => match inner.falsify(t, doc) {
                Some(_) => None,
                None => match &**inner {
                    Predicate::Equal(expected, _, repr) => Some(
                        doc.text(repr(t))
                            .append(doc.space())
                            .append(doc.text("=="))
                            .append(doc.space())
                            .append(doc.text(repr(&expected))),
                    ),
                    _ => Some(
                        doc.text("NOT")
                            .append(doc.space().append(inner.describe(doc)).nest(2))
                            .group(),
                    ),
                },
            },
            Predicate::Predicate(pred, desc) => {
                if pred(t) {
                    None
                } else {
                    Some(doc.text("NOT").append(doc.space().append(doc.as_string(desc)).nest(2)))
                }
            }
            Predicate::Over(over) => over.falsify_over(t, doc),
            Predicate::Any(any) => any.falsify_any(t, doc),
            Predicate::All(all) => all.falsify_all(t, doc),
        }
    }
    pub fn satisfied<'t>(&self, t: &'t T) -> bool {
        match self {
            Predicate::Equal(expected, are_eq, _) => are_eq(t, expected),
            Predicate::And(left, right) => left.satisfied(t) && right.satisfied(t),
            Predicate::Or(left, right) => left.satisfied(t) || right.satisfied(t),
            Predicate::Not(inner) => !inner.satisfied(t),
            Predicate::Predicate(pred, _) => pred(t),
            Predicate::Over(over) => over.falsify_over(t, &BoxAllocator).is_none(),
            Predicate::Any(any) => any.falsify_any(t, &BoxAllocator).is_none(),
            Predicate::All(all) => all.falsify_all(t, &BoxAllocator).is_none(),
        }
    }
    pub fn assert_satisfied(&self, t: &T) -> Result<(), DebugString> {
        let doc = BoxAllocator;
        match self.falsify(t, &doc) {
            Some(falsification) => {
                let d = doc
                    .text("FAILED EXPECTATION")
                    .append(doc.newline().append(self.describe(&doc)).nest(2))
                    .append(doc.newline().append(doc.text("BECAUSE")))
                    .append(doc.newline().append(falsification).nest(2));
                Err(DebugString(d.1.pretty(FMT_CHAR_WIDTH).to_string()))
            }
            None => Ok(()),
        }
    }
    pub fn and(self, rhs: Predicate<T>) -> Predicate<T> {
        Predicate::And(Box::new(self), Box::new(rhs))
    }
    pub fn or(self, rhs: Predicate<T>) -> Predicate<T> {
        Predicate::Or(Box::new(self), Box::new(rhs))
    }
    pub fn not(self) -> Predicate<T> {
        Predicate::Not(Box::new(self))
    }
    /// Construct a simple predicate function
    pub fn predicate<F, S>(f: F, label: S) -> Predicate<T>
    where
        F: for<'t> Fn(&'t T) -> bool + Send + Sync + 'static,
        S: Into<String>,
    {
        Predicate::Predicate(Arc::new(f), label.into())
    }
}

/// Convenient implementations that rely on `Debug` to provide output on falsification, and
/// `PartialEq` to provide equality. If you wish to create predicates for `?Debug` types, use the
/// `Predicate` or `Equal` constructors directly.
impl<T: PartialEq + Debug + 'static> Predicate<T> {
    /// Construct a Predicate that expects two `T`s to be equal
    pub fn equal(t: T) -> Predicate<T> {
        Predicate::Equal(Arc::new(t), Arc::new(T::eq), Arc::new(show_debug))
    }
    /// Construct a Predicate that expects two `T`s to be non-equal
    pub fn not_equal(t: T) -> Predicate<T> {
        Predicate::Equal(Arc::new(t), Arc::new(T::eq), Arc::new(show_debug)).not()
    }
}

/// Predicates on iterable types, those convertible into iterators via IntoIterator (e.g. Vec<_>)
impl<Elem, T> Predicate<T>
where
    T: Send + Sync + 'static,
    for<'a> &'a T: IntoIterator<Item = &'a Elem>,
    Elem: Debug + Send + Sync + 'static,
{
    /// Construct a predicate that all elements of an iterable type match a given predicate
    /// If the iterable is empty, the predicate will succeed
    pub fn all(pred: Predicate<Elem>) -> Predicate<T> {
        Predicate::All(Arc::new(pred))
    }

    /// Construct a predicate that at least one element of an iterable type match a given predicate
    /// If the iterable is empty, the predicate will fail
    pub fn any(pred: Predicate<Elem>) -> Predicate<T> {
        Predicate::Any(Arc::new(pred))
    }
}

/// Predicates on types which are an `Iterator`
impl<'e, Elem, Iter> Predicate<Iter>
where
    Iter: Iterator<Item = &'e Elem> + Clone,
    Elem: Debug + Send + Sync + 'static,
{
    /// Construct a predicate that all elements of an Iterator match a given predicate
    /// If the Iterator is empty, the predicate will succeed
    pub fn iter_all(pred: Predicate<Elem>) -> Predicate<Iter> {
        Predicate::All(Arc::new(OverIterator(pred)))
    }

    /// Construct a predicate that at least one element of an Iterator match a given predicate
    /// If the iterator is empty, the predicate will fail
    pub fn iter_any(pred: Predicate<Elem>) -> Predicate<Iter> {
        Predicate::Any(Arc::new(OverIterator(pred)))
    }
}

impl<U: Send + Sync + 'static> Predicate<U> {
    /// Lift a predicate over a projection from `T -> &U`. This constructs a Predicate<T> from a
    /// predicate on some field (or arbitrary projection) of type `U`.
    ///
    /// This allows:
    ///   * Creating a Predicate on a struct from a predicate on a field (or field of a field) of
    ///     that struct.
    ///   * Creating a Predicate on a type from a predicate on some value computable from that type
    ///
    /// Compared to writing an arbitrary function using the `predicate()` method, an
    /// `over` projection allows for more minimal falsification and better error reporting in
    /// failure cases.
    ///
    /// Use `over` when your projection function returns a reference. If you need to return a value
    /// (for example, a temporary whose reference lifetime would not escape the function), use
    /// `over_value`.
    pub fn over<F, T, P>(self, project: F, path: P) -> Predicate<T>
    where
        F: Fn(&T) -> &U + Send + Sync + 'static,
        P: Into<String>,
        T: 'static,
    {
        Predicate::Over(Arc::new(OverPred::ByRef(self, Arc::new(project), path.into())))
    }

    /// Lift a predicate over a projection from `T -> U`. This constructs a Predicate<T> from a
    /// predicate on some field (or arbitrary projection) of type `U`.
    ///
    /// This allows:
    ///   * Creating a Predicate on a struct from a predicate on a field (or field of a field) of
    ///     that struct.
    ///   * Creating a Predicate on a type from a predicate on some value computable from that type
    ///
    /// Compared to writing an arbitrary function using the `predicate()` method, an
    /// `over` projection allows for more minimal falsification and better error reporting in
    /// failure cases.
    ///
    /// Use `over_value` when your projection function needs to return a value. If you can return a
    /// reference, use `over`.
    pub fn over_value<F, T, P>(self, project: F, path: P) -> Predicate<T>
    where
        F: Fn(&T) -> U + Send + Sync + 'static,
        P: Into<String>,
        T: 'static,
    {
        Predicate::Over(Arc::new(OverPred::ByValue(self, Arc::new(project), path.into())))
    }
}

/// A macro for allowing more ergonomic projection of predicates 'over' some projection function
/// that focuses on a subset of a data type.
///
/// Specify the name of the parent type, the field to focus on, and then pass in the predicate over
/// that field
///
/// usage: over!(Type:field, predicate)
///
/// e.g.
///
/// ```
/// let predicate = over!(RemoteDevice:name, P::equal(Some("INCORRECT_NAME".to_string())));
/// ```
#[macro_export]
macro_rules! over {
    ($type:ty : $selector:tt, $pred:expr) => {
        $pred.over(|var: &$type| &var.$selector, format!(".{}", stringify!($selector)))
    };
}

/// A simple macro to allow idiomatic assertion of predicates, producing well formatted
/// falsifications if the predicate fails.
///
/// usage:
///
/// ```
/// let predicate = correct_name().or(correct_address());
/// assert_satisfies!(&test_peer(), predicate);
/// ```
#[macro_export]
macro_rules! assert_satisfies {
    ($subject:expr, $pred:expr) => {
        if let Err(msg) = $pred.assert_satisfied($subject) {
            panic!("{}", msg.0)
        }
    };
}
