// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
 **********************************************************************
 * Copyright (c) 2002-2015, International Business Machines
 * Corporation and others.  All Rights Reserved.
 **********************************************************************
 * Author: Mark Davis
 **********************************************************************
 */
package com.ibm.icu.impl;

import java.lang.reflect.Constructor;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.ibm.icu.util.Freezable;

/**
 * A Relation is a set of mappings from keys to values.
 * Unlike Map, there is not guaranteed to be a single value per key.
 * The Map-like APIs return collections for values.
 * @author medavis

 */
public class Relation<K, V> implements Freezable<Relation<K,V>> { // TODO: add , Map<K, Collection<V>>, but requires API changes
    private Map<K, Set<V>> data;

    Constructor<? extends Set<V>> setCreator;
    Object[] setComparatorParam;

    public static <K, V> Relation<K, V> of(Map<K, Set<V>> map, Class<?> setCreator) {
        return new Relation<>(map, setCreator);
    }

    public static <K,V> Relation<K, V> of(Map<K, Set<V>> map, Class<?> setCreator, Comparator<V> setComparator) {
        return new Relation<>(map, setCreator, setComparator);
    }

    public Relation(Map<K, Set<V>> map, Class<?> setCreator) {
        this(map, setCreator, null);
    }

    @SuppressWarnings("unchecked")
    public Relation(Map<K, Set<V>> map, Class<?> setCreator, Comparator<V> setComparator) {
        try {
            setComparatorParam = setComparator == null ? null : new Object[]{setComparator};
            if (setComparator == null) {
                this.setCreator = ((Class<? extends Set<V>>)setCreator).getConstructor();
                this.setCreator.newInstance(setComparatorParam); // check to make sure compiles
            } else {
                this.setCreator = ((Class<? extends Set<V>>)setCreator).getConstructor(Comparator.class);
                this.setCreator.newInstance(setComparatorParam); // check to make sure compiles
            }
            data = map == null ? new HashMap<K, Set<V>>() : map;
        } catch (Exception e) {
            throw (RuntimeException) new IllegalArgumentException("Can't create new set").initCause(e);
        }
    }

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

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

    public boolean containsValue(Object value) {
        for (Set<V> values : data.values()) {
            if (values.contains(value)) {
                return true;
            }
        }
        return false;
    }

    public final Set<Entry<K, V>> entrySet() {
        return keyValueSet();
    }

    public Set<Entry<K, Set<V>>> keyValuesSet() {
        return data.entrySet();
    }

    public Set<Entry<K, V>> keyValueSet() {
        Set<Entry<K, V>> result = new LinkedHashSet<>();
        for (K key : data.keySet()) {
            for (V value : data.get(key)) {
                result.add(new SimpleEntry<>(key, value));
            }
        }
        return result;
    }

    @Override
    public boolean equals(Object o) {
        if (o == null)
            return false;
        if (o.getClass() != this.getClass())
            return false;
        return data.equals(((Relation<?, ?>) o).data);
    }

    //  public V get(Object key) {
    //      Set<V> set = data.get(key);
    //      if (set == null || set.size() == 0)
    //        return null;
    //      return set.iterator().next();
    //  }

    public Set<V> getAll(Object key) {
        return data.get(key);
    }

    public Set<V> get(Object key) {
        return data.get(key);
    }

    @Override
    public int hashCode() {
        return data.hashCode();
    }

    public boolean isEmpty() {
        return data.isEmpty();
    }

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

    public V put(K key, V value) {
        Set<V> set = data.get(key);
        if (set == null) {
            data.put(key, set = newSet());
        }
        set.add(value);
        return value;
    }

    public V putAll(K key, Collection<? extends V> values) {
        Set<V> set = data.get(key);
        if (set == null) {
            data.put(key, set = newSet());
        }
        set.addAll(values);
        return values.size() == 0 ? null : values.iterator().next();
    }

    public V putAll(Collection<K> keys, V value) {
        V result = null;
        for (K key : keys) {
            result = put(key, value);
        }
        return result;
    }

