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

package net.ranides.assira.collection.map;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map.Entry;

/**
 * Implementacja dwu-wymiarowej mapy używająca wewnętrznie {@code HashMap<HashMap<>>}
 * @param <KX> 
 * @param <KY> 
 * @param <V> 
 * @author ranides
 * @todo (migration) assira
 */
@SuppressWarnings("PMD.ShortVar")
public class CrossHashMap<KX, KY, V> implements CrossMap<KX, KY, V> {
    
    private static final long serialVersionUID = 3L;
    
    private final HashMap<KX, HashMap<KY,V>> data;

    /**
     * Constructs an empty <tt>CrossHashMap</tt> with the default initial capacity
     * (16) and the default load factor (0.75).
     */
    public CrossHashMap() {
        data = new HashMap<>();
    }

    @Override
    public boolean contains(KX x, KY y) {
        return data.containsKey(x) && data.get(x).containsKey(y);
    }

    @Override
    public V put(KX x, KY y, V value) {
        if( !data.containsKey(x) ) {
            data.put(x, new HashMap<KY,V>());
        }
        return data.get(x).put(y, value);
    }

    @Override
    public V remove(KX x, KY y) {
        if( !data.containsKey(x) ) {
            return null;
        }
        V value = data.get(x).remove(y);
        if( data.get(x).isEmpty() ) {
            data.remove(x);
        }
        return value;
    }

    @Override
    public V get(KX x, KY y) {
        return data.containsKey(x) ? data.get(x).get(y) : null;
    }

    @Override
    public final MultiMap<KX, KY> reduceZ() {
        MultiMap<KX, KY> result = new MultiHashMap<>();
        for(Entry<KX, HashMap<KY,V>> entry : data.entrySet() ) {
            result.put(entry.getKey(), new ArrayList<>(entry.getValue().keySet()) );
        }
        return result;
    }

    @Override
    public final MultiMap<KX, V> reduceY() {
        MultiMap<KX, V> result = new MultiHashMap<>();
        for( Entry<KX, HashMap<KY,V>> item : data.entrySet() ) {
            result.put( item.getKey(), new ArrayList<>(item.getValue().values()) );
        }
        return result;
    }

    @Override
    public int size() {
        int sum = 0;
        for(HashMap<KY,V> row : data.values()) {
            sum += row.size();
        }
        return sum;
    }

    @Override
    public boolean isEmpty() {
        return 0 == size();
    }

    @Override
    public void clear() {
        data.clear();
    }

    

}
