import { BaseMatcher } from "../BaseMatcher.js";
import { NullDescription } from "../NullDescription.js";

export class IsIterableContaining extends BaseMatcher {
    /**
     * @type {Matcher}
     */
    #element_matcher

    /**
     *
     * @param {Matcher} matcher
     */
    constructor(matcher) {
        super();

        this.#element_matcher = matcher;
    }

    matches(item, mismatch_description) {
        if (this.#isEmpty(item)) {
            mismatch_description.appendText("was empty");
            return false;
        }

        for (const itemElement of item) {
            if (this.#element_matcher.matches(itemElement, NullDescription.INSTANCE)) {
                return true;
            }
        }

        mismatch_description.appendText("mismatches were: [");

        let is_past_first = false;

        for (const itemElement of item) {
            if (is_past_first) {
                mismatch_description.appendText(", ");
            }

            this.#element_matcher.describeMismatch(item, mismatch_description);

            is_past_first = true;
        }


        mismatch_description.appendText("]");

        return false;

    }

    /**
     *
     * @param {Iterable} iterable
     * @return {boolean}
     */
    #isEmpty(iterable) {
        const iterator = iterable[Symbol.iterator]();

        const el = iterator.next();

        return el.done === true;
    }


    describeTo(description) {

        description
            .appendText("a collection containing ")
            .appendDescriptionOf(this.#element_matcher);

    }
}
