use super::*;

use std::fmt;
use std::marker::PhantomData;

impl<'a> super::ForestObligation for &'a str {
    type Predicate = &'a str;

    fn as_predicate(&self) -> &Self::Predicate {
        self
    }
}

struct ClosureObligationProcessor<OF, BF, O, E> {
    process_obligation: OF,
    _process_backedge: BF,
    marker: PhantomData<(O, E)>,
}

#[allow(non_snake_case)]
fn C<OF, BF, O>(of: OF, bf: BF) -> ClosureObligationProcessor<OF, BF, O, &'static str>
    where OF: FnMut(&mut O) -> ProcessResult<O, &'static str>,
          BF: FnMut(&[O])
{
    ClosureObligationProcessor {
        process_obligation: of,
        _process_backedge: bf,
        marker: PhantomData
    }
}

impl<OF, BF, O, E> ObligationProcessor for ClosureObligationProcessor<OF, BF, O, E>
    where O: super::ForestObligation + fmt::Debug,
          E: fmt::Debug,
          OF: FnMut(&mut O) -> ProcessResult<O, E>,
          BF: FnMut(&[O])
{
    type Obligation = O;
    type Error = E;

    fn process_obligation(&mut self,
                          obligation: &mut Self::Obligation)
                          -> ProcessResult<Self::Obligation, Self::Error>
    {
        (self.process_obligation)(obligation)
    }

    fn process_backedge<'c, I>(&mut self, _cycle: I,
                               _marker: PhantomData<&'c Self::Obligation>)
        where I: Clone + Iterator<Item=&'c Self::Obligation>
    {
    }
}


#[test]
fn push_pop() {
    let mut forest = ObligationForest::new();
    forest.register_obligation("A");
    forest.register_obligation("B");
    forest.register_obligation("C");

    // first round, B errors out, A has subtasks, and C completes, creating this:
    //      A |-> A.1
    //        |-> A.2
    //        |-> A.3
    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]),
                "B" => ProcessResult::Error("B is for broken"),
                "C" => ProcessResult::Changed(vec![]),
                _ => unreachable!(),
            }
        }, |_| {}), DoCompleted::Yes);
    assert_eq!(ok.unwrap(), vec!["C"]);
    assert_eq!(err,
               vec![Error {
                        error: "B is for broken",
                        backtrace: vec!["B"],
                    }]);

    // second round: two delays, one success, creating an uneven set of subtasks:
    //      A |-> A.1
    //        |-> A.2
    //        |-> A.3 |-> A.3.i
    //      D |-> D.1
    //        |-> D.2
    forest.register_obligation("D");
    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "A.1" => ProcessResult::Unchanged,
                "A.2" => ProcessResult::Unchanged,
                "A.3" => ProcessResult::Changed(vec!["A.3.i"]),
                "D" => ProcessResult::Changed(vec!["D.1", "D.2"]),
                _ => unreachable!(),
            }
        }, |_| {}), DoCompleted::Yes);
    assert_eq!(ok.unwrap(), Vec::<&'static str>::new());
    assert_eq!(err, Vec::new());


    // third round: ok in A.1 but trigger an error in A.2. Check that it
    // propagates to A, but not D.1 or D.2.
    //      D |-> D.1 |-> D.1.i
    //        |-> D.2 |-> D.2.i
    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "A.1" => ProcessResult::Changed(vec![]),
                "A.2" => ProcessResult::Error("A is for apple"),
                "A.3.i" => ProcessResult::Changed(vec![]),
                "D.1" => ProcessResult::Changed(vec!["D.1.i"]),
                "D.2" => ProcessResult::Changed(vec!["D.2.i"]),
                _ => unreachable!(),
            }
        }, |_| {}), DoCompleted::Yes);
    assert_eq!(ok.unwrap(), vec!["A.3", "A.1", "A.3.i"]);
    assert_eq!(err,
               vec![Error {
                        error: "A is for apple",
                        backtrace: vec!["A.2", "A"],
                    }]);

    // fourth round: error in D.1.i
    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "D.1.i" => ProcessResult::Error("D is for dumb"),
                "D.2.i" => ProcessResult::Changed(vec![]),
                _ => panic!("unexpected obligation {:?}", obligation),
            }
        }, |_| {}), DoCompleted::Yes);
    assert_eq!(ok.unwrap(), vec!["D.2.i", "D.2"]);
    assert_eq!(err,
               vec![Error {
                        error: "D is for dumb",
                        backtrace: vec!["D.1.i", "D.1", "D"],
                    }]);
}

