// © 2017 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
package com.ibm.icu.dev.test.number;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
// TODO: enable in Java 8: import java.lang.reflect.Parameter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.junit.Test;

import com.ibm.icu.dev.test.serializable.SerializableTestUtility;
import com.ibm.icu.impl.number.DecimalFormatProperties;
import com.ibm.icu.impl.number.DecimalFormatProperties.ParseMode;
import com.ibm.icu.impl.number.Padder.PadPosition;
import com.ibm.icu.impl.number.PatternStringParser;
import com.ibm.icu.text.CompactDecimalFormat.CompactStyle;
import com.ibm.icu.text.CurrencyPluralInfo;
import com.ibm.icu.text.MeasureFormat.FormatWidth;
import com.ibm.icu.text.PluralRules;
import com.ibm.icu.util.Currency;
import com.ibm.icu.util.Currency.CurrencyUsage;
import com.ibm.icu.util.MeasureUnit;
import com.ibm.icu.util.ULocale;

public class PropertiesTest {

    @Test
    public void testBasicEquals() {
        DecimalFormatProperties p1 = new DecimalFormatProperties();
        DecimalFormatProperties p2 = new DecimalFormatProperties();
        assertEquals(p1, p2);

        p1.setPositivePrefix("abc");
        assertNotEquals(p1, p2);
        p2.setPositivePrefix("xyz");
        assertNotEquals(p1, p2);
        p1.setPositivePrefix("xyz");
        assertEquals(p1, p2);
    }

