package net.ranides.assira.collection.query.base;

import net.ranides.assira.collection.query.CQuery;
import net.ranides.assira.collection.query.CQueryAbstract;
import net.ranides.assira.collection.query.support.BaseStream;

import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Spliterator;
import java.util.function.Supplier;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

/**
 * It is rudimentary implementation which uses provided stream generator as source.
 * It assumes at cost of generator call is very high and does not report any fast operations.
 *
 * @param <T> T
 */
public abstract class CQStream<T> extends CQueryAbstract<T> {

    protected boolean parallel;

    protected Supplier<? extends RuntimeException> message;

    /**
     * Creates new stream. It assummes that provided generator is not fast.
     *
     * @param source source
     * @param <T> T
     * @return query
     */
    public static <T> CQuery<T> from(Supplier<Stream<T>> source) {
        return new CQStream<T>() {
            @Override
            public Stream<T> stream() {
                return isParallel() ? source.get().parallel() : source.get().sequential();
            }
        };
    }

    @Override
    public abstract Stream<T> stream();

    @Override
    public Supplier<? extends RuntimeException> message() {
        return message;
    }

    @Override
    public CQuery<T> message(Supplier<? extends RuntimeException> message) {
        this.message = message;
        return this;
    }

    @Override
    public boolean isParallel() {
        return parallel;
    }

    @Override
    public CQuery<T> parallel() {
        this.parallel = true;
        return this;
    }

    @Override
    public CQuery<T> sequential() {
        this.parallel = false;
        return this;
    }

    @Override
    public Iterator<T> iterator() {
        return BaseStream.iterator(this);
    }

    @Override
    public int size() {
        return BaseStream.size(this);
    }

}


