/*
 * @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 java.util.Map;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
public class MapBuilder<K,V> {
    
    private final Map<K,V> map;

    public MapBuilder(Map<K, V> target) {
        this.map = target;
    }
    
    public Map<K,V> map() {
        return map;
    }
    
    public MultiMap<K,V> multimap() {
        return (MultiMap<K,V>)map;
    }
    
    public MapBuilder<K,V> put(K key, V value) {
        map.put(key, value);
        return this;
    }
    
    public MapBuilder<K,V> putAll(Map<? extends K, ? extends V> values) {
        map.putAll(values);
        return this;
    }

    public MapBuilder<K,V> putIfAbsent(K key, V value) {
        map.putIfAbsent(key, value);
        return this;
    }
    
    public MapBuilder<K,V> replace(K key, V value) {
        map.replace(key, value);
        return this;
    }
    
    public MapBuilder<K,V> replace(K key, V oldValue, V newValue) {
        map.replace(key, oldValue, newValue);
        return this;
    }
    
    public MapBuilder<K,V> replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
        map.replaceAll(function);
        return this;
    }
      
    public MapBuilder<K,V> merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
        map.merge(key, value, remappingFunction);
        return this;
    }
    
    public MapBuilder<K,V> remove(Object key) {
        map.remove(key);
        return this;
    }
    
    public MapBuilder<K,V> remove(Object key, Object value) {
        map.remove(key, value);
        return this;
    }
    
    public MapBuilder<K,V> clear() {
        map.clear();
        return this;
    }
    
    public MapBuilder<K,V> forEach(BiConsumer<? super K, ? super V> action) {
        map.forEach(action);
        return this;
    }
        
    public MapBuilder<K,V> putAll(K key, Iterable<? extends V> values) {
        ((MultiMap<K,V>)map).putAll(key, values);
        return this;
    }
    
    public MapBuilder<K,V> replaceAll(K key, Collection<V> values) {
        ((MultiMap<K,V>)map).replaceAll(key, values);
        return this;
    }

    public MapBuilder<K,V> removeAll(Object key) {
        if(map instanceof MultiMap) {
            ((MultiMap<K,V>)map).removeAll(key);
        } else {
            map.remove(key);
        }
        return this;
    }
    
}