    @Test
    public void testFieldCoverage() {
        DecimalFormatProperties p0 = new DecimalFormatProperties();
        DecimalFormatProperties p1 = new DecimalFormatProperties();
        DecimalFormatProperties p2 = new DecimalFormatProperties();
        DecimalFormatProperties p3 = new DecimalFormatProperties();
        DecimalFormatProperties p4 = new DecimalFormatProperties();

        Set<Integer> hashCodes = new HashSet<Integer>();
        Field[] fields = DecimalFormatProperties.class.getDeclaredFields();
        for (Field field : fields) {
            if (Modifier.isStatic(field.getModifiers())) {
                continue;
            }

            // Check for getters and setters
            String fieldNamePascalCase = Character.toUpperCase(field.getName().charAt(0))
                    + field.getName().substring(1);
            String getterName = "get" + fieldNamePascalCase;
            String setterName = "set" + fieldNamePascalCase;
            Method getter, setter;
            try {
                getter = DecimalFormatProperties.class.getMethod(getterName);
                assertEquals("Getter does not return correct type",
                        field.getType(),
                        getter.getReturnType());
            } catch (NoSuchMethodException e) {
                fail("Could not find method " + getterName + " for field " + field);
                continue;
            } catch (SecurityException e) {
                fail("Could not access method " + getterName + " for field " + field);
                continue;
            }
            try {
                setter = DecimalFormatProperties.class.getMethod(setterName, field.getType());
                assertEquals("Method " + setterName + " does not return correct type",
                        DecimalFormatProperties.class,
                        setter.getReturnType());
            } catch (NoSuchMethodException e) {
                fail("Could not find method " + setterName + " for field " + field);
                continue;
            } catch (SecurityException e) {
                fail("Could not access method " + setterName + " for field " + field);
                continue;
            }

            // Check for parameter name equality.
            // The parameter name is not always available, depending on compiler settings.
            // TODO: Enable in Java 8
            /*
             * Parameter param = setter.getParameters()[0]; if (!param.getName().subSequence(0,
             * 3).equals("arg")) { assertEquals("Parameter name should equal field name",
             * field.getName(), param.getName()); }
             */

            try {
                // Check for default value (should be null for objects)
                if (field.getType() != Integer.TYPE && field.getType() != Boolean.TYPE) {
                    Object default0 = getter.invoke(p0);
                    assertEquals("Field " + field + " has non-null default value:", null, default0);
                }

                // Check for getter, equals, and hash code behavior
                Object val0 = getSampleValueForType(field.getType(), 0);
                Object val1 = getSampleValueForType(field.getType(), 1);
                Object val2 = getSampleValueForType(field.getType(), 2);
                assertNotEquals(val0, val1);
                setter.invoke(p1, val0);
                setter.invoke(p2, val0);
                assertEquals(p1, p2);
                assertEquals(p1.hashCode(), p2.hashCode());
                assertEquals(getter.invoke(p1), getter.invoke(p2));
                assertEquals(getter.invoke(p1), val0);
                assertNotEquals(getter.invoke(p1), val1);
                hashCodes.add(p1.hashCode());
                setter.invoke(p1, val1);
                assertNotEquals("Field " + field + " is missing from equals()", p1, p2);
                assertNotEquals(getter.invoke(p1), getter.invoke(p2));
                assertNotEquals(getter.invoke(p1), val0);
                assertEquals(getter.invoke(p1), val1);
                setter.invoke(p1, val0);
                assertEquals("Field " + field + " setter might have side effects", p1, p2);
                assertEquals(p1.hashCode(), p2.hashCode());
                assertEquals(getter.invoke(p1), getter.invoke(p2));
                setter.invoke(p1, val1);
                setter.invoke(p2, val1);
                assertEquals(p1, p2);
                assertEquals(p1.hashCode(), p2.hashCode());
                assertEquals(getter.invoke(p1), getter.invoke(p2));
                setter.invoke(p1, val2);
                setter.invoke(p1, val1);
                assertEquals("Field " + field + " setter might have side effects", p1, p2);
                assertEquals(p1.hashCode(), p2.hashCode());
                assertEquals(getter.invoke(p1), getter.invoke(p2));
                hashCodes.add(p1.hashCode());

                // Check for clone behavior
                DecimalFormatProperties copy = p1.clone();
                assertEquals("Field " + field + " did not get copied in clone", p1, copy);
                assertEquals(p1.hashCode(), copy.hashCode());
                assertEquals(getter.invoke(p1), getter.invoke(copy));

                // Check for copyFrom behavior
                setter.invoke(p1, val0);
                assertNotEquals(p1, p2);
                assertNotEquals(getter.invoke(p1), getter.invoke(p2));
                p2.copyFrom(p1);
                assertEquals("Field " + field + " is missing from copyFrom()", p1, p2);
                assertEquals(p1.hashCode(), p2.hashCode());
                assertEquals(getter.invoke(p1), getter.invoke(p2));

                // Load values into p3 and p4 for clear() behavior test
                setter.invoke(p3, getSampleValueForType(field.getType(), 3));
                hashCodes.add(p3.hashCode());
                setter.invoke(p4, getSampleValueForType(field.getType(), 4));
                hashCodes.add(p4.hashCode());
            } catch (IllegalAccessException e) {
                fail("Could not access method for field " + field);
            } catch (IllegalArgumentException e) {
                fail("Could call method for field " + field);
            } catch (InvocationTargetException e) {
                fail("Could invoke method on target for field " + field);
            }
        }

        // Check for clear() behavior
        assertNotEquals(p3, p4);
        p3.clear();
        p4.clear();
        assertEquals("A field is missing from the clear() function", p3, p4);

        // A good hashCode() implementation should produce very few collisions. We added at most
        // 4*fields.length codes to the set. We'll say the implementation is good if we had at least
        // fields.length unique values.
        // TODO: Should the requirement be stronger than this?
        assertTrue(
                "Too many hash code collisions: " + hashCodes.size() + " out of " + (fields.length * 4),
                hashCodes.size() >= fields.length);
    }

