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

import java.math.RoundingMode;

import com.ibm.icu.impl.number.MacroProps;
import com.ibm.icu.impl.number.Padder;
import com.ibm.icu.number.NumberFormatter.DecimalSeparatorDisplay;
import com.ibm.icu.number.NumberFormatter.GroupingStrategy;
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.NumberingSystem;
import com.ibm.icu.util.Currency;
import com.ibm.icu.util.Measure;
import com.ibm.icu.util.MeasureUnit;
import com.ibm.icu.util.NoUnit;
import com.ibm.icu.util.ULocale;

/**
 * An abstract base class for specifying settings related to number formatting. This class is implemented
 * by {@link UnlocalizedNumberFormatter} and {@link LocalizedNumberFormatter}. This class is not intended
 * for public subclassing.
 *
 * @stable ICU 60
 * @see NumberFormatter
 */
public abstract class NumberFormatterSettings<T extends NumberFormatterSettings<?>> {

    static final int KEY_MACROS = 0;
    static final int KEY_LOCALE = 1;
    static final int KEY_NOTATION = 2;
    static final int KEY_UNIT = 3;
    static final int KEY_PRECISION = 4;
    static final int KEY_ROUNDING_MODE = 5;
    static final int KEY_GROUPING = 6;
    static final int KEY_PADDER = 7;
    static final int KEY_INTEGER = 8;
    static final int KEY_SYMBOLS = 9;
    static final int KEY_UNIT_WIDTH = 10;
    static final int KEY_SIGN = 11;
    static final int KEY_DECIMAL = 12;
    static final int KEY_SCALE = 13;
    static final int KEY_THRESHOLD = 14;
    static final int KEY_PER_UNIT = 15;
    static final int KEY_USAGE = 16;
    static final int KEY_MAX = 17;

    private final NumberFormatterSettings<?> parent;
    private final int key;
    private final Object value;
    private volatile MacroProps resolvedMacros;

    NumberFormatterSettings(NumberFormatterSettings<?> parent, int key, Object value) {
        this.parent = parent;
        this.key = key;
        this.value = value;
    }

    /**
     * Specifies the notation style (simple, scientific, or compact) for rendering numbers.
     *
     * <ul>
     * <li>Simple notation: "12,300"
     * <li>Scientific notation: "1.23E4"
     * <li>Compact notation: "12K"
     * </ul>
     *
     * <p>
     * All notation styles will be properly localized with locale data, and all notation styles are
     * compatible with units, rounding strategies, and other number formatter settings.
     *
     * <p>
     * Pass this method the return value of a {@link Notation} factory method. For example:
     *
     * <pre>
     * NumberFormatter.with().notation(Notation.compactShort())
     * </pre>
     *
     * The default is to use simple notation.
     *
     * @param notation
     *            The notation strategy to use.
     * @return The fluent chain.
     * @see Notation
     * @stable ICU 60
     */
    public T notation(Notation notation) {
        return create(KEY_NOTATION, notation);
    }

    /**
     * Specifies the unit (unit of measure, currency, or percent) to associate with rendered numbers.
     *
     * <ul>
     * <li>Unit of measure: "12.3 meters"
     * <li>Currency: "$12.30"
     * <li>Percent: "12.3%"
     * </ul>
     *
     * <p>
     * <strong>Note:</strong> The unit can also be specified by passing a {@link Measure} to
     * {@link LocalizedNumberFormatter#format(Measure)}. Units specified via the format method take
     * precedence over units specified here. This setter is designed for situations when the unit is
     * constant for the duration of the number formatting process.
     *
     * <p>
     * All units will be properly localized with locale data, and all units are compatible with notation
     * styles, rounding strategies, and other number formatter settings.
     *
     * <p>
     * Pass this method any instance of {@link MeasureUnit}. For units of measure:
     *
     * <pre>
     * NumberFormatter.with().unit(MeasureUnit.METER)
     * </pre>
     *
     * Currency:
     *
     * <pre>
     * NumberFormatter.with().unit(Currency.getInstance("USD"))
     * </pre>
     *
     * Percent:
     *
     * <pre>
     * NumberFormatter.with().unit(NoUnit.PERCENT)
     * </pre>
     *
     * <p>
     * See {@link #perUnit} for information on how to format strings like "5 meters per second".
     *
     * <p>
     * The default is to render without units (equivalent to {@link NoUnit#BASE}).
     *
     * <p>
     * If the input usage is correctly set the output unit <b>will change</b>
     * according to `usage`, `locale` and `unit` value.
     * </p>
     *
     * @param unit
     *            The unit to render.
     * @return The fluent chain.
     * @see MeasureUnit
     * @see Currency
     * @see NoUnit
     * @see #perUnit
     * @stable ICU 60
     */
    public T unit(MeasureUnit unit) {
        return create(KEY_UNIT, unit);
    }

