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

import java.text.AttributedCharacterIterator;
import java.text.AttributedString;
import java.text.FieldPosition;
import java.text.Format;
import java.util.List;

import com.ibm.icu.text.ConstrainedFieldPosition;

/**
 * Implementation of FormattedValue based on FieldPositionIterator.
 *
 * In C++, this implements FormattedValue. In Java, it is a stateless
 * collection of static functions to avoid having to use nested objects.
 */
public class FormattedValueFieldPositionIteratorImpl {

    /** Do not construct instances of this class */
    private FormattedValueFieldPositionIteratorImpl() {}

    /** Helper class to keep track of fields with values in Java */
    private static class FieldWithValue extends Format.Field {
        private static final long serialVersionUID = -3850076447157793465L;

        public final Format.Field field;
        public final int value;

        public FieldWithValue(Format.Field field, int value) {
            super(field.toString());
            this.field = field;
            this.value = value;
        }
    }

    public static boolean nextPosition(List<FieldPosition> attributes, ConstrainedFieldPosition cfpos) {
        int numFields = attributes.size();
        int i = (int) cfpos.getInt64IterationContext();
        for (; i < numFields; i++) {
            FieldPosition fpos = attributes.get(i);
            Format.Field field = fpos.getFieldAttribute();
            Object value = null;
            if (field instanceof FieldWithValue) {
                value = ((FieldWithValue) field).value;
                field = ((FieldWithValue) field).field;
            }
            if (cfpos.matchesField(field, value)) {
                int start = fpos.getBeginIndex();
                int limit = fpos.getEndIndex();
                cfpos.setState(field, value, start, limit);
                break;
            }
        }
        cfpos.setInt64IterationContext(i == numFields ? i : i + 1);
        return i < numFields;
    }

    public static AttributedCharacterIterator toCharacterIterator(CharSequence cs, List<FieldPosition> attributes) {
        AttributedString as = new AttributedString(cs.toString());

        // add attributes to the AttributedString
        for (int i = 0; i < attributes.size(); i++) {
            FieldPosition fp = attributes.get(i);
            Format.Field field = fp.getFieldAttribute();
            Object value = field;
            if (field instanceof FieldWithValue) {
                value = ((FieldWithValue) field).value;
                field = ((FieldWithValue) field).field;
            }
            as.addAttribute(field, value, fp.getBeginIndex(), fp.getEndIndex());
        }

        // return the CharacterIterator from AttributedString
        return as.getIterator();
    }

    public static void addOverlapSpans(List<FieldPosition> attributes, Format.Field spanField, int firstIndex) {
        // In order to avoid fancy data structures, this is an O(N^2) algorithm,
        // which should be fine for all real-life applications of this function.
        int s1a = Integer.MAX_VALUE;
        int s1b = 0;
        int s2a = Integer.MAX_VALUE;
        int s2b = 0;
        int numFields = attributes.size();
        for (int i = 0; i<numFields; i++) {
            FieldPosition fp1 = attributes.get(i);
            for (int j = i + 1; j<numFields; j++) {
                FieldPosition fp2 = attributes.get(j);
                if (fp1.getFieldAttribute() != fp2.getFieldAttribute()) {
                    continue;
                }
                // Found a duplicate
                s1a = Math.min(s1a, fp1.getBeginIndex());
                s1b = Math.max(s1b, fp1.getEndIndex());
                s2a = Math.min(s2a, fp2.getBeginIndex());
                s2b = Math.max(s2b, fp2.getEndIndex());
                break;
            }
        }
        if (s1a != Integer.MAX_VALUE) {
            // Success: add the two span fields
            FieldPosition newPos = new FieldPosition(new FieldWithValue(spanField, firstIndex));
            newPos.setBeginIndex(s1a);
            newPos.setEndIndex(s1b);
            attributes.add(newPos);
            newPos = new FieldPosition(new FieldWithValue(spanField, 1 - firstIndex));
            newPos.setBeginIndex(s2a);
            newPos.setEndIndex(s2b);
            attributes.add(newPos);
        }
    }

    public static void sort(List<FieldPosition> attributes) {
        // Use bubble sort, O(N^2) but easy and no fancy data structures.
        int numFields = attributes.size();
        while (true) {
            boolean isSorted = true;
            for (int i=0; i<numFields-1; i++) {
                FieldPosition fp1 = attributes.get(i);
                FieldPosition fp2 = attributes.get(i + 1);
                long comparison = 0;
                if (fp1.getBeginIndex() != fp2.getBeginIndex()) {
                    // Higher start index -> higher rank
                    comparison = fp2.getBeginIndex() - fp1.getBeginIndex();
                } else if (fp1.getEndIndex() != fp2.getEndIndex()) {
                    // Higher length (end index) -> lower rank
                    comparison = fp1.getEndIndex() - fp2.getEndIndex();
                } else if (fp1.getFieldAttribute() != fp2.getFieldAttribute()) {
                    // Span category -> lower rank
                    // Pick other orders arbitrarily
                    boolean fp1isSpan = fp1.getFieldAttribute() instanceof FieldWithValue;
                    boolean fp2isSpan = fp2.getFieldAttribute() instanceof FieldWithValue;
                    if (fp1isSpan && !fp2isSpan) {
                        comparison = 1;
                    } else if (fp2isSpan && !fp1isSpan) {
                        comparison = -1;
                    } else {
                        comparison = fp1.hashCode() - fp2.hashCode();
                    }
                }
                if (comparison < 0) {
                    // Perform a swap
                    isSorted = false;
                    attributes.set(i, fp2);
                    attributes.set(i + 1, fp1);
                }
            }
            if (isSorted) {
                break;
            }
        }
    }
}
