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

import java.util.Collection;
import java.util.Comparator;
import net.ranides.assira.collections.map.IndexQuery;
import java.util.function.Consumer;
import java.util.function.Function;
import net.ranides.assira.collection.query.CQueryAbstract;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public abstract class AIndexQuery<V> extends CQueryAbstract<V> implements IndexQuery<V> {
    
    protected abstract AIndexMap<V> parent();
    
    @SuppressWarnings("unchecked")
    @Override
    public final IndexQuery<V> eq(String index, Object value) {
        return filter(index, a -> eq(a,value), a -> eq(a,(V)value));
    }

    @SuppressWarnings("unchecked")
    @Override
    public final IndexQuery<V> lt(String index, Object value) {
        return filter(index, a -> lt(a,value), a -> lt(a,(V)value));
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public final IndexQuery<V> gt(String index, Object value) {
        return filter(index, a -> gt(a,value), a -> gt(a,(V)value));
    }
    
    @SuppressWarnings("unchecked")
    @Override
    public final IndexQuery<V> in(String index, Object begin, Object end) {
        return filter(index, a -> in(a,begin,end), a -> in(a,(V)begin,(V)end));
    }
    
    @Override
    public void update(Consumer<? super V> consumer) {
        select().forEach(v -> parent().update(v, consumer));
    }
    
    protected abstract Collection<V> select();
    
    private IndexQuery<V> filter(
            String index, 
            Function<Function<V, Object>, IndexQuery<V>> mf, 
            Function<Comparator<V>, IndexQuery<V>> sf
    ) {
        Function<V, Object> mi = parent().mindex(index);
        if(mi != null) {
            return mf.apply(mi);
        }
        Comparator<V> si = parent().sindex(index);
        if(si != null) {
            return sf.apply(si);
        }
        throw new IllegalArgumentException("Unknown index: " + index);
    }
}