    /**
     * Sets a unit to be used in the denominator. For example, to format "3 m/s", pass METER to the unit
     * and SECOND to the perUnit.
     *
     * <p>
     * Pass this method any instance of {@link MeasureUnit}. For example:
     *
     * <pre>
     * NumberFormatter.with().unit(MeasureUnit.METER).perUnit(MeasureUnit.SECOND)
     * </pre>
     *
     * <p>
     * The default is not to display any unit in the denominator.
     *
     * <p>
     * If a per-unit is specified without a primary unit via {@link #unit}, the behavior is undefined.
     *
     * @param perUnit
     *            The unit to render in the denominator.
     * @return The fluent chain
     * @see #unit
     * @stable ICU 61
     */
    public T perUnit(MeasureUnit perUnit) {
        return create(KEY_PER_UNIT, perUnit);
    }

    /**
     * Specifies the rounding precision to use when formatting numbers.
     *
     * <ul>
     * <li>Round to 3 decimal places: "3.142"
     * <li>Round to 3 significant figures: "3.14"
     * <li>Round to the closest nickel: "3.15"
     * <li>Do not perform rounding: "3.1415926..."
     * </ul>
     *
     * <p>
     * Pass this method the return value of one of the factory methods on {@link Precision}. For example:
     *
     * <pre>
     * NumberFormatter.with().precision(Precision.fixedFraction(2))
     * </pre>
     *
     * <p>
     * In most cases, the default rounding precision is to round to 6 fraction places; i.e.,
     * <code>Precision.maxFraction(6)</code>. The exceptions are if compact notation is being used, then
     * the compact notation rounding precision is used (see {@link Notation#compactShort} for details), or
     * if the unit is a currency, then standard currency rounding is used, which varies from currency to
     * currency (see {@link Precision#currency} for details).
     *
     * @param precision
     *            The rounding precision to use.
     * @return The fluent chain.
     * @see Precision
     * @stable ICU 62
     */
    public T precision(Precision precision) {
        return create(KEY_PRECISION, precision);
    }

    /**
     * Specifies how to determine the direction to round a number when it has more digits than fit in the
     * desired precision.  When formatting 1.235:
     *
     * <ul>
     * <li>Ceiling rounding mode with integer precision: "2"
     * <li>Half-down rounding mode with 2 fixed fraction digits: "1.23"
     * <li>Half-up rounding mode with 2 fixed fraction digits: "1.24"
     * </ul>
     *
     * The default is HALF_EVEN. For more information on rounding mode, see the ICU userguide here:
     *
     * http://userguide.icu-project.org/formatparse/numbers/rounding-modes
     *
     * @param roundingMode
     *            The rounding mode to use.
     * @return The fluent chain.
     * @see Precision
     * @stable ICU 62
     */
    public T roundingMode(RoundingMode roundingMode) {
        return create(KEY_ROUNDING_MODE, roundingMode);
    }

    /**
     * Specifies the grouping strategy to use when formatting numbers.
     *
     * <ul>
     * <li>Default grouping: "12,300" and "1,230"
     * <li>Grouping with at least 2 digits: "12,300" and "1230"
     * <li>No grouping: "12300" and "1230"
     * </ul>
     *
     * <p>
     * The exact grouping widths will be chosen based on the locale.
     *
     * <p>
     * Pass this method an element from the {@link GroupingStrategy} enum. For example:
     *
     * <pre>
     * NumberFormatter.with().grouping(GroupingStrategy.MIN2)
     * </pre>
     *
     * The default is to perform grouping according to locale data; most locales, but not all locales,
     * enable it by default.
     *
     * @param strategy
     *            The grouping strategy to use.
     * @return The fluent chain.
     * @see GroupingStrategy
     * @stable ICU 61
     */
    public T grouping(GroupingStrategy strategy) {
        return create(KEY_GROUPING, strategy);
    }

    /**
     * Specifies the minimum and maximum number of digits to render before the decimal mark.
     *
     * <ul>
     * <li>Zero minimum integer digits: ".08"
     * <li>One minimum integer digit: "0.08"
     * <li>Two minimum integer digits: "00.08"
     * </ul>
     *
     * <p>
     * Pass this method the return value of {@link IntegerWidth#zeroFillTo(int)}. For example:
     *
     * <pre>
     * NumberFormatter.with().integerWidth(IntegerWidth.zeroFillTo(2))
     * </pre>
     *
     * The default is to have one minimum integer digit.
     *
     * @param style
     *            The integer width to use.
     * @return The fluent chain.
     * @see IntegerWidth
     * @stable ICU 60
     */
    public T integerWidth(IntegerWidth style) {
        return create(KEY_INTEGER, style);
    }

