// © 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 com.ibm.icu.impl.FormattedStringBuilder;
import com.ibm.icu.impl.StandardPlural;
import com.ibm.icu.impl.number.AffixUtils.SymbolProvider;
import com.ibm.icu.number.NumberFormatter.SignDisplay;
import com.ibm.icu.number.NumberFormatter.UnitWidth;
import com.ibm.icu.text.DecimalFormatSymbols;
import com.ibm.icu.text.NumberFormat.Field;
import com.ibm.icu.text.PluralRules;
import com.ibm.icu.util.Currency;

/**
 * This class is a {@link Modifier} that wraps a decimal format pattern. It applies the pattern's affixes
 * in {@link Modifier#apply}.
 *
 * <p>
 * In addition to being a Modifier, this class contains the business logic for substituting the correct
 * locale symbols into the affixes of the decimal format pattern.
 *
 * <p>
 * In order to use this class, create a new instance and call the following four setters:
 * {@link #setPatternInfo}, {@link #setPatternAttributes}, {@link #setSymbols}, and
 * {@link #setNumberProperties}. After calling these four setters, the instance will be ready for use as
 * a Modifier.
 *
 * <p>
 * This is a MUTABLE, NON-THREAD-SAFE class designed for performance. Do NOT save references to this or
 * attempt to use it from multiple threads! Instead, you can obtain a safe, immutable decimal format
 * pattern modifier by calling {@link MutablePatternModifier#createImmutable}, in effect treating this
 * instance as a builder for the immutable variant.
 */
public class MutablePatternModifier implements Modifier, SymbolProvider, MicroPropsGenerator {

    // Modifier details
    final boolean isStrong;

    // Pattern details
    AffixPatternProvider patternInfo;
    Field field;
    SignDisplay signDisplay;
    boolean perMilleReplacesPercent;

    // Symbol details
    DecimalFormatSymbols symbols;
    UnitWidth unitWidth;
    Currency currency;
    PluralRules rules;

    // Number details
    Signum signum;
    StandardPlural plural;

    // QuantityChain details
    MicroPropsGenerator parent;

    // Transient fields for rendering
    StringBuilder currentAffix;

    /**
     * @param isStrong
     *            Whether the modifier should be considered strong. For more information, see
     *            {@link Modifier#isStrong()}. Most of the time, decimal format pattern modifiers should
     *            be considered as non-strong.
     */
    public MutablePatternModifier(boolean isStrong) {
        this.isStrong = isStrong;
    }

    /**
     * Sets a reference to the parsed decimal format pattern, usually obtained from
     * {@link PatternStringParser#parseToPatternInfo(String)}, but any implementation of
     * {@link AffixPatternProvider} is accepted.
     *
     * @param field
     *            Which field to use for literal characters in the pattern.
     */
    public void setPatternInfo(AffixPatternProvider patternInfo, Field field) {
        this.patternInfo = patternInfo;
        this.field = field;
    }

    /**
     * Sets attributes that imply changes to the literal interpretation of the pattern string affixes.
     *
     * @param signDisplay
     *            Whether to force a plus sign on positive numbers.
     * @param perMille
     *            Whether to substitute the percent sign in the pattern with a permille sign.
     */
    public void setPatternAttributes(SignDisplay signDisplay, boolean perMille) {
        this.signDisplay = signDisplay;
        this.perMilleReplacesPercent = perMille;
    }

    /**
     * Sets locale-specific details that affect the symbols substituted into the pattern string affixes.
     *
     * @param symbols
     *            The desired instance of DecimalFormatSymbols.
     * @param currency
     *            The currency to be used when substituting currency values into the affixes.
     * @param unitWidth
     *            The width used to render currencies.
     * @param rules
     *            Required if the triple currency sign, "¤¤¤", appears in the pattern, which can be
     *            determined from the convenience method {@link #needsPlurals()}.
     */
    public void setSymbols(
            DecimalFormatSymbols symbols,
            Currency currency,
            UnitWidth unitWidth,
            PluralRules rules) {
        assert (rules != null) == needsPlurals();
        this.symbols = symbols;
        this.currency = currency;
        this.unitWidth = unitWidth;
        this.rules = rules;
    }

    /**
     * Sets attributes of the current number being processed.
     *
     * @param signum
     *            -1 if negative; +1 if positive; or 0 if zero.
     * @param plural
     *            The plural form of the number, required only if the pattern contains the triple
     *            currency sign, "¤¤¤" (and as indicated by {@link #needsPlurals()}).
     */
    public void setNumberProperties(Signum signum, StandardPlural plural) {
        assert (plural != null) == needsPlurals();
        this.signum = signum;
        this.plural = plural;
    }

    /**
     * Returns true if the pattern represented by this MurkyModifier requires a plural keyword in order
     * to localize. This is currently true only if there is a currency long name placeholder in the
     * pattern ("¤¤¤").
     */
    public boolean needsPlurals() {
        return patternInfo.containsSymbolType(AffixUtils.TYPE_CURRENCY_TRIPLE);
    }