// Test that if a tree with grandchildren succeeds, everything is
// reported as expected:
// A
//   A.1
//   A.2
//      A.2.i
//      A.2.ii
//   A.3
#[test]
fn success_in_grandchildren() {
    let mut forest = ObligationForest::new();
    forest.register_obligation("A");

    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]),
                _ => unreachable!(),
            }
        }, |_| {}), DoCompleted::Yes);
    assert!(ok.unwrap().is_empty());
    assert!(err.is_empty());

    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "A.1" => ProcessResult::Changed(vec![]),
                "A.2" => ProcessResult::Changed(vec!["A.2.i", "A.2.ii"]),
                "A.3" => ProcessResult::Changed(vec![]),
                _ => unreachable!(),
            }
        }, |_| {}), DoCompleted::Yes);
    assert_eq!(ok.unwrap(), vec!["A.3", "A.1"]);
    assert!(err.is_empty());

    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "A.2.i" => ProcessResult::Changed(vec!["A.2.i.a"]),
                "A.2.ii" => ProcessResult::Changed(vec![]),
                _ => unreachable!(),
            }
        }, |_| {}), DoCompleted::Yes);
    assert_eq!(ok.unwrap(), vec!["A.2.ii"]);
    assert!(err.is_empty());

    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "A.2.i.a" => ProcessResult::Changed(vec![]),
                _ => unreachable!(),
            }
        }, |_| {}), DoCompleted::Yes);
    assert_eq!(ok.unwrap(), vec!["A.2.i.a", "A.2.i", "A.2", "A"]);
    assert!(err.is_empty());

    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|_| unreachable!(), |_| {}),
        DoCompleted::Yes);

    assert!(ok.unwrap().is_empty());
    assert!(err.is_empty());
}

#[test]
fn to_errors_no_throw() {
    // check that converting multiple children with common parent (A)
    // yields to correct errors (and does not panic, in particular).
    let mut forest = ObligationForest::new();
    forest.register_obligation("A");
    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "A" => ProcessResult::Changed(vec!["A.1", "A.2", "A.3"]),
                _ => unreachable!(),
            }
        }, |_|{}), DoCompleted::Yes);
    assert_eq!(ok.unwrap().len(), 0);
    assert_eq!(err.len(), 0);
    let errors = forest.to_errors(());
    assert_eq!(errors[0].backtrace, vec!["A.1", "A"]);
    assert_eq!(errors[1].backtrace, vec!["A.2", "A"]);
    assert_eq!(errors[2].backtrace, vec!["A.3", "A"]);
    assert_eq!(errors.len(), 3);
}

#[test]
fn diamond() {
    // check that diamond dependencies are handled correctly
    let mut forest = ObligationForest::new();
    forest.register_obligation("A");
    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "A" => ProcessResult::Changed(vec!["A.1", "A.2"]),
                _ => unreachable!(),
            }
        }, |_|{}), DoCompleted::Yes);
    assert_eq!(ok.unwrap().len(), 0);
    assert_eq!(err.len(), 0);

    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "A.1" => ProcessResult::Changed(vec!["D"]),
                "A.2" => ProcessResult::Changed(vec!["D"]),
                _ => unreachable!(),
            }
        }, |_|{}), DoCompleted::Yes);
    assert_eq!(ok.unwrap().len(), 0);
    assert_eq!(err.len(), 0);

    let mut d_count = 0;
    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "D" => { d_count += 1; ProcessResult::Changed(vec![]) },
                _ => unreachable!(),
            }
        }, |_|{}), DoCompleted::Yes);
    assert_eq!(d_count, 1);
    assert_eq!(ok.unwrap(), vec!["D", "A.2", "A.1", "A"]);
    assert_eq!(err.len(), 0);

    let errors = forest.to_errors(());
    assert_eq!(errors.len(), 0);

    forest.register_obligation("A'");
    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "A'" => ProcessResult::Changed(vec!["A'.1", "A'.2"]),
                _ => unreachable!(),
            }
        }, |_|{}), DoCompleted::Yes);
    assert_eq!(ok.unwrap().len(), 0);
    assert_eq!(err.len(), 0);

    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "A'.1" => ProcessResult::Changed(vec!["D'", "A'"]),
                "A'.2" => ProcessResult::Changed(vec!["D'"]),
                _ => unreachable!(),
            }
        }, |_|{}), DoCompleted::Yes);
    assert_eq!(ok.unwrap().len(), 0);
    assert_eq!(err.len(), 0);

    let mut d_count = 0;
    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "D'" => { d_count += 1; ProcessResult::Error("operation failed") },
                _ => unreachable!(),
            }
        }, |_|{}), DoCompleted::Yes);
    assert_eq!(d_count, 1);
    assert_eq!(ok.unwrap().len(), 0);
    assert_eq!(err, vec![super::Error {
        error: "operation failed",
        backtrace: vec!["D'", "A'.1", "A'"]
    }]);

    let errors = forest.to_errors(());
    assert_eq!(errors.len(), 0);
}

