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

import net.ranides.assira.collection.query.CQuery;
import net.ranides.assira.collection.query.base.CQQuerySupplier;
import net.ranides.assira.generic.LazySupplier;
import net.ranides.assira.generic.LazySuppliers;

import java.util.NoSuchElementException;
import java.util.function.Supplier;

/**
 * Adapter query: it fetches collected data on demand.
 * Used by {@link CQuery#prefetch()} operation.
 *
 * Because it uses "fetch" operation, it supports all fast features.
 *
 * @param <T> T
 */
public class CQPrefetch<T> extends CQQuerySupplier<T> {

    private final LazySupplier<CQuery<T>> source;

    /**
     * Creates new prefetched query.
     *
     * @param source source
     */
    public CQPrefetch(CQuery<T> source, Supplier<? extends RuntimeException> message) {
        super(message);
        this.source = LazySuppliers.shared(() -> source.fetch());
    }

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

    @Override
    protected CQuery<T> query() {
        CQuery<T> out = isParallel() ? source.compute().parallel() : source.compute().sequential();
        if(message != null) {
            return out.message(message);
        } else {
            return out;
        }
    }

    @Override
    protected boolean hasFastQuery() {
        return true;
    }

    @Override
    public final CQuery<T> fetch() {
        return query();
    }

    @Override
    public CQuery<T> prefetch() {
        return this;
    }

}
