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

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

import java.math.BigDecimal;
import java.text.AttributedCharacterIterator;
import java.text.Format;
import java.text.Format.Field;
import java.util.HashSet;
import java.util.Set;

import org.junit.Test;

import com.ibm.icu.text.ConstrainedFieldPosition;
import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.FormattedValue;
import com.ibm.icu.text.NumberFormat;

/**
 * @author sffc
 */
public class FormattedValueTest {
    @Test
    public void testBasic() {
        ConstrainedFieldPosition cfpos = new ConstrainedFieldPosition();
        assertAllPartsEqual(
            "basic",
            cfpos,
            7,
            null,
            null,
            0,
            0,
            0L);
    }

    @Test
    public void testSetters() {
        ConstrainedFieldPosition cfpos = new ConstrainedFieldPosition();

        cfpos.constrainField(NumberFormat.Field.COMPACT);
        assertAllPartsEqual(
            "setters 1",
            cfpos,
            2,
            NumberFormat.Field.COMPACT,
            null,
            0,
            0,
            0L);

        cfpos.constrainClass(NumberFormat.Field.class);
        assertAllPartsEqual(
            "setters 1.5",
            cfpos,
            3,
            null,
            null,
            0,
            0,
            0L);

        cfpos.setInt64IterationContext(42424242424242L);
        assertAllPartsEqual(
            "setters 2",
            cfpos,
            3,
            null,
            null,
            0,
            0,
            42424242424242L);

        cfpos.setState(NumberFormat.Field.COMPACT, BigDecimal.ONE, 5, 10);
        assertAllPartsEqual(
            "setters 3",
            cfpos,
            3,
            NumberFormat.Field.COMPACT,
            BigDecimal.ONE,
            5,
            10,
            42424242424242L);

        cfpos.reset();
        assertAllPartsEqual(
            "setters 4",
            cfpos,
            7,
            null,
            null,
            0,
            0,
            0L);
    }

    @Test
    public void testIllegalArgumentException() {
        ConstrainedFieldPosition cfpos = new ConstrainedFieldPosition();
        try {
            cfpos.matchesField(null);
            fail("Expected an IllegalArgumentException");
        } catch (IllegalArgumentException e) {
            // pass
        }
    }

    private void assertAllPartsEqual(
            String messagePrefix,
            ConstrainedFieldPosition cfpos,
            int matching,
            Field field,
            Object value,
            int start,
            int limit,
            long context) {
        assertEquals(messagePrefix + ": field", field, cfpos.getField());
        assertEquals(messagePrefix + ": field value", value, cfpos.getFieldValue());
        assertEquals(messagePrefix + ": start", start, cfpos.getStart());
        assertEquals(messagePrefix + ": limit", limit, cfpos.getLimit());
        assertEquals(messagePrefix + ": context", context, cfpos.getInt64IterationContext());

        assertEquals(messagePrefix + ": integer field",
            ((matching & 1) != 0), cfpos.matchesField(NumberFormat.Field.INTEGER));
        assertEquals(messagePrefix + ": compact field",
            ((matching & 2) != 0), cfpos.matchesField(NumberFormat.Field.COMPACT));
        assertEquals(messagePrefix + ": date field",
            ((matching & 4) != 0), cfpos.matchesField(DateFormat.Field.AM_PM));
    }

