// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/*
 *******************************************************************************
 * Copyright (C) 2004-2016, International Business Machines Corporation and         *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.dev.test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;

import com.ibm.icu.text.UnicodeSet;

/**
 * To use, override the abstract and the protected methods as necessary.
 * Tests boilerplate invariants:
 * <br>a.equals(a)
 * <br>!a.equals(null)
 * <br>if a.equals(b) then 
 * <br>(1) a.hashCode() == b.hashCode  // note: the reverse is not necessarily true.
 * <br>(2) a functions in all aspects as equivalent to b
 * <br>(3) b.equals(a)
 * <br>if b = clone(a)
 * <br>(1) b.equals(a), and the above checks
 * <br>(2) if mutable(a), then a.clone() != a // note: the reverse is not necessarily true.
 * @author Davis
 */
public abstract class TestBoilerplate<T> extends TestFmwk {

    protected static Random random = new Random(12345);

    protected final void _test() throws Exception {
        List<T> list = new LinkedList<T>();
        while (_addTestObject(list)) {
        }
        T[] testArray = (T[]) list.toArray();
        for (int i = 0; i < testArray.length; ++i) {
            //logln("Testing " + i);
            T a = testArray[i];
            int aHash = a.hashCode();
            if (a.equals(null)) {
                errln("Equality/Null invariant fails: " + i);
            }
            if (!a.equals(a)) {
                errln("Self-Equality invariant fails: " + i);
            }
            T b;                
            if (_canClone(a)) {
                b = _clone(a);
                if (b == a) {
                    if (_isMutable(a)) {
                        errln("Clone/Mutability invariant fails: " + i);
                    }
                } else {
                    if (!a.equals(b)) {
                        errln("Clone/Equality invariant fails: " + i);
                    }
                }
                _checkEquals(i, -1, a, aHash, b);
            }
            for (int j = i; j < testArray.length; ++j) {
                b = testArray[j];
                if (a.equals(b)) _checkEquals(i, j, a, aHash, b);
            }
        }
    }

    private void _checkEquals(int i, int j, T a, int aHash, T b) {
        int bHash = b.hashCode();
        if (!b.equals(a)) errln("Equality/Symmetry",i, j);
        if (aHash != bHash) errln("Equality/Hash",i, j);
        if (a != b && !_hasSameBehavior(a,b)) {
            errln("Equality/Equivalence",i, j);
        }
    }

    private void errln(String title, int i, int j) {
        if (j < 0) errln("Clone/" + title + "invariant fails: " + i);
        else errln(title + "invariant fails: " + i + "," + j);
    }

    /**
     * Must be overridden to check whether a and be behave the same
     */
    protected abstract boolean _hasSameBehavior(T a, T b);

    /**
     * This method will be called multiple times until false is returned.
     * The results should be a mixture of different objects of the same
     * type: some equal and most not equal.
     * The subclasser controls how many are produced (recommend about 
     * 100, based on the size of the objects and how costly they are
     * to run this test on. The running time grows with the square of the
     * count.
     * NOTE: this method will only be called if the objects test as equal.
     */
    protected abstract boolean _addTestObject(List<T> c);
    /**
     * Override if the tested objects are mutable.
     * <br>Since Java doesn't tell us, we need a function to tell if so.
     * The default is true, so must be overridden if not.
     */
    protected boolean _isMutable(T a) {
        return true;
    }
    /**
     * Override if the tested objects can be cloned.
     */
    protected boolean _canClone(T a) {
        return true;
    }
    /**
     * Produce a clone of the object. Tries two methods
     * (a) clone
     * (b) constructor
     * Must be overridden if _canClone returns true and
     * the above methods don't work.
     * @param a
     * @return clone
     */
    protected T _clone(T a) throws Exception {
        Class aClass = a.getClass();
        try {
            Method cloner = aClass.getMethod("clone", (Class[])null);
            return (T) cloner.invoke(a,(Object[])null);
        } catch (NoSuchMethodException e) {
            Constructor constructor = aClass.getConstructor(new Class[] {aClass});
            return (T) constructor.newInstance(new Object[]{a});
        }
    }
    
    /* Utilities */
    public static boolean verifySetsIdentical(AbstractTestLog here, UnicodeSet set1, UnicodeSet set2) {
        if (set1.equals(set2)) return true;
        TestFmwk.errln("Sets differ:");
        TestFmwk.errln("UnicodeMap - HashMap");
        TestFmwk.errln(new UnicodeSet(set1).removeAll(set2).toPattern(true));
        TestFmwk.errln("HashMap - UnicodeMap");
        TestFmwk.errln(new UnicodeSet(set2).removeAll(set1).toPattern(true));
        return false;
    }

    public static boolean verifySetsIdentical(AbstractTestLog here, Set values1, Set values2) {
        if (values1.equals(values2)) return true;
        Set temp;
        TestFmwk.errln("Values differ:");
        TestFmwk.errln("UnicodeMap - HashMap");
        temp = new TreeSet(values1);
        temp.removeAll(values2);
        TestFmwk.errln(show(temp));
        TestFmwk.errln("HashMap - UnicodeMap");
        temp = new TreeSet(values2);
        temp.removeAll(values1);
        TestFmwk.errln(show(temp));
        return false;
    }
    
    public static String show(Map m) {
        StringBuilder buffer = new StringBuilder();
        for (Iterator it = m.keySet().iterator(); it.hasNext();) {
            Object key = it.next();
            buffer.append(key + "=>" + m.get(key) + "\r\n");
        }
        return buffer.toString();
    }
    
    public static <T> UnicodeSet getSet(Map<Integer, T> m, T value) {
        UnicodeSet result = new UnicodeSet();
        for (Iterator<Integer> it = m.keySet().iterator(); it.hasNext();) {
            Integer key = it.next();
            T val = m.get(key);
            if (!val.equals(value)) continue;
            result.add(key.intValue());
        }
        return result;
    }
    
    public static String show(Collection c) {
        StringBuilder buffer = new StringBuilder();
        for (Iterator it = c.iterator(); it.hasNext();) {
            buffer.append(it.next() + "\r\n");
        }
        return buffer.toString();
    }
}
