/*
 * Decompiled with CFR 0.152.
 */
package org.jivesoftware.smack.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class MultiMap<K, V> {
    public static final int DEFAULT_MAP_SIZE = 6;
    private static final int ENTRY_SET_SIZE = 3;
    private final Map<K, Set<V>> map;

    public MultiMap() {
        this(6);
    }

    public MultiMap(int size) {
        this.map = new LinkedHashMap<K, Set<V>>(size);
    }

    public int size() {
        int size = 0;
        for (Set<V> set : this.map.values()) {
            size += set.size();
        }
        return size;
    }

    public boolean isEmpty() {
        return this.map.isEmpty();
    }

    public boolean containsKey(Object key) {
        return this.map.containsKey(key);
    }

    public boolean containsValue(Object value) {
        for (Set<V> set : this.map.values()) {
            if (!set.contains(value)) continue;
            return true;
        }
        return false;
    }

    public V getFirst(Object key) {
        Set<V> res = this.getAll(key);
        if (res.isEmpty()) {
            return null;
        }
        return res.iterator().next();
    }

    public Set<V> getAll(Object key) {
        Set<Object> res = this.map.get(key);
        if (res == null) {
            res = Collections.emptySet();
        }
        return res;
    }

    public boolean put(K key, V value) {
        boolean keyExisted;
        Set<V> set = this.map.get(key);
        if (set == null) {
            set = new LinkedHashSet<V>(3);
            set.add(value);
            this.map.put(key, set);
            keyExisted = false;
        } else {
            set.add(value);
            keyExisted = true;
        }
        return keyExisted;
    }

    public V remove(Object key) {
        Set<V> res = this.map.remove(key);
        if (res == null) {
            return null;
        }
        assert (!res.isEmpty());
        return res.iterator().next();
    }

    public boolean removeOne(Object key, V value) {
        Set<V> set = this.map.get(key);
        if (set == null) {
            return false;
        }
        boolean res = set.remove(value);
        if (set.isEmpty()) {
            this.map.remove(key);
        }
        return res;
    }

    public void putAll(Map<? extends K, ? extends V> map) {
        for (Map.Entry<K, V> entry : map.entrySet()) {
            this.put(entry.getKey(), entry.getValue());
        }
    }

    public void clear() {
        this.map.clear();
    }

    public Set<K> keySet() {
        return this.map.keySet();
    }

    public List<V> values() {
        ArrayList<V> values = new ArrayList<V>(this.size());
        for (Set<V> set : this.map.values()) {
            values.addAll(set);
        }
        return values;
    }

    public Set<Map.Entry<K, V>> entrySet() {
        LinkedHashSet<Map.Entry<K, V>> entrySet = new LinkedHashSet<Map.Entry<K, V>>(this.size());
        for (Map.Entry<K, Set<V>> entries : this.map.entrySet()) {
            K key = entries.getKey();
            for (V value : entries.getValue()) {
                entrySet.add(new SimpleMapEntry(key, value));
            }
        }
        return entrySet;
    }

    private static class SimpleMapEntry<K, V>
    implements Map.Entry<K, V> {
        private final K key;
        private V value;

        private SimpleMapEntry(K key, V value) {
            this.key = key;
            this.value = value;
        }

        @Override
        public K getKey() {
            return this.key;
        }

        @Override
        public V getValue() {
            return this.value;
        }

        @Override
        public V setValue(V value) {
            V tmp = this.value;
            this.value = value;
            return tmp;
        }
    }
}