    private Set<V> newSet() {
        try {
            return setCreator.newInstance(setComparatorParam);
        } catch (Exception e) {
            throw (RuntimeException) new IllegalArgumentException("Can't create new set").initCause(e);
        }
    }

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

    public void putAll(Relation<? extends K, ? extends V> t) {
        for (K key : t.keySet()) {
            for (V value : t.getAll(key)) {
                put(key, value);
            }
        }
    }

    public Set<V> removeAll(K key) {
        try {
            return data.remove(key);
        } catch (NullPointerException e) {
            return null; // data doesn't allow null, eg ConcurrentHashMap
        }
    }

    public boolean remove(K key, V value) {
        try {
            Set<V> set = data.get(key);
            if (set == null) {
                return false;
            }
            boolean result = set.remove(value);
            if (set.size() == 0) {
                data.remove(key);
            }
            return result;
        } catch (NullPointerException e) {
            return false; // data doesn't allow null, eg ConcurrentHashMap
        }
    }

    public int size() {
        return data.size();
    }

    public Set<V> values() {
        return values(new LinkedHashSet<V>());
    }

    public <C extends Collection<V>> C values(C result) {
        for (Entry<K, Set<V>> keyValue : data.entrySet()) {
            result.addAll(keyValue.getValue());
        }
        return result;
    }

    @Override
    public String toString() {
        return data.toString();
    }

    static class SimpleEntry<K, V> implements Entry<K, V> {
        K key;

        V value;

        public SimpleEntry(K key, V value) {
            this.key = key;
            this.value = value;
        }

        public SimpleEntry(Entry<K, V> e) {
            this.key = e.getKey();
            this.value = e.getValue();
        }

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

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

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

    public Relation<K,V> addAllInverted(Relation<V,K> source) {
        for (V value : source.data.keySet()) {
            for (K key : source.data.get(value)) {
                put(key, value);
            }
        }
        return this;
    }

    public Relation<K,V> addAllInverted(Map<V,K> source) {
        for (Map.Entry<V,K> entry : source.entrySet()) {
            put(entry.getValue(), entry.getKey());
        }
        return this;
    }

    volatile boolean frozen = false;

    @Override
    public boolean isFrozen() {
        return frozen;
    }

    @Override
    public Relation<K, V> freeze() {
        if (!frozen) {
            // does not handle one level down, so we do that on a case-by-case basis
            for (K key : data.keySet()) {
                data.put(key, Collections.unmodifiableSet(data.get(key)));
            }
            // now do top level
            data = Collections.unmodifiableMap(data);
            frozen = true;
        }
        return this;
    }

    @Override
    public Relation<K, V> cloneAsThawed() {
        // TODO do later
        throw new UnsupportedOperationException();
    }

    public boolean removeAll(Relation<K, V> toBeRemoved) {
        boolean result = false;
        for (K key : toBeRemoved.keySet()) {
            try {
                Set<V> values = toBeRemoved.getAll(key);
                if (values != null) {
                    result |= removeAll(key, values);
                }
            } catch (NullPointerException e) {
                // data doesn't allow null, eg ConcurrentHashMap
            }
        }
        return result;
    }

    @SafeVarargs
    @SuppressWarnings("varargs")    // Not supported by Eclipse, but we need this for javac
    public final Set<V> removeAll(K... keys) {
        return removeAll(Arrays.asList(keys));
    }

    public boolean removeAll(K key, Iterable<V> toBeRemoved) {
        boolean result = false;
        for (V value : toBeRemoved) {
            result |= remove(key, value);
        }
        return result;
    }

    public Set<V> removeAll(Collection<K> toBeRemoved) {
        Set<V> result = new LinkedHashSet<>();
        for (K key : toBeRemoved) {
            try {
                final Set<V> removals = data.remove(key);
                if (removals != null) {
                    result.addAll(removals);
                }
            } catch (NullPointerException e) {
                // data doesn't allow null, eg ConcurrentHashMap
            }
        }
        return result;
    }
}