    /**
     * Creates a valid sample instance of the given type. Used to simulate getters and setters.
     *
     * @param type
     *            The type to generate.
     * @param seed
     *            An integer seed, guaranteed to be positive. The same seed should generate two instances
     *            that are equal. A different seed should in general generate two instances that are not
     *            equal; this might not always be possible, such as with booleans or enums where there
     *            are limited possible values.
     * @return An instance of the specified type.
     */
    Object getSampleValueForType(Class<?> type, int seed) {
        if (type == Integer.TYPE) {
            return seed * 1000001;

        } else if (type == Boolean.TYPE) {
            return (seed % 2) == 0;

        } else if (type == BigDecimal.class) {
            if (seed == 0)
                return null;
            return new BigDecimal(seed * 1000002);

        } else if (type == String.class) {
            if (seed == 0)
                return null;
            return BigInteger.valueOf(seed * 1000003).toString(32);

        } else if (type == CompactStyle.class) {
            if (seed == 0)
                return null;
            CompactStyle[] values = CompactStyle.values();
            return values[seed % values.length];

        } else if (type == Currency.class) {
            if (seed == 0)
                return null;
            Object[] currencies = Currency.getAvailableCurrencies().toArray();
            return currencies[seed % currencies.length];

        } else if (type == CurrencyPluralInfo.class) {
            if (seed == 0)
                return null;
            ULocale[] locales = ULocale.getAvailableLocales();
            return CurrencyPluralInfo.getInstance(locales[seed % locales.length]);

        } else if (type == CurrencyUsage.class) {
            if (seed == 0)
                return null;
            CurrencyUsage[] values = CurrencyUsage.values();
            return values[seed % values.length];

        } else if (type == FormatWidth.class) {
            if (seed == 0)
                return null;
            FormatWidth[] values = FormatWidth.values();
            return values[seed % values.length];

        } else if (type == Map.class) {
            // Map<String,Map<String,String>> for compactCustomData property
            if (seed == 0)
                return null;
            Map<String, Map<String, String>> outer = new HashMap<String, Map<String, String>>();
            Map<String, String> inner = new HashMap<String, String>();
            inner.put("one", "0 thousand");
            StringBuilder magnitudeKey = new StringBuilder();
            magnitudeKey.append("1000");
            for (int i = 0; i < seed % 9; i++) {
                magnitudeKey.append("0");
            }
            outer.put(magnitudeKey.toString(), inner);
            return outer;

        } else if (type == MathContext.class) {
            if (seed == 0)
                return null;
            RoundingMode[] modes = RoundingMode.values();
            return new MathContext(seed, modes[seed % modes.length]);

        } else if (type == MeasureUnit.class) {
            if (seed == 0)
                return null;
            Object[] units = MeasureUnit.getAvailable().toArray();
            return units[seed % units.length];

        } else if (type == PadPosition.class) {
            if (seed == 0)
                return null;
            PadPosition[] values = PadPosition.values();
            return values[seed % values.length];

        } else if (type == ParseMode.class) {
            if (seed == 0)
                return null;
            ParseMode[] values = ParseMode.values();
            return values[seed % values.length];

        } else if (type == PluralRules.class) {
            if (seed == 0)
                return null;
            ULocale[] locales = PluralRules.getAvailableULocales();
            return PluralRules.forLocale(locales[seed % locales.length]);

        } else if (type == RoundingMode.class) {
            if (seed == 0)
                return null;
            RoundingMode[] values = RoundingMode.values();
            return values[seed % values.length];

        } else {
            fail("Don't know how to handle type "
                    + type
                    + ". Please add it to getSampleValueForType().");
            return null;
        }
    }

    @Test
    public void TestBasicSerializationRoundTrip() throws IOException, ClassNotFoundException {
        DecimalFormatProperties props0 = new DecimalFormatProperties();

        // Write values to some of the fields
        PatternStringParser.parseToExistingProperties("A-**####,#00.00#b¤", props0);

        // Write to byte stream
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ObjectOutputStream oos = new ObjectOutputStream(baos);
        oos.writeObject(props0);
        oos.flush();
        baos.close();
        byte[] bytes = baos.toByteArray();

        // Read from byte stream
        ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(bytes));
        Object obj = ois.readObject();
        ois.close();
        DecimalFormatProperties props1 = (DecimalFormatProperties) obj;

        // Test equality
        assertEquals("Did not round-trip through serialization", props0, props1);
    }

    /** Handler for serialization compatibility test suite. */
    public static class PropertiesHandler implements SerializableTestUtility.Handler {

        @Override
        public Object[] getTestObjects() {
            return new Object[] {
                    new DecimalFormatProperties(),
                    PatternStringParser.parseToProperties("x#,##0.00%"),
                    new DecimalFormatProperties().setCompactStyle(CompactStyle.LONG)
                            .setMinimumExponentDigits(2) };
        }

        @Override
        public boolean hasSameBehavior(Object a, Object b) {
            return a.equals(b);
        }
    }

    /**
     * Handler for the ICU 59 class named "Properties" before it was renamed to
     * "DecimalFormatProperties".
     */
    public static class ICU59PropertiesHandler implements SerializableTestUtility.Handler {

        @Override
        public Object[] getTestObjects() {
            return new Object[] { new com.ibm.icu.impl.number.Properties() };
        }

        @Override
        public boolean hasSameBehavior(Object a, Object b) {
            return true;
        }
    }
}