    /**
     * Creates a new quantity-dependent Modifier that behaves the same as the current instance, but which
     * is immutable and can be saved for future use. The number properties in the current instance are
     * mutated; all other properties are left untouched.
     *
     * <p>
     * The resulting modifier cannot be used in a QuantityChain.
     *
     * @return An immutable that supports both positive and negative numbers.
     */
    public ImmutablePatternModifier createImmutable() {
        FormattedStringBuilder a = new FormattedStringBuilder();
        FormattedStringBuilder b = new FormattedStringBuilder();
        if (needsPlurals()) {
            // Slower path when we require the plural keyword.
            AdoptingModifierStore pm = new AdoptingModifierStore();
            for (StandardPlural plural : StandardPlural.VALUES) {
                setNumberProperties(Signum.POS, plural);
                pm.setModifier(Signum.POS, plural, createConstantModifier(a, b));
                setNumberProperties(Signum.POS_ZERO, plural);
                pm.setModifier(Signum.POS_ZERO, plural, createConstantModifier(a, b));
                setNumberProperties(Signum.NEG_ZERO, plural);
                pm.setModifier(Signum.NEG_ZERO, plural, createConstantModifier(a, b));
                setNumberProperties(Signum.NEG, plural);
                pm.setModifier(Signum.NEG, plural, createConstantModifier(a, b));
            }
            pm.freeze();
            return new ImmutablePatternModifier(pm, rules);
        } else {
            // Faster path when plural keyword is not needed.
            setNumberProperties(Signum.POS, null);
            Modifier positive = createConstantModifier(a, b);
            setNumberProperties(Signum.POS_ZERO, null);
            Modifier posZero = createConstantModifier(a, b);
            setNumberProperties(Signum.NEG_ZERO, null);
            Modifier negZero = createConstantModifier(a, b);
            setNumberProperties(Signum.NEG, null);
            Modifier negative = createConstantModifier(a, b);
            AdoptingModifierStore pm = new AdoptingModifierStore(positive, posZero, negZero, negative);
            return new ImmutablePatternModifier(pm, null);
        }
    }

    /**
     * Uses the current properties to create a single {@link ConstantMultiFieldModifier} with currency
     * spacing support if required.
     *
     * @param a
     *            A working FormattedStringBuilder object; passed from the outside to prevent the need to
     *            create many new instances if this method is called in a loop.
     * @param b
     *            Another working FormattedStringBuilder object.
     * @return The constant modifier object.
     */
    private ConstantMultiFieldModifier createConstantModifier(
            FormattedStringBuilder a,
            FormattedStringBuilder b) {
        insertPrefix(a.clear(), 0);
        insertSuffix(b.clear(), 0);
        if (patternInfo.hasCurrencySign()) {
            return new CurrencySpacingEnabledModifier(a, b, !patternInfo.hasBody(), isStrong, symbols);
        } else {
            return new ConstantMultiFieldModifier(a, b, !patternInfo.hasBody(), isStrong);
        }
    }

    public static class ImmutablePatternModifier implements MicroPropsGenerator {
        final AdoptingModifierStore pm;
        final PluralRules rules;
        /* final */ MicroPropsGenerator parent;

        ImmutablePatternModifier(
                AdoptingModifierStore pm,
                PluralRules rules) {
            this.pm = pm;
            this.rules = rules;
            this.parent = null;
        }

        public ImmutablePatternModifier addToChain(MicroPropsGenerator parent) {
            this.parent = parent;
            return this;
        }

        @Override
        public MicroProps processQuantity(DecimalQuantity quantity) {
            MicroProps micros = parent.processQuantity(quantity);
            if (micros.modMiddle != null) {
                return micros;
            }
            applyToMicros(micros, quantity);
            return micros;
        }

        public void applyToMicros(MicroProps micros, DecimalQuantity quantity) {
            if (rules == null) {
                micros.modMiddle = pm.getModifierWithoutPlural(quantity.signum());
            } else {
                StandardPlural pluralForm = RoundingUtils.getPluralSafe(micros.rounder, rules, quantity);
                micros.modMiddle = pm.getModifier(quantity.signum(), pluralForm);
            }
        }

        // NOTE: This method is not used in ICU4J right now.
        // In ICU4C, it is used by getPrefixSuffix().
        // Un-comment this method when getPrefixSuffix() is cleaned up in ICU4J.
        // public Modifier getModifier(byte signum, StandardPlural plural) {
        // if (rules == null) {
        // return pm.getModifier(signum);
        // } else {
        // return pm.getModifier(signum, plural);
        // }
        // }
    }

    /** Used by the unsafe code path. */
    public MicroPropsGenerator addToChain(MicroPropsGenerator parent) {
        this.parent = parent;
        return this;
    }

    @Override
    public MicroProps processQuantity(DecimalQuantity fq) {
        MicroProps micros = parent.processQuantity(fq);
        if (micros.modMiddle != null) {
            return micros;
        }
        if (needsPlurals()) {
            StandardPlural pluralForm = RoundingUtils.getPluralSafe(micros.rounder, rules, fq);
            setNumberProperties(fq.signum(), pluralForm);
        } else {
            setNumberProperties(fq.signum(), null);
        }
        micros.modMiddle = this;
        return micros;
    }

