/*
 *******************************************************************************
 * Copyright (C) 1996-2013, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.dev.util;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import com.ibm.icu.text.Transform;

public class XEquivalenceClass<T,R> implements Iterable<T> {
    private static final String ARROW = "\u2192";

    public SetMaker<T> getSetMaker() {
        return setMaker;
    }

    // quick test
    static public void main(String[] args) {
        XEquivalenceClass<String, Integer> foo1 = new XEquivalenceClass<String, Integer>(1);
        String[][] tests = {{"b","a1"}, {"b", "c"}, {"a1", "c"}, {"d", "e"}, {"e", "f"}, {"c", "d"}};
        for (int i = 0; i < tests.length; ++i) {
            System.out.println("Adding: " + tests[i][0] + ", " + tests[i][1]);
            foo1.add(tests[i][0], tests[i][1], new Integer(i));
            for (String item : foo1.getExplicitItems()) {
                System.out.println("\t" + item  + ";\t" + foo1.getSample(item) + ";\t" + foo1.getEquivalences(item));
                List<Linkage<String, Integer>> reasons = foo1.getReasons(item, foo1.getSample(item));
                if (reasons != null) {
                    System.out.println("\t\t" + XEquivalenceClass.toString(reasons, null));
                }
            }
        }
    }

    private Map<T,Set<T>> toPartitionSet = new HashMap();
    private Map<T,Map<T,Set<R>>> obj_obj_reasons = new HashMap();
    private R defaultReason;
    private SetMaker setMaker;
    
    public interface SetMaker<T> {
        Set<T> make();
    }

    /**
     * empty, as if just created
     */
    public XEquivalenceClass clear(R defaultReasonArg) {
        toPartitionSet.clear();
        obj_obj_reasons.clear();
        this.defaultReason = defaultReasonArg;
        return this;
    }

    /**
     * Create class
     *
     */
    public XEquivalenceClass() {
    }

    /**
     * Create class with comparator, and default reason.
     *
     */
    public XEquivalenceClass(R defaultReason) {
        this.defaultReason = defaultReason;
    }
    
    /**
     * Create class with comparator, and default reason.
     *
     */
    public XEquivalenceClass(R defaultReason, SetMaker<T> setMaker) {
        this.defaultReason = defaultReason;
        this.setMaker = setMaker;
    }

    /**
     * Add two equivalent items, with NO_REASON for the reason.
     */
    public XEquivalenceClass add(T a, T b) {
        return add(a,b,null);
    }

    /**
     * Add two equivalent items, with NO_REASON for the reason.
     */
    public XEquivalenceClass add(T a, T b, R reason) {
        return add(a,b,reason, reason);
    }

    /**
     * Add two equivalent items, plus a reason. The reason is only used for getReasons
     */
    public XEquivalenceClass add(T a, T b, R reasonAB, R reasonBA) {
        if (a.equals(b)) return this;
        if (reasonAB == null) reasonAB = defaultReason;
        if (reasonBA == null) reasonBA = defaultReason;
        addReason(a,b,reasonAB);
        addReason(b,a,reasonBA);
        Set<T>aPartitionSet = toPartitionSet.get(a);
        Set<T>bPartitionSet = toPartitionSet.get(b);
        if (aPartitionSet == null) {
            if (bPartitionSet == null) { // both null, set up bSet
                bPartitionSet = setMaker != null ? setMaker.make() : new HashSet();
                bPartitionSet.add(b);
                toPartitionSet.put(b, bPartitionSet);
            }
            bPartitionSet.add(a);
            toPartitionSet.put(a, bPartitionSet);
        } else if (bPartitionSet == null) { // aSet is not null, bSet null
            aPartitionSet.add(b);
            toPartitionSet.put(b, aPartitionSet);
        } else if (aPartitionSet != bPartitionSet) {  // both non-null, not equal, merge.  Equality check ok here
            aPartitionSet.addAll(bPartitionSet);
            // remap every x that had x => bPartitionSet
            for (T item : bPartitionSet) {
                toPartitionSet.put(item, aPartitionSet);
            }
        }
        return this;
    }

    /**
     * Add all the information from the other class
     *
     */
    public XEquivalenceClass<T,R> addAll(XEquivalenceClass<T,R> other) {
        // For now, does the simple, not optimized version
        for (T a : other.obj_obj_reasons.keySet()) {
            Map<T,Set<R>> obj_reasons = other.obj_obj_reasons.get(a);
            for (T b : obj_reasons.keySet()) {
                Set<R> reasons = obj_reasons.get(b);
                for (R reason: reasons) {
                    add(a, b, reason);
                }
            }
        }
        return this;
    }

    /**
     * 
     */
    private void addReason(T a, T b, R reason) {
        Map<T,Set<R>> obj_reasons = obj_obj_reasons.get(a);
        if (obj_reasons == null) obj_obj_reasons.put(a, obj_reasons = new HashMap());
        Set<R> reasons = obj_reasons.get(b);
        if (reasons == null) obj_reasons.put(b, reasons = new HashSet());
        reasons.add(reason);
    }

    /**
     * Returns a set of all the explicit items in the equivalence set. (Any non-explicit items only
     * have themselves as equivalences.)
     *
     */
    public Set<T> getExplicitItems() {
        return Collections.unmodifiableSet(toPartitionSet.keySet());
    }

    /**
     * Returns an unmodifiable set of all the equivalent objects
     *
     */
    public Set<T>getEquivalences(T a) {
        Set<T> aPartitionSet = toPartitionSet.get(a);
        if (aPartitionSet == null) { // manufacture an equivalence
            aPartitionSet = new HashSet<T>();
            aPartitionSet.add(a); 
        }
        return Collections.unmodifiableSet(aPartitionSet);
    }
    
    public boolean hasEquivalences(T a) {
        return toPartitionSet.get(a) != null;
    }

    public Set<Set<T>> getEquivalenceSets() {
        Set<Set<T>> result = new HashSet<Set<T>>();
        for (T item : toPartitionSet.keySet()) {
            Set<T> partition = toPartitionSet.get(item);
            result.add(Collections.unmodifiableSet(partition));
        }
        return result;
    }
    /**
     * returns true iff a is equivalent to b (or a.equals b)
     *
     */
    public boolean isEquivalent(T a, T b) {
        if (a.equals(b)) return true;
        Set<T>aPartitionSet = toPartitionSet.get(a);
        if (aPartitionSet == null) return false;
        return aPartitionSet.contains(b);
    }

    /**
     * Gets a sample object in the equivalence set for a. 
     *
     */
    public T getSample(T a) {
        Set<T> aPartitionSet = toPartitionSet.get(a);
        if (aPartitionSet == null) return a; // singleton
        return aPartitionSet.iterator().next();
    }

    public interface Filter<T> {
        boolean matches(T o);
    }

    public T getSample(T a, Filter<T> f) {
        Set<T> aPartitionSet = toPartitionSet.get(a);
        if (aPartitionSet == null) return a; // singleton
        for (T obj : aPartitionSet) {
            if (f.matches(obj)) return obj;
        }
        return a;
    }

    /**
     * gets the set of all the samples, one from each equivalence class. 
     *
     */
    public Set<T> getSamples() {
        Set<T> seenAlready = new HashSet();
        Set<T> result = new HashSet();
        for (T item : toPartitionSet.keySet()) {
            if (seenAlready.contains(item)) continue;
            Set<T> partition = toPartitionSet.get(item);
            result.add(partition.iterator().next());
            seenAlready.addAll(partition);
        }
        return result;
    }

    public Iterator<T> iterator() {
        return getSamples().iterator();
    }
    
    public static class Linkage<T,R> {
        public Set<R> reasons;
        public T result;

        public Linkage(Set<R> reasons, T result) {
            this.reasons = reasons;
            this.result = result;
        }
        public String toString() {
            return reasons + (result == null ? "" : ARROW + result);
        }
    }

    public static <T,R> String toString(List<Linkage<T,R>> others, Transform<Linkage<T,R>,String> itemTransform) {
        StringBuffer result = new StringBuffer();
        for (Linkage<T,R> item : others) {
            result.append(itemTransform == null ? item.toString() : itemTransform.transform(item));
        }
        return result.toString();
    }

    /**
     * Returns a list of linkages, where each set of reasons to go from one obj to the next. The list does not include a and b themselves.
     * The last linkage has a null result.<br>
     * Returns null if there is no connection.
     */
    public List<Linkage<T,R>> getReasons(T a, T b) {
        // use dumb algorithm for getting shortest path
        // don't bother with optimization
        Set<T> aPartitionSet = toPartitionSet.get(a);
        Set<T> bPartitionSet = toPartitionSet.get(b);

        // see if they connect
        if (aPartitionSet == null || bPartitionSet == null || aPartitionSet != bPartitionSet || a.equals(b)) return null;

        ArrayList<Linkage<T,R>> list = new ArrayList<Linkage<T,R>>();
        list.add(new Linkage(null, a));
        ArrayList<ArrayList<Linkage<T,R>>> lists = new ArrayList<ArrayList<Linkage<T,R>>>();
        lists.add(list);

        // this will contain the results
        Set<T> sawLastTime = new HashSet<T>();
        sawLastTime.add(a);

        // each time, we extend each lists by one (adding multiple other lists)
        while (true) { // foundLists.size() == 0
            ArrayList extendedList = new ArrayList();
            Set<T>sawThisTime = new HashSet();
            for (ArrayList<Linkage<T,R>> lista : lists) {
                Linkage<T,R> last = lista.get(lista.size()-1);
                Map<T,Set<R>> obj_reasons = obj_obj_reasons.get(last.result);
                for (T result : obj_reasons.keySet()) {
                    if (sawLastTime.contains(result)) {
                        continue; // skip since we have shorter
                    }
                    sawThisTime.add(result);
                    Set<R> reasons = obj_reasons.get(result);
                    ArrayList<Linkage<T,R>> lista2 = (ArrayList<Linkage<T,R>>) lista.clone();
                    lista2.add(new Linkage(reasons,result));
                    extendedList.add(lista2);
                    if (result.equals(b)) {
                        // remove first and last
                        ArrayList<Linkage<T,R>> found = (ArrayList<Linkage<T,R>>) lista2.clone();
                        found.remove(0);
                        found.get(found.size()-1).result = null;
                        return found;
                    }
                }
            }
            lists = extendedList;
            sawLastTime.addAll(sawThisTime);
        }
        // return foundLists;
    }
    
    /**
     * For debugging.
     */
    public String toString() {
        return getEquivalenceSets().toString();
    }
}