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

import java.text.Format.Field;

import com.ibm.icu.impl.SimpleFormatterImpl;
import com.ibm.icu.impl.number.range.PrefixInfixSuffixLengthHelper;
import com.ibm.icu.util.ICUException;

/**
 * The second primary implementation of {@link Modifier}, this one consuming a
 * {@link com.ibm.icu.text.SimpleFormatter} pattern.
 */
public class SimpleModifier implements Modifier {
    private final String compiledPattern;
    private final Field field;
    private final boolean strong;
    private final int prefixLength;
    private final int suffixOffset;
    private final int suffixLength;

    // Parameters: used for number range formatting
    private final Parameters parameters;

    /** TODO: This is copied from SimpleFormatterImpl. */
    private static final int ARG_NUM_LIMIT = 0x100;

    /** Creates a modifier that uses the SimpleFormatter string formats. */
    public SimpleModifier(String compiledPattern, Field field, boolean strong) {
        this(compiledPattern, field, strong, null);
    }

    /** Creates a modifier that uses the SimpleFormatter string formats. */
    public SimpleModifier(String compiledPattern, Field field, boolean strong, Parameters parameters) {
        assert compiledPattern != null;
        this.compiledPattern = compiledPattern;
        this.field = field;
        this.strong = strong;
        this.parameters = parameters;

        int argLimit = SimpleFormatterImpl.getArgumentLimit(compiledPattern);
        if (argLimit == 0) {
            // No arguments in compiled pattern
            prefixLength = compiledPattern.charAt(1) - ARG_NUM_LIMIT;
            assert 2 + prefixLength == compiledPattern.length();
            // Set suffixOffset = -1 to indicate no arguments in compiled pattern.
            suffixOffset = -1;
            suffixLength = 0;
        } else {
            assert argLimit == 1;
            if (compiledPattern.charAt(1) != '\u0000') {
                prefixLength = compiledPattern.charAt(1) - ARG_NUM_LIMIT;
                suffixOffset = 3 + prefixLength;
            } else {
                prefixLength = 0;
                suffixOffset = 2;
            }
            if (3 + prefixLength < compiledPattern.length()) {
                suffixLength = compiledPattern.charAt(suffixOffset) - ARG_NUM_LIMIT;
            } else {
                suffixLength = 0;
            }
        }
    }

    @Override
    public int apply(NumberStringBuilder output, int leftIndex, int rightIndex) {
        return formatAsPrefixSuffix(output, leftIndex, rightIndex);
    }

    @Override
    public int getPrefixLength() {
        return prefixLength;
    }

    @Override
    public int getCodePointCount() {
        int count = 0;
        if (prefixLength > 0) {
            count += Character.codePointCount(compiledPattern, 2, 2 + prefixLength);
        }
        if (suffixLength > 0) {
            count += Character
                    .codePointCount(compiledPattern, 1 + suffixOffset, 1 + suffixOffset + suffixLength);
        }
        return count;
    }

    @Override
    public boolean isStrong() {
        return strong;
    }

    @Override
    public boolean containsField(Field field) {
        // This method is not currently used.
        assert false;
        return false;
    }

    @Override
    public Parameters getParameters() {
        return parameters;
    }

    @Override
    public boolean semanticallyEquivalent(Modifier other) {
        if (!(other instanceof SimpleModifier)) {
            return false;
        }
        SimpleModifier _other = (SimpleModifier) other;
        if (parameters != null && _other.parameters != null && parameters.obj == _other.parameters.obj) {
            return true;
        }
        return compiledPattern.equals(_other.compiledPattern) && field == _other.field && strong == _other.strong;
    }

    /**
     * TODO: This belongs in SimpleFormatterImpl. The only reason I haven't moved it there yet is because
     * DoubleSidedStringBuilder is an internal class and SimpleFormatterImpl feels like it should not
     * depend on it.
     *
     * <p>
     * Formats a value that is already stored inside the StringBuilder <code>result</code> between the
     * indices <code>startIndex</code> and <code>endIndex</code> by inserting characters before the start
     * index and after the end index.
     *
     * <p>
     * This is well-defined only for patterns with exactly one argument.
     *
     * @param result
     *            The StringBuilder containing the value argument.
     * @param startIndex
     *            The left index of the value within the string builder.
     * @param endIndex
     *            The right index of the value within the string builder.
     * @return The number of characters (UTF-16 code points) that were added to the StringBuilder.
     */
    public int formatAsPrefixSuffix(
            NumberStringBuilder result,
            int startIndex,
            int endIndex) {
        if (suffixOffset == -1) {
            // There is no argument for the inner number; overwrite the entire segment with our string.
            return result.splice(startIndex, endIndex, compiledPattern, 2, 2 + prefixLength, field);
        } else {
            if (prefixLength > 0) {
                result.insert(startIndex, compiledPattern, 2, 2 + prefixLength, field);
            }
            if (suffixLength > 0) {
                result.insert(endIndex + prefixLength,
                        compiledPattern,
                        1 + suffixOffset,
                        1 + suffixOffset + suffixLength,
                        field);
            }
            return prefixLength + suffixLength;
        }
    }

    /**
     * TODO: Like above, this belongs with the rest of the SimpleFormatterImpl code.
     * I put it here so that the SimpleFormatter uses in NumberStringBuilder are near each other.
     *
     * <p>
     * Applies the compiled two-argument pattern to the NumberStringBuilder.
     *
     * <p>
     * This method is optimized for the case where the prefix and suffix are often empty, such as
     * in the range pattern like "{0}-{1}".
     */
    public static void formatTwoArgPattern(String compiledPattern, NumberStringBuilder result, int index, PrefixInfixSuffixLengthHelper h,
            Field field) {
        int argLimit = SimpleFormatterImpl.getArgumentLimit(compiledPattern);
        if (argLimit != 2) {
            throw new ICUException();
        }
        int offset = 1; // offset into compiledPattern
        int length = 0; // chars added to result

        int prefixLength = compiledPattern.charAt(offset);
        offset++;
        if (prefixLength < ARG_NUM_LIMIT) {
            // No prefix
            prefixLength = 0;
        } else {
            prefixLength -= ARG_NUM_LIMIT;
            result.insert(index + length, compiledPattern, offset, offset + prefixLength, field);
            offset += prefixLength;
            length += prefixLength;
            offset++;
        }

        int infixLength = compiledPattern.charAt(offset);
        offset++;
        if (infixLength < ARG_NUM_LIMIT) {
            // No infix
            infixLength = 0;
        } else {
            infixLength -= ARG_NUM_LIMIT;
            result.insert(index + length, compiledPattern, offset, offset + infixLength, field);
            offset += infixLength;
            length += infixLength;
            offset++;
        }

        int suffixLength;
        if (offset == compiledPattern.length()) {
            // No suffix
            suffixLength = 0;
        } else {
            suffixLength = compiledPattern.charAt(offset) -  ARG_NUM_LIMIT;
            offset++;
            result.insert(index + length, compiledPattern, offset, offset + suffixLength, field);
            length += suffixLength;
        }

        h.lengthPrefix = prefixLength;
        h.lengthInfix = infixLength;
        h.lengthSuffix = suffixLength;
    }
}
