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

import java.util.ArrayList;
import java.util.Collection;
import java.util.NoSuchElementException;
import java.util.function.BinaryOperator;
import net.ranides.assira.collection.sets.IntHashSet;
import net.ranides.assira.collection.sets.IntSet;
//import net.ranides.assira.functional.Fold;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public interface IntMultiMap<V> extends IntMap<V>, MultiMap<Integer, V> {
    
    Collection<V> getAll(int key);
    
    default V get(int key, BinaryOperator<V> fold) {
        return getAll(key).stream().reduce(fold).orElseThrow(()->new NoSuchElementException());
    }
    
    default boolean containsEntry(int key, Object value) {
        return getAll(key).contains(value);
    }

    default void putAll(int key, Iterable<? extends V> values) {
        for(V value : values) {
            put(key, value);
        }
    }

    default Collection<V> removeAll(int key) {
        Collection<V> prev = new ArrayList<>();
        V last;
        while(null != (last=remove(key))) {
            prev.add(last);
        }
        return prev;
    }
    
    @Override
    default Collection<V> getAll(Object key) {
        return getAll(((Integer)key).intValue());
    }
    
    @Override
    default V get(Object key, BinaryOperator<V> fold) {
        return get(((Integer)key).intValue(), fold);
    }
    
    @Override
    default boolean containsEntry(Object key, Object value) {
        return containsEntry(((Integer)key).intValue(), value);
    }

    @Override
    default void putAll(Integer key, Iterable<? extends V> values) {
        putAll(key.intValue(), values);
    }
    
    @Override
    default Collection<V> removeAll(Object key) {
        return removeAll(((Integer)key).intValue());
    }
    
    @Override
    default IntSet uniqueKeySet() {
        return new IntHashSet(keySet());
    }
    
    
}
