// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.common.map;

import java.util.function.Function;
import java.util.function.BiFunction;
import java.util.function.BiConsumer;
import java.util.Collection;
import java.util.Set;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;

public class DefaultMap<K, V> implements Map<K, V>
{
    private final Map<K, V> delegate;
    private final boolean allowReplacing;
    private final boolean replaceNullWithDefault;
    private V defaultValue;
    
    public DefaultMap(final V defaultValue) {
        this(defaultValue, new HashMap<K, Object>());
    }
    
    public DefaultMap(final V defaultValue, final Map<K, V> delegate) {
        this(defaultValue, (Map<K, Object>)delegate, true);
    }
    
    public DefaultMap(final V defaultValue, final Map<K, V> delegate, final boolean allowReplacing) {
        this(defaultValue, (Map<K, Object>)delegate, allowReplacing, true);
    }
    
    public DefaultMap(final V defaultValue, final Map<K, V> delegate, final boolean allowReplacing, final boolean replaceNullWithDefault) {
        this.defaultValue = defaultValue;
        this.delegate = delegate;
        this.allowReplacing = allowReplacing;
        this.replaceNullWithDefault = replaceNullWithDefault;
    }
    
    public V getDefaultValue() {
        return this.defaultValue;
    }
    
    public void setDefaultValue(final V defaultValue) {
        this.defaultValue = defaultValue;
    }
    
    public Map<K, V> getDelegate() {
        return this.delegate;
    }
    
    @Override
    public int size() {
        return this.delegate.size();
    }
    
    @Override
    public boolean isEmpty() {
        return this.delegate.isEmpty();
    }
    
    @Override
    public boolean containsKey(final Object key) {
        return this.delegate.containsKey(key);
    }
    
    @Override
    public boolean containsValue(final Object value) {
        return this.delegate.containsValue(value);
    }
    
    @Override
    public V get(@Nullable final Object key) {
        if (this.replaceNullWithDefault && key == null) {
            return this.defaultValue;
        }
        final V value = this.delegate.get(key);
        return (value != null) ? value : this.defaultValue;
    }
    
    @Override
    public V put(final K key, final V value) {
        if (this.allowReplacing) {
            return this.delegate.put(key, value);
        }
        final V oldValue = this.delegate.putIfAbsent(key, value);
        if (oldValue == null) {
            return null;
        }
        throw new IllegalArgumentException("Attachment (" + String.valueOf(key) + ") is already registered!");
    }
    
    @Override
    public V remove(final Object key) {
        return this.delegate.remove(key);
    }
    
    @Override
    public void putAll(@Nonnull final Map<? extends K, ? extends V> m) {
        this.delegate.putAll(m);
    }
    
    @Override
    public void clear() {
        this.delegate.clear();
    }
    
    @Nonnull
    @Override
    public Set<K> keySet() {
        return this.delegate.keySet();
    }
    
    @Nonnull
    @Override
    public Collection<V> values() {
        return this.delegate.values();
    }
    
    @Nonnull
    @Override
    public Set<Entry<K, V>> entrySet() {
        return this.delegate.entrySet();
    }
    
    @Override
    public boolean equals(@Nullable final Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || this.getClass() != o.getClass()) {
            return false;
        }
        final DefaultMap<?, ?> that = (DefaultMap<?, ?>)o;
        if (this.allowReplacing != that.allowReplacing) {
            return false;
        }
        if (this.replaceNullWithDefault != that.replaceNullWithDefault) {
            return false;
        }
        if (this.delegate != null) {
            if (this.delegate.equals(that.delegate)) {
                return (this.defaultValue != null) ? this.defaultValue.equals(that.defaultValue) : (that.defaultValue == null);
            }
        }
        else if (that.delegate == null) {
            return (this.defaultValue != null) ? this.defaultValue.equals(that.defaultValue) : (that.defaultValue == null);
        }
        return false;
    }
    
    @Override
    public int hashCode() {
        int result = (this.delegate != null) ? this.delegate.hashCode() : 0;
        result = 31 * result + (this.allowReplacing ? 1 : 0);
        result = 31 * result + (this.replaceNullWithDefault ? 1 : 0);
        result = 31 * result + ((this.defaultValue != null) ? this.defaultValue.hashCode() : 0);
        return result;
    }
    
    @Override
    public V getOrDefault(final Object key, final V defaultValue) {
        return this.delegate.getOrDefault(key, defaultValue);
    }
    
    @Override
    public void forEach(final BiConsumer<? super K, ? super V> action) {
        this.delegate.forEach(action);
    }
    
    @Override
    public void replaceAll(final BiFunction<? super K, ? super V, ? extends V> function) {
        this.delegate.replaceAll(function);
    }
    
    @Override
    public V putIfAbsent(final K key, final V value) {
        return this.delegate.putIfAbsent(key, value);
    }
    
    @Override
    public boolean remove(final Object key, final Object value) {
        return this.delegate.remove(key, value);
    }
    
    @Override
    public boolean replace(final K key, final V oldValue, final V newValue) {
        return this.delegate.replace(key, oldValue, newValue);
    }
    
    @Override
    public V replace(final K key, final V value) {
        return this.delegate.replace(key, value);
    }
    
    @Override
    public V computeIfAbsent(final K key, @Nonnull final Function<? super K, ? extends V> mappingFunction) {
        return this.delegate.computeIfAbsent(key, mappingFunction);
    }
    
    @Nullable
    @Override
    public V computeIfPresent(final K key, @Nonnull final BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        return this.delegate.computeIfPresent(key, remappingFunction);
    }
    
    @Override
    public V compute(final K key, @Nonnull final BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
        return this.delegate.compute(key, remappingFunction);
    }
    
    @Override
    public V merge(final K key, @Nonnull final V value, @Nonnull final BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
        return this.delegate.merge(key, value, remappingFunction);
    }
    
    @Nonnull
    @Override
    public String toString() {
        return "DefaultMap{defaultValue=" + String.valueOf(this.defaultValue) + ", delegate=" + String.valueOf(this.delegate);
    }
}
