use tests::memchr_tests;
use {Memchr, Memchr2, Memchr3};

#[test]
fn memchr1_iter() {
    for test in memchr_tests() {
        test.iter_one(false, Memchr::new);
    }
}

#[test]
fn memchr2_iter() {
    for test in memchr_tests() {
        test.iter_two(false, Memchr2::new);
    }
}

#[test]
fn memchr3_iter() {
    for test in memchr_tests() {
        test.iter_three(false, Memchr3::new);
    }
}

#[test]
fn memrchr1_iter() {
    for test in memchr_tests() {
        test.iter_one(true, |n1, corpus| Memchr::new(n1, corpus).rev());
    }
}

#[test]
fn memrchr2_iter() {
    for test in memchr_tests() {
        test.iter_two(true, |n1, n2, corpus| {
            Memchr2::new(n1, n2, corpus).rev()
        })
    }
}

#[test]
fn memrchr3_iter() {
    for test in memchr_tests() {
        test.iter_three(true, |n1, n2, n3, corpus| {
            Memchr3::new(n1, n2, n3, corpus).rev()
        })
    }
}

quickcheck! {
    fn qc_memchr_double_ended_iter(
        needle: u8, data: Vec<u8>, take_side: Vec<bool>
    ) -> bool {
        // make nonempty
        let mut take_side = take_side;
        if take_side.is_empty() { take_side.push(true) };

        let iter = Memchr::new(needle, &data);
        let all_found = double_ended_take(
            iter, take_side.iter().cycle().cloned());

        all_found.iter().cloned().eq(positions1(needle, &data))
    }

    fn qc_memchr2_double_ended_iter(
        needle1: u8, needle2: u8, data: Vec<u8>, take_side: Vec<bool>
    ) -> bool {
        // make nonempty
        let mut take_side = take_side;
        if take_side.is_empty() { take_side.push(true) };

        let iter = Memchr2::new(needle1, needle2, &data);
        let all_found = double_ended_take(
            iter, take_side.iter().cycle().cloned());

        all_found.iter().cloned().eq(positions2(needle1, needle2, &data))
    }

    fn qc_memchr3_double_ended_iter(
        needle1: u8, needle2: u8, needle3: u8,
        data: Vec<u8>, take_side: Vec<bool>
    ) -> bool {
        // make nonempty
        let mut take_side = take_side;
        if take_side.is_empty() { take_side.push(true) };

        let iter = Memchr3::new(needle1, needle2, needle3, &data);
        let all_found = double_ended_take(
            iter, take_side.iter().cycle().cloned());

        all_found
            .iter()
            .cloned()
            .eq(positions3(needle1, needle2, needle3, &data))
    }

    fn qc_memchr1_iter(data: Vec<u8>) -> bool {
        let needle = 0;
        let answer = positions1(needle, &data);
        answer.eq(Memchr::new(needle, &data))
    }

    fn qc_memchr1_rev_iter(data: Vec<u8>) -> bool {
        let needle = 0;
        let answer = positions1(needle, &data);
        answer.rev().eq(Memchr::new(needle, &data).rev())
    }

    fn qc_memchr2_iter(data: Vec<u8>) -> bool {
        let needle1 = 0;
        let needle2 = 1;
        let answer = positions2(needle1, needle2, &data);
        answer.eq(Memchr2::new(needle1, needle2, &data))
    }

    fn qc_memchr2_rev_iter(data: Vec<u8>) -> bool {
        let needle1 = 0;
        let needle2 = 1;
        let answer = positions2(needle1, needle2, &data);
        answer.rev().eq(Memchr2::new(needle1, needle2, &data).rev())
    }

    fn qc_memchr3_iter(data: Vec<u8>) -> bool {
        let needle1 = 0;
        let needle2 = 1;
        let needle3 = 2;
        let answer = positions3(needle1, needle2, needle3, &data);
        answer.eq(Memchr3::new(needle1, needle2, needle3, &data))
    }

    fn qc_memchr3_rev_iter(data: Vec<u8>) -> bool {
        let needle1 = 0;
        let needle2 = 1;
        let needle3 = 2;
        let answer = positions3(needle1, needle2, needle3, &data);
        answer.rev().eq(Memchr3::new(needle1, needle2, needle3, &data).rev())
    }

    fn qc_memchr1_iter_size_hint(data: Vec<u8>) -> bool {
        // test that the size hint is within reasonable bounds
        let needle = 0;
        let mut iter = Memchr::new(needle, &data);
        let mut real_count = data
            .iter()
            .filter(|&&elt| elt == needle)
            .count();

        while let Some(index) = iter.next() {
            real_count -= 1;
            let (lower, upper) = iter.size_hint();
            assert!(lower <= real_count);
            assert!(upper.unwrap() >= real_count);
            assert!(upper.unwrap() <= data.len() - index);
        }
        true
    }
}

// take items from a DEI, taking front for each true and back for each false.
// Return a vector with the concatenation of the fronts and the reverse of the
// backs.
fn double_ended_take<I, J>(mut iter: I, take_side: J) -> Vec<I::Item>
where
    I: DoubleEndedIterator,
    J: Iterator<Item = bool>,
{
    let mut found_front = Vec::new();
    let mut found_back = Vec::new();

    for take_front in take_side {
        if take_front {
            if let Some(pos) = iter.next() {
                found_front.push(pos);
            } else {
                break;
            }
        } else {
            if let Some(pos) = iter.next_back() {
                found_back.push(pos);
            } else {
                break;
            }
        };
    }

    let mut all_found = found_front;
    all_found.extend(found_back.into_iter().rev());
    all_found
}

// return an iterator of the 0-based indices of haystack that match the needle
fn positions1<'a>(
    n1: u8,
    haystack: &'a [u8],
) -> Box<dyn DoubleEndedIterator<Item = usize> + 'a> {
    let it = haystack
        .iter()
        .enumerate()
        .filter(move |&(_, &b)| b == n1)
        .map(|t| t.0);
    Box::new(it)
}

fn positions2<'a>(
    n1: u8,
    n2: u8,
    haystack: &'a [u8],
) -> Box<dyn DoubleEndedIterator<Item = usize> + 'a> {
    let it = haystack
        .iter()
        .enumerate()
        .filter(move |&(_, &b)| b == n1 || b == n2)
        .map(|t| t.0);
    Box::new(it)
}

fn positions3<'a>(
    n1: u8,
    n2: u8,
    n3: u8,
    haystack: &'a [u8],
) -> Box<dyn DoubleEndedIterator<Item = usize> + 'a> {
    let it = haystack
        .iter()
        .enumerate()
        .filter(move |&(_, &b)| b == n1 || b == n2 || b == n3)
        .map(|t| t.0);
    Box::new(it)
}