    public static void checkFormattedValue(String message, FormattedValue fv, String expectedString,
            Object[][] expectedFieldPositions) {
        // Calculate some initial expected values
        int stringLength = fv.toString().length();
        HashSet<Format.Field> uniqueFields = new HashSet<>();
        Set<Class<?>> uniqueFieldClasses = new HashSet<>();
        for (int i=0; i<expectedFieldPositions.length; i++) {
            uniqueFields.add((Format.Field) expectedFieldPositions[i][0]);
            uniqueFieldClasses.add(expectedFieldPositions[i][0].getClass());
        }
        String baseMessage = message + ": " + fv.toString() + ": ";

        // Check the String and CharSequence
        assertEquals(baseMessage + " string", expectedString, fv.toString());
        assertCharSequenceEquals(expectedString, fv);

        // Check the AttributedCharacterIterator
        AttributedCharacterIterator fpi = fv.toCharacterIterator();
        Set<AttributedCharacterIterator.Attribute> allAttributes = fpi.getAllAttributeKeys();
        assertEquals(baseMessage + "All known fields should be in the iterator", uniqueFields.size(), allAttributes.size());
        assertEquals(baseMessage + "Iterator should have length of string output", stringLength, fpi.getEndIndex());
        int i = 0;
        for (char c = fpi.first(); c != AttributedCharacterIterator.DONE; c = fpi.next(), i++) {
            Set<AttributedCharacterIterator.Attribute> currentAttributes = fpi.getAttributes().keySet();
            int attributesRemaining = currentAttributes.size();
            for (Object[] cas : expectedFieldPositions) {
                Format.Field expectedField = (Format.Field) cas[0];
                int expectedBeginIndex = (Integer) cas[1];
                int expectedEndIndex = (Integer) cas[2];
                if (expectedBeginIndex > i || expectedEndIndex <= i) {
                    // Field position does not overlap with the current character
                    continue;
                }

                assertTrue(baseMessage + "Character at " + i + " should have field " + expectedField,
                        currentAttributes.contains(expectedField));
                assertTrue(baseMessage + "Field " + expectedField + " should be a known attribute",
                        allAttributes.contains(expectedField));
                int actualBeginIndex = fpi.getRunStart(expectedField);
                int actualEndIndex = fpi.getRunLimit(expectedField);
                assertEquals(baseMessage + expectedField + " begin @" + i, expectedBeginIndex, actualBeginIndex);
                assertEquals(baseMessage + expectedField + " end @" + i, expectedEndIndex, actualEndIndex);
                attributesRemaining--;
            }
            assertEquals(baseMessage + "Should have looked at every field: " + i + ": " + currentAttributes,
                    0, attributesRemaining);
        }
        assertEquals(baseMessage + "Should have looked at every character", stringLength, i);

        // Check nextPosition over all fields
        ConstrainedFieldPosition cfpos = new ConstrainedFieldPosition();
        i = 0;
        for (Object[] cas : expectedFieldPositions) {
            assertTrue(baseMessage + i, fv.nextPosition(cfpos));
            Format.Field expectedField = (Format.Field) cas[0];
            int expectedStart = (Integer) cas[1];
            int expectedLimit = (Integer) cas[2];
            assertEquals(baseMessage + "field " + i, expectedField, cfpos.getField());
            assertEquals(baseMessage + "start " + i, expectedStart, cfpos.getStart());
            assertEquals(baseMessage + "limit " + i, expectedLimit, cfpos.getLimit());
            i++;
        }
        boolean afterLoopResult = fv.nextPosition(cfpos);
        assertFalse(baseMessage + "after loop: " + cfpos, afterLoopResult);

        // Check nextPosition constrained over each class one at a time
        for (Class<?> classConstraint : uniqueFieldClasses) {
            cfpos.reset();
            cfpos.constrainClass(classConstraint);
            i = 0;
            for (Object[] cas : expectedFieldPositions) {
                if (cas[0].getClass() != classConstraint) {
                    continue;
                }
                assertTrue(baseMessage + i, fv.nextPosition(cfpos));
                Format.Field expectedField = (Format.Field) cas[0];
                int expectedStart = (Integer) cas[1];
                int expectedLimit = (Integer) cas[2];
                assertEquals(baseMessage + "field " + i, expectedField, cfpos.getField());
                assertEquals(baseMessage + "start " + i, expectedStart, cfpos.getStart());
                assertEquals(baseMessage + "limit " + i, expectedLimit, cfpos.getLimit());
                i++;
            }
            afterLoopResult = fv.nextPosition(cfpos);
            assertFalse(baseMessage + "after loop: " + cfpos, afterLoopResult);
        }

        // Check nextPosition constrained over an unrelated class
        cfpos.reset();
        cfpos.constrainClass(HashSet.class);
        assertFalse(baseMessage + "unrelated class", fv.nextPosition(cfpos));

        // Check nextPosition constrained over each field one at a time
        for (Format.Field field : uniqueFields) {
            cfpos.reset();
            cfpos.constrainField(field);
            i = 0;
            for (Object[] cas : expectedFieldPositions) {
                if (cas[0] != field) {
                    continue;
                }
                assertTrue(baseMessage + i, fv.nextPosition(cfpos));
                Format.Field expectedField = (Format.Field) cas[0];
                int expectedStart = (Integer) cas[1];
                int expectedLimit = (Integer) cas[2];
                assertEquals(baseMessage + "field " + i, expectedField, cfpos.getField());
                assertEquals(baseMessage + "start " + i, expectedStart, cfpos.getStart());
                assertEquals(baseMessage + "limit " + i, expectedLimit, cfpos.getLimit());
                i++;
            }
            afterLoopResult = fv.nextPosition(cfpos);
            assertFalse(baseMessage + "after loop: " + cfpos, afterLoopResult);
        }
    }

    public static void assertCharSequenceEquals(CharSequence a, CharSequence b) {
        assertEquals(a.toString(), b.toString());

        assertEquals(a.length(), b.length());
        for (int i = 0; i < a.length(); i++) {
            assertEquals(a.charAt(i), b.charAt(i));
        }

        int start = Math.min(2, a.length());
        int end = Math.min(8, a.length());
        if (start != end) {
            assertCharSequenceEquals(a.subSequence(start, end), b.subSequence(start, end));
        }
    }
}