    @Override
    public int apply(FormattedStringBuilder output, int leftIndex, int rightIndex) {
        int prefixLen = insertPrefix(output, leftIndex);
        int suffixLen = insertSuffix(output, rightIndex + prefixLen);
        // If the pattern had no decimal stem body (like #,##0.00), overwrite the value.
        int overwriteLen = 0;
        if (!patternInfo.hasBody()) {
            overwriteLen = output.splice(leftIndex + prefixLen, rightIndex + prefixLen, "", 0, 0, null);
        }
        CurrencySpacingEnabledModifier.applyCurrencySpacing(output,
                leftIndex,
                prefixLen,
                rightIndex + prefixLen + overwriteLen,
                suffixLen,
                symbols);
        return prefixLen + overwriteLen + suffixLen;
    }

    @Override
    public int getPrefixLength() {
        // Render the affix to get the length
        prepareAffix(true);
        int result = AffixUtils.unescapedCount(currentAffix, true, this); // prefix length
        return result;
    }

    @Override
    public int getCodePointCount() {
        // Render the affixes to get the length
        prepareAffix(true);
        int result = AffixUtils.unescapedCount(currentAffix, false, this); // prefix length
        prepareAffix(false);
        result += AffixUtils.unescapedCount(currentAffix, false, this); // suffix length
        return result;
    }

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

    @Override
    public boolean containsField(java.text.Format.Field field) {
        // This method is not currently used. (unsafe path not used in range formatting)
        assert false;
        return false;
    }

    @Override
    public Parameters getParameters() {
        // This method is not currently used.
        assert false;
        return null;
    }

    @Override
    public boolean semanticallyEquivalent(Modifier other) {
        // This method is not currently used. (unsafe path not used in range formatting)
        assert false;
        return false;
    }

    private int insertPrefix(FormattedStringBuilder sb, int position) {
        prepareAffix(true);
        int length = AffixUtils.unescape(currentAffix, sb, position, this, field);
        return length;
    }

    private int insertSuffix(FormattedStringBuilder sb, int position) {
        prepareAffix(false);
        int length = AffixUtils.unescape(currentAffix, sb, position, this, field);
        return length;
    }

    /**
     * Pre-processes the prefix or suffix into the currentAffix field, creating and mutating that field
     * if necessary. Calls down to {@link PatternStringUtils#affixPatternProviderToStringBuilder}.
     *
     * @param isPrefix
     *            true to prepare the prefix; false to prepare the suffix.
     */
    private void prepareAffix(boolean isPrefix) {
        if (currentAffix == null) {
            currentAffix = new StringBuilder();
        }
        PatternStringUtils.patternInfoToStringBuilder(patternInfo,
                isPrefix,
                PatternStringUtils.resolveSignDisplay(signDisplay, signum),
                plural,
                perMilleReplacesPercent,
                currentAffix);
    }

    /**
     * Returns the string that substitutes a given symbol type in a pattern.
     */
    @Override
    public CharSequence getSymbol(int type) {
        switch (type) {
        case AffixUtils.TYPE_MINUS_SIGN:
            return symbols.getMinusSignString();
        case AffixUtils.TYPE_PLUS_SIGN:
            return symbols.getPlusSignString();
        case AffixUtils.TYPE_PERCENT:
            return symbols.getPercentString();
        case AffixUtils.TYPE_PERMILLE:
            return symbols.getPerMillString();
        case AffixUtils.TYPE_CURRENCY_SINGLE:
            // UnitWidth ISO, HIDDEN, or NARROW overrides the singular currency symbol.
            if (unitWidth == UnitWidth.ISO_CODE) {
                return currency.getCurrencyCode();
            } else if (unitWidth == UnitWidth.HIDDEN) {
                return "";
            } else {
                int selector = unitWidth == UnitWidth.NARROW ? Currency.NARROW_SYMBOL_NAME
                        : Currency.SYMBOL_NAME;
                return currency.getName(symbols.getULocale(), selector, null);
            }
        case AffixUtils.TYPE_CURRENCY_DOUBLE:
            return currency.getCurrencyCode();
        case AffixUtils.TYPE_CURRENCY_TRIPLE:
            // NOTE: This is the code path only for patterns containing "¤¤¤".
            // Plural currencies set via the API are formatted in LongNameHandler.
            // This code path is used by DecimalFormat via CurrencyPluralInfo.
            assert plural != null;
            return currency
                    .getName(symbols.getULocale(), Currency.PLURAL_LONG_NAME, plural.getKeyword(), null);
        case AffixUtils.TYPE_CURRENCY_QUAD:
            return "\uFFFD";
        case AffixUtils.TYPE_CURRENCY_QUINT:
            return currency.getName(symbols.getULocale(), Currency.NARROW_SYMBOL_NAME, null);
        default:
            throw new AssertionError();
        }
    }
}