#[test]
fn done_dependency() {
    // check that the local cache works
    let mut forest = ObligationForest::new();
    forest.register_obligation("A: Sized");
    forest.register_obligation("B: Sized");
    forest.register_obligation("C: Sized");

    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "A: Sized" | "B: Sized" | "C: Sized" => ProcessResult::Changed(vec![]),
                _ => unreachable!(),
            }
        }, |_|{}), DoCompleted::Yes);
    assert_eq!(ok.unwrap(), vec!["C: Sized", "B: Sized", "A: Sized"]);
    assert_eq!(err.len(), 0);

    forest.register_obligation("(A,B,C): Sized");
    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "(A,B,C): Sized" => ProcessResult::Changed(vec![
                    "A: Sized",
                    "B: Sized",
                    "C: Sized"
                        ]),
                _ => unreachable!(),
            }
        }, |_|{}), DoCompleted::Yes);
    assert_eq!(ok.unwrap(), vec!["(A,B,C): Sized"]);
    assert_eq!(err.len(), 0);
}

#[test]
fn orphan() {
    // check that orphaned nodes are handled correctly
    let mut forest = ObligationForest::new();
    forest.register_obligation("A");
    forest.register_obligation("B");
    forest.register_obligation("C1");
    forest.register_obligation("C2");

    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "A" => ProcessResult::Changed(vec!["D", "E"]),
                "B" => ProcessResult::Unchanged,
                "C1" => ProcessResult::Changed(vec![]),
                "C2" => ProcessResult::Changed(vec![]),
                _ => unreachable!(),
            }
        }, |_|{}), DoCompleted::Yes);
    assert_eq!(ok.unwrap(), vec!["C2", "C1"]);
    assert_eq!(err.len(), 0);

    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "D" | "E" => ProcessResult::Unchanged,
                "B" => ProcessResult::Changed(vec!["D"]),
                _ => unreachable!(),
            }
        }, |_|{}), DoCompleted::Yes);
    assert_eq!(ok.unwrap().len(), 0);
    assert_eq!(err.len(), 0);

    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "D" => ProcessResult::Unchanged,
                "E" => ProcessResult::Error("E is for error"),
                _ => unreachable!(),
            }
        }, |_|{}), DoCompleted::Yes);
    assert_eq!(ok.unwrap().len(), 0);
    assert_eq!(err, vec![super::Error {
        error: "E is for error",
        backtrace: vec!["E", "A"]
    }]);

    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "D" => ProcessResult::Error("D is dead"),
                _ => unreachable!(),
            }
        }, |_|{}), DoCompleted::Yes);
    assert_eq!(ok.unwrap().len(), 0);
    assert_eq!(err, vec![super::Error {
        error: "D is dead",
        backtrace: vec!["D"]
    }]);

    let errors = forest.to_errors(());
    assert_eq!(errors.len(), 0);
}

#[test]
fn simultaneous_register_and_error() {
    // check that registering a failed obligation works correctly
    let mut forest = ObligationForest::new();
    forest.register_obligation("A");
    forest.register_obligation("B");

    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "A" => ProcessResult::Error("An error"),
                "B" => ProcessResult::Changed(vec!["A"]),
                _ => unreachable!(),
            }
        }, |_|{}), DoCompleted::Yes);
    assert_eq!(ok.unwrap().len(), 0);
    assert_eq!(err, vec![super::Error {
        error: "An error",
        backtrace: vec!["A"]
    }]);

    let mut forest = ObligationForest::new();
    forest.register_obligation("B");
    forest.register_obligation("A");

    let Outcome { completed: ok, errors: err, .. } =
        forest.process_obligations(&mut C(|obligation| {
            match *obligation {
                "A" => ProcessResult::Error("An error"),
                "B" => ProcessResult::Changed(vec!["A"]),
                _ => unreachable!(),
            }
        }, |_|{}), DoCompleted::Yes);
    assert_eq!(ok.unwrap().len(), 0);
    assert_eq!(err, vec![super::Error {
        error: "An error",
        backtrace: vec!["A"]
    }]);
}
