/*
 **********************************************************************
 * Copyright (c) 2002-2014, International Business Machines
 * Corporation and others.  All Rights Reserved.
 **********************************************************************
 * Author: Mark Davis
 **********************************************************************
 */
package com.ibm.icu.dev.util;

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 { // TODO: add , Map<K, Collection<V>>, but requires API changes
    private Map<K, Set<V>> data;

    Constructor<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<Set<V>> setCreator) {
        this(map, setCreator, null);
    }

    public Relation(Map<K, Set<V>> map, Class<Set<V>> setCreator, Comparator<V> setComparator) {
        try {
            setComparatorParam = setComparator == null ? null : new Object[]{setComparator};
            if (setComparator == null) {
                this.setCreator = setCreator.getConstructor();
                this.setCreator.newInstance(setComparatorParam); // check to make sure compiles
            } else {
                this.setCreator = setCreator.getConstructor(Comparator.class);
                this.setCreator.newInstance(setComparatorParam); // check to make sure compiles        
            }
            data = map == null ? new HashMap() : 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;
    }

    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);
    }

    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 (Set<V>) 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 (K key : t.keySet()) {
            put(key, t.get(key));
        }
    }

    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());
    }

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

    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();
        }

        public K getKey() {
            return key;
        }

        public V getValue() {
            return value;
        }

        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 (V value : source.keySet()) {
            put(source.get(value), value);
        }
        return this;
    }

    volatile boolean frozen = false;

    public boolean isFrozen() {
        return frozen;
    }

    public Object 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;
    }

    public Object 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;
    }

    public 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;
    }
}