    /**
     * Specifies the symbols (decimal separator, grouping separator, percent sign, numerals, etc.) to use
     * when rendering numbers.
     *
     * <ul>
     * <li><em>en_US</em> symbols: "12,345.67"
     * <li><em>fr_FR</em> symbols: "12&nbsp;345,67"
     * <li><em>de_CH</em> symbols: "12’345.67"
     * <li><em>my_MY</em> symbols: "၁၂,၃၄၅.၆၇"
     * </ul>
     *
     * <p>
     * Pass this method an instance of {@link DecimalFormatSymbols}. For example:
     *
     * <pre>
     * NumberFormatter.with().symbols(DecimalFormatSymbols.getInstance(new ULocale("de_CH")))
     * </pre>
     *
     * <p>
     * <strong>Note:</strong> DecimalFormatSymbols automatically chooses the best numbering system based
     * on the locale. In the examples above, the first three are using the Latin numbering system, and
     * the fourth is using the Myanmar numbering system.
     *
     * <p>
     * <strong>Note:</strong> The instance of DecimalFormatSymbols will be copied: changes made to the
     * symbols object after passing it into the fluent chain will not be seen.
     *
     * <p>
     * <strong>Note:</strong> Calling this method will override the NumberingSystem previously specified
     * in {@link #symbols(NumberingSystem)}.
     *
     * <p>
     * The default is to choose the symbols based on the locale specified in the fluent chain.
     *
     * @param symbols
     *            The DecimalFormatSymbols to use.
     * @return The fluent chain.
     * @see DecimalFormatSymbols
     * @stable ICU 60
     */
    public T symbols(DecimalFormatSymbols symbols) {
        symbols = (DecimalFormatSymbols) symbols.clone();
        return create(KEY_SYMBOLS, symbols);
    }

    /**
     * Specifies that the given numbering system should be used when fetching symbols.
     *
     * <ul>
     * <li>Latin numbering system: "12,345"
     * <li>Myanmar numbering system: "၁၂,၃၄၅"
     * <li>Math Sans Bold numbering system: "𝟭𝟮,𝟯𝟰𝟱"
     * </ul>
     *
     * <p>
     * Pass this method an instance of {@link NumberingSystem}. For example, to force the locale to
     * always use the Latin alphabet numbering system (ASCII digits):
     *
     * <pre>
     * NumberFormatter.with().symbols(NumberingSystem.LATIN)
     * </pre>
     *
     * <p>
     * <strong>Note:</strong> Calling this method will override the DecimalFormatSymbols previously
     * specified in {@link #symbols(DecimalFormatSymbols)}.
     *
     * <p>
     * The default is to choose the best numbering system for the locale.
     *
     * @param ns
     *            The NumberingSystem to use.
     * @return The fluent chain.
     * @see NumberingSystem
     * @stable ICU 60
     */
    public T symbols(NumberingSystem ns) {
        return create(KEY_SYMBOLS, ns);
    }

    /**
     * Sets the width of the unit (measure unit or currency). Most common values:
     *
     * <ul>
     * <li>Short: "$12.00", "12 m"
     * <li>ISO Code: "USD 12.00"
     * <li>Full name: "12.00 US dollars", "12 meters"
     * </ul>
     *
     * <p>
     * Pass an element from the {@link UnitWidth} enum to this setter. For example:
     *
     * <pre>
     * NumberFormatter.with().unitWidth(UnitWidth.FULL_NAME)
     * </pre>
     *
     * <p>
     * The default is the SHORT width.
     *
     * @param style
     *            The width to use when rendering numbers.
     * @return The fluent chain
     * @see UnitWidth
     * @stable ICU 60
     */
    public T unitWidth(UnitWidth style) {
        return create(KEY_UNIT_WIDTH, style);
    }

    /**
     * Sets the plus/minus sign display strategy. Most common values:
     *
     * <ul>
     * <li>Auto: "123", "-123"
     * <li>Always: "+123", "-123"
     * <li>Accounting: "$123", "($123)"
     * </ul>
     *
     * <p>
     * Pass an element from the {@link SignDisplay} enum to this setter. For example:
     *
     * <pre>
     * NumberFormatter.with().sign(SignDisplay.ALWAYS)
     * </pre>
     *
     * <p>
     * The default is AUTO sign display.
     *
     * @param style
     *            The sign display strategy to use when rendering numbers.
     * @return The fluent chain
     * @see SignDisplay
     * @stable ICU 60
     */
    public T sign(SignDisplay style) {
        return create(KEY_SIGN, style);
    }

