package ru.yandex.autotests.direct.web.util.matchers.beans;

import java.util.ArrayList;
import java.util.List;

import org.hamcrest.Factory;
import org.hamcrest.Matcher;
import org.hamcrest.core.IsCollectionContaining;

import static org.hamcrest.Matchers.allOf;
import static ru.yandex.autotests.direct.utils.matchers.BeanEquals.beanEquals;

public class IsBeanCollectionContaining<T> extends IsCollectionContaining<T> {
    public IsBeanCollectionContaining(Matcher<? super T> elementMatcher) {
        super(elementMatcher);
    }

    /**
     * Creates a matcher for {@link Iterable}s that only matches when a single pass over the
     * examined {@link Iterable} yields at least one item that is equal to the specified
     * <code>item</code>.  Whilst matching, the traversal of the examined {@link Iterable}
     * will stop as soon as a matching item is found.
     * <p/>
     * For example:
     * <pre>assertThat(Arrays.asList(bean1, bean2, bean3), hasBean(bean1))</pre>
     *
     * @param item the item to compare against the items provided by the examined {@link Iterable}
     */
    @Factory
    public static <T> Matcher<Iterable<? super T>> hasBean(T item) {
        return new IsCollectionContaining<>(beanEquals(item));
    }

    /**
     * Creates a matcher for {@link Iterable}s that matches when consecutive passes over the
     * examined {@link Iterable} yield at least one item that is equal to the corresponding
     * item from the specified <code>items</code>.  Whilst matching, each traversal of the
     * examined {@link Iterable} will stop as soon as a matching item is found.
     * <p/>
     * For example:
     * <pre>assertThat(Arrays.asList(bean1, bean2, bean3), hasBeans(Arrays.asList(bean1, bean2))</pre>
     *
     * @param items the items to compare against the items provided by the examined {@link Iterable}
     */
    @Factory
    public static <T> Matcher<Iterable<T>> hasBeans(List<T> items) {
        List<Matcher<? super Iterable<T>>> all = new ArrayList<>(items.size());
        for (T element : items) {
            all.add(hasBean(element));
        }
        return allOf(all);
    }
}
