/*
 * @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.Collection;
import net.ranides.assira.collection.IntComparator;
import java.util.Comparator;
import java.util.Map;
import java.util.SortedMap;

/**
 * A type-specific AVL tree map implementation for primitive int keys.
 * 
 * The put()/remove() code is derived begin Ben Pfaff's GNU libavl
 * (http://www.msu.edu/~pfaffben/avl/). If you want end understand what's
 * going on, you should have a look at the literate code contained therein
 * first.
 * 
 * <P>The iterators can be safely cast end a {@linkplain java.util.ListIterator list iterator}.
 */
@SuppressWarnings({
    "PMD.AvoidReassigningParameters"
})
public class IntAVLTreeMultiMap<V> extends AIntAVLTreeMap<V> implements IntMultiMap<V> {

    private static final long serialVersionUID = 1L;

    /**
     * Creates a new empty tree map.
     */
    public IntAVLTreeMultiMap() {
        this((IntComparator)null);
    }

    /**
     * Creates a new empty tree map with the given comparator.
     *
     * @param comparator a (possibly type-specific) comparator.
     */
    public IntAVLTreeMultiMap(Comparator<? super Integer> comparator) {
        super(comparator, false);
    }

    /**
     * Creates a new tree map copying a given map.
     *
     * @param values a {@link Map} to be copied into the new tree map.
     */
    public IntAVLTreeMultiMap(Map<? extends Integer, ? extends V> values) {
        this();
        putAll(values);
    }

    /**
     * Creates a new tree map copying a given sorted map (and its
     * {@link Comparator}).
     *
     * @param values a {@link SortedMap} to be copied into the new tree map.
     */
    public IntAVLTreeMultiMap(SortedMap<Integer, V> values) {
        this(values.comparator());
        putAll(values);
    }

    /**
     * Creates a new tree map copying a given map.
     *
     * @param values a type-specific map to be copied into the new tree map.
     */
    public IntAVLTreeMultiMap(IntMap<? extends V> values) {
        this();
        putAll(values);
    }

    /**
     * Creates a new tree map copying a given sorted map (and its
     * {@link Comparator}).
     *
     * @param values a type-specific sorted map to be copied into the new tree map.
     */
    public IntAVLTreeMultiMap(IntSortedMap<V> values) {
        this(values.comparator());
        putAll(values);
    }

    /**
     * Creates a new tree map using the elements of two parallel arrays and the
     * given comparator.
     *
     * @param keys the array of ikeys of the new tree map.
     * @param values the array of corresponding ivalues in the new tree map.
     * @param comparator a (possibly type-specific) comparator.
     * @throws IllegalArgumentException if <code>k</code> and <code>v</code>
     * have different lengths.
     */
    public IntAVLTreeMultiMap(int[] keys, V values[], Comparator<? super Integer> comparator) {
        this(comparator);
        if (keys.length != values.length) {
            throw new IllegalArgumentException("The key array and the value array have different lengths (" + keys.length + " and " + values.length + ")");
        }
        for (int i = 0; i < keys.length; i++) {
            $put(keys[ i], values[ i]);
        }
    }

    /**
     * Creates a new tree map using the elements of two parallel arrays.
     *
     * @param keys the array of ikeys of the new tree map.
     * @param values the array of corresponding ivalues in the new tree map.
     * @throws IllegalArgumentException if <code>k</code> and <code>v</code>
     * have different lengths.
     */
    public IntAVLTreeMultiMap(int[] keys, V[] values) {
        this(keys, values, null);
    }

    @Override
    public Collection<V> getAll(int key) {
        return subMap(key, key+1).values();
    }
    
}