    /**
     * Sets the decimal separator display strategy. This affects integer numbers with no fraction part.
     * Most common values:
     *
     * <ul>
     * <li>Auto: "1"
     * <li>Always: "1."
     * </ul>
     *
     * <p>
     * Pass an element from the {@link DecimalSeparatorDisplay} enum to this setter. For example:
     *
     * <pre>
     * NumberFormatter.with().decimal(DecimalSeparatorDisplay.ALWAYS)
     * </pre>
     *
     * <p>
     * The default is AUTO decimal separator display.
     *
     * @param style
     *            The decimal separator display strategy to use when rendering numbers.
     * @return The fluent chain
     * @see DecimalSeparatorDisplay
     * @stable ICU 60
     */
    public T decimal(DecimalSeparatorDisplay style) {
        return create(KEY_DECIMAL, style);
    }

    /**
     * Sets a scale (multiplier) to be used to scale the number by an arbitrary amount before formatting.
     * Most common values:
     *
     * <ul>
     * <li>Multiply by 100: useful for percentages.
     * <li>Multiply by an arbitrary value: useful for unit conversions.
     * </ul>
     *
     * <p>
     * Pass an element from a {@link Scale} factory method to this setter. For example:
     *
     * <pre>
     * NumberFormatter.with().scale(Scale.powerOfTen(2))
     * </pre>
     *
     * <p>
     * The default is to not apply any multiplier.
     *
     * @param scale
     *            An amount to be multiplied against numbers before formatting.
     * @return The fluent chain
     * @see Scale
     * @stable ICU 62
     */
    public T scale(Scale scale) {
        return create(KEY_SCALE, scale);
    }

    /**
     * Specifies the usage for which numbers will be formatted ("person-height",
     * "road", "rainfall", etc.)
     *
     * <p>
     * When a `usage` is specified, the output unit will change depending on the
     * `Locale` and the unit quantity. For example, formatting length
     * measurements specified in meters:
     *
     * <p>
     * <pre>
     * NumberFormatter.with().usage("person").unit(MeasureUnit.METER).locale(new ULocale("en-US"))
     * </pre>
     * <ul>
     *   <li> When formatting 0.25, the output will be "10 inches".
     *   <li> When formatting 1.50, the output will be "4 feet and 11 inches".
     * </li>
     *
     * <p>
     * The input unit specified via unit() determines the type of measurement
     * being formatted (e.g. "length" when the unit is "foot"). The usage
     * requested will be looked for only within this category of measurement
     * units.
     *
     * <p>
     * The output unit can be found via FormattedNumber.getOutputUnit().
     *
     * <p>
     * If the usage has multiple parts (e.g. "land-agriculture-grain") and does
     * not match a known usage preference, the last part will be dropped
     * repeatedly until a match is found (e.g. trying "land-agriculture", then
     * "land"). If a match is still not found, usage will fall back to
     * "default".
     *
     * <p>
     * Setting usage to an empty string clears the usage (disables usage-based
     * localized formatting).
     *
     * <p>
     * Setting a usage string but not a correct input unit will result in an
     * U_ILLEGAL_ARGUMENT_ERROR.
     *
     * <p>
     * When using usage, specifying rounding or precision is unnecessary.
     * Specifying a precision in some manner will override the default
     * formatting.
     *
     * @param usage A usage parameter from the units resource.
     * @return The fluent chain
     * @throws IllegalArgumentException in case of Setting a usage string but not a correct input unit.
     * @draft ICU 68
     * @provisional This API might change or be removed in a future release.
     */
    public T usage(String usage) {
        return create(KEY_USAGE, usage);
    }

    /**
     * Internal method to set a starting macros.
     *
     * @internal
     * @deprecated ICU 60 This API is ICU internal only.
     */
    @Deprecated
    public T macros(MacroProps macros) {
        return create(KEY_MACROS, macros);
    }

    /**
     * Set the padding strategy. May be added to ICU 61; see #13338.
     *
     * @internal
     * @deprecated ICU 60 This API is ICU internal only.
     */
    @Deprecated
    public T padding(Padder padder) {
        return create(KEY_PADDER, padder);
    }

