/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */
package net.ranides.assira.reflection.impl;

import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collector;
import net.ranides.assira.collection.query.CQuery;
import net.ranides.assira.reflection.*;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public abstract class AElements<T> implements IElements<T> {
    
    private final IHints hints;
    
    private CQuery<T> cquery;

    protected AElements(IHints hints, CQuery<T> cquery) {
        this.hints = hints;
        this.cquery = cquery; 
    }

    protected void filter(Predicate<? super T> predicate) {
        this.cquery = cquery.filter(predicate);
    }
    
    @Override
    public CQuery<T> stream() {
        return cquery;
    }

    @Override
    public void each(Consumer<? super T> consumer) {
        stream().each(consumer);
    }
    
    @Override
    public Iterator<T> iterator() {
        return stream().iterator();
    }
    
    @Override
    public <R> CQuery<R> stream(Function<? super T, ? extends R> mapper) {
        return cquery.map(mapper);
    }
    
    @Override
    public int count() {
        return cquery.size();
    }
    
    @Override
    public boolean isEmpty() {
        return cquery.isEmpty();
    }
    
    @Override
    public <R> List<R> list(Function<? super T, R> mapper) {
        return cquery.map(mapper).list();
    }
    
    @Override
    public List<T> list() {
        return cquery.list();
    }
    
    @Override
    public <R, A> R collect(Collector<? super T, A, R> collector) {
        return cquery.collect(collector);
    }
    
    @Override
    public Optional<T> first() {
        return cquery.first();
    }

    @Override
    public IElements<T> hint(IHints hints) {
        this.hints.replace(hints);
        return this;
    }
    
    protected IHints hints() {
        return hints;
    }

    @Override
    public final int hashCode() {
        return 0;
    }

    @Override
    public final boolean equals(Object object) {
        if(object instanceof IElements<?>) {
            IElements<?> that = (IElements<?>)object;
            return this.list().equals(that.list());
        }
        return false;
    }

    @Override
    public String toString() {
        return list().toString();
    }
    
}