    /**
     * Internal fluent setter to support a custom regulation threshold. A threshold of 1 causes the data
     * structures to be built right away. A threshold of 0 prevents the data structures from being built.
     *
     * @internal
     * @deprecated ICU 60 This API is ICU internal only.
     */
    @Deprecated
    public T threshold(Long threshold) {
        return create(KEY_THRESHOLD, threshold);
    }

    /**
     * Creates a skeleton string representation of this number formatter. A skeleton string is a
     * locale-agnostic serialized form of a number formatter.
     * <p>
     * Not all options are capable of being represented in the skeleton string; for example, a
     * DecimalFormatSymbols object. If any such option is encountered, an
     * {@link UnsupportedOperationException} is thrown.
     * <p>
     * The returned skeleton is in normalized form, such that two number formatters with equivalent
     * behavior should produce the same skeleton.
     *
     * @return A number skeleton string with behavior corresponding to this number formatter.
     * @throws UnsupportedOperationException
     *             If the number formatter has an option that cannot be represented in a skeleton string.
     * @stable ICU 62
     */
    public String toSkeleton() {
        return NumberSkeletonImpl.generate(resolve());
    }

    /* package-protected */ abstract T create(int key, Object value);

    MacroProps resolve() {
        if (resolvedMacros != null) {
            return resolvedMacros;
        }
        // Although the linked-list fluent storage approach requires this method,
        // my benchmarks show that linked-list is still faster than a full clone
        // of a MacroProps object at each step.
        // TODO: Remove the reference to the parent after the macros are resolved?
        MacroProps macros = new MacroProps();
        NumberFormatterSettings<?> current = this;
        while (current != null) {
            switch (current.key) {
            case KEY_MACROS:
                macros.fallback((MacroProps) current.value);
                break;
            case KEY_LOCALE:
                if (macros.loc == null) {
                    macros.loc = (ULocale) current.value;
                }
                break;
            case KEY_NOTATION:
                if (macros.notation == null) {
                    macros.notation = (Notation) current.value;
                }
                break;
            case KEY_UNIT:
                if (macros.unit == null) {
                    macros.unit = (MeasureUnit) current.value;
                }
                break;
            case KEY_PRECISION:
                if (macros.precision == null) {
                    macros.precision = (Precision) current.value;
                }
                break;
            case KEY_ROUNDING_MODE:
                if (macros.roundingMode == null) {
                    macros.roundingMode = (RoundingMode) current.value;
                }
                break;
            case KEY_GROUPING:
                if (macros.grouping == null) {
                    macros.grouping = /* (Object) */ current.value;
                }
                break;
            case KEY_PADDER:
                if (macros.padder == null) {
                    macros.padder = (Padder) current.value;
                }
                break;
            case KEY_INTEGER:
                if (macros.integerWidth == null) {
                    macros.integerWidth = (IntegerWidth) current.value;
                }
                break;
            case KEY_SYMBOLS:
                if (macros.symbols == null) {
                    macros.symbols = /* (Object) */ current.value;
                }
                break;
            case KEY_UNIT_WIDTH:
                if (macros.unitWidth == null) {
                    macros.unitWidth = (UnitWidth) current.value;
                }
                break;
            case KEY_SIGN:
                if (macros.sign == null) {
                    macros.sign = (SignDisplay) current.value;
                }
                break;
            case KEY_DECIMAL:
                if (macros.decimal == null) {
                    macros.decimal = (DecimalSeparatorDisplay) current.value;
                }
                break;
            case KEY_SCALE:
                if (macros.scale == null) {
                    macros.scale = (Scale) current.value;
                }
                break;
            case KEY_THRESHOLD:
                if (macros.threshold == null) {
                    macros.threshold = (Long) current.value;
                }
                break;
            case KEY_PER_UNIT:
                if (macros.perUnit == null) {
                    macros.perUnit = (MeasureUnit) current.value;
                }
                break;
            case KEY_USAGE:
                if(macros.usage == null) {
                    macros.usage = (String) current.value;
                }
                break;
            default:
                throw new AssertionError("Unknown key: " + current.key);
            }
            current = current.parent;
        }
        resolvedMacros = macros;
        return macros;
    }

    /**
     * {@inheritDoc}
     *
     * @stable ICU 60
     */
    @Override
    public int hashCode() {
        return resolve().hashCode();
    }

    /**
     * {@inheritDoc}
     *
     * @stable ICU 60
     */
    @Override
    public boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (other == null) {
            return false;
        }
        if (!(other instanceof NumberFormatterSettings)) {
            return false;
        }
        return resolve().equals(((NumberFormatterSettings<?>) other).resolve());
    }
}
