// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
 **********************************************************************
 * Copyright (c) 2004-2016, International Business Machines
 * Corporation and others.  All Rights Reserved.
 **********************************************************************
 * Author: Alan Liu
 * Created: April 20, 2004
 * Since: ICU 3.0
 **********************************************************************
 */
package com.ibm.icu.text;

import java.io.Externalizable;
import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.io.ObjectStreamException;
import java.math.RoundingMode;
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.concurrent.ConcurrentHashMap;

import com.ibm.icu.impl.DontCareFieldPosition;
import com.ibm.icu.impl.FormattedStringBuilder;
import com.ibm.icu.impl.FormattedValueStringBuilderImpl;
import com.ibm.icu.impl.ICUData;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.impl.SimpleFormatterImpl;
import com.ibm.icu.impl.Utility;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.DecimalQuantity_DualStorageBCD;
import com.ibm.icu.impl.number.LongNameHandler;
import com.ibm.icu.impl.number.RoundingUtils;
import com.ibm.icu.number.IntegerWidth;
import com.ibm.icu.number.LocalizedNumberFormatter;
import com.ibm.icu.number.NumberFormatter;
import com.ibm.icu.number.NumberFormatter.UnitWidth;
import com.ibm.icu.number.Precision;
import com.ibm.icu.text.ListFormatter.FormattedListBuilder;
import com.ibm.icu.util.Currency;
import com.ibm.icu.util.ICUUncheckedIOException;
import com.ibm.icu.util.Measure;
import com.ibm.icu.util.MeasureUnit;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.ULocale.Category;
import com.ibm.icu.util.UResourceBundle;

// If you update the examples in the doc, don't forget to update MesaureUnitTest.TestExamplesInDocs too.
/**
 * A formatter for Measure objects.
 *
 * <p>
 * <strong>IMPORTANT:</strong> New users are strongly encouraged to see if
 * {@link NumberFormatter} fits their use case.  Although not deprecated, this
 * class, MeasureFormat, is provided for backwards compatibility only, and has
 * much more limited capabilities.
 * <hr>
 *
 * <p>
 * To format a Measure object, first create a formatter object using a MeasureFormat factory method. Then
 * use that object's format or formatMeasures methods.
 *
 * Here is sample code:
 *
 * <pre>
 * MeasureFormat fmtFr = MeasureFormat.getInstance(ULocale.FRENCH, FormatWidth.SHORT);
 * Measure measure = new Measure(23, MeasureUnit.CELSIUS);
 *
 * // Output: 23 °C
 * System.out.println(fmtFr.format(measure));
 *
 * Measure measureF = new Measure(70, MeasureUnit.FAHRENHEIT);
 *
 * // Output: 70 °F
 * System.out.println(fmtFr.format(measureF));
 *
 * MeasureFormat fmtFrFull = MeasureFormat.getInstance(ULocale.FRENCH, FormatWidth.WIDE);
 * // Output: 70 pieds et 5,3 pouces
 * System.out.println(fmtFrFull.formatMeasures(new Measure(70, MeasureUnit.FOOT),
 *         new Measure(5.3, MeasureUnit.INCH)));
 *
 * // Output: 1 pied et 1 pouce
 * System.out.println(
 *         fmtFrFull.formatMeasures(new Measure(1, MeasureUnit.FOOT), new Measure(1, MeasureUnit.INCH)));
 *
 * MeasureFormat fmtFrNarrow = MeasureFormat.getInstance(ULocale.FRENCH, FormatWidth.NARROW);
 * // Output: 1′ 1″
 * System.out.println(fmtFrNarrow.formatMeasures(new Measure(1, MeasureUnit.FOOT),
 *         new Measure(1, MeasureUnit.INCH)));
 *
 * MeasureFormat fmtEn = MeasureFormat.getInstance(ULocale.ENGLISH, FormatWidth.WIDE);
 *
 * // Output: 1 inch, 2 feet
 * fmtEn.formatMeasures(new Measure(1, MeasureUnit.INCH), new Measure(2, MeasureUnit.FOOT));
 * </pre>
 * <p>
 * This class does not do conversions from one unit to another. It simply formats whatever units it is
 * given
 * <p>
 * This class is immutable and thread-safe so long as its deprecated subclass, TimeUnitFormat, is never
 * used. TimeUnitFormat is not thread-safe, and is mutable. Although this class has existing subclasses,
 * this class does not support new sub-classes.
 *
 * @see com.ibm.icu.text.UFormat
 * @author Alan Liu
 * @stable ICU 3.0
 */
public class MeasureFormat extends UFormat {

    // Generated by serialver from JDK 1.4.1_01
    static final long serialVersionUID = -7182021401701778240L;

    private final transient FormatWidth formatWidth;

    // PluralRules is documented as being immutable which implies thread-safety.
    private final transient PluralRules rules;

    private final transient NumericFormatters numericFormatters;

    private final transient NumberFormat numberFormat;

    private final transient LocalizedNumberFormatter numberFormatter;

    private static final SimpleCache<ULocale, NumericFormatters> localeToNumericDurationFormatters = new SimpleCache<>();

    private static final Map<MeasureUnit, Integer> hmsTo012 = new HashMap<>();

    static {
        hmsTo012.put(MeasureUnit.HOUR, 0);
        hmsTo012.put(MeasureUnit.MINUTE, 1);
        hmsTo012.put(MeasureUnit.SECOND, 2);
    }

    // For serialization: sub-class types.
    private static final int MEASURE_FORMAT = 0;
    private static final int TIME_UNIT_FORMAT = 1;
    private static final int CURRENCY_FORMAT = 2;

    /**
     * Formatting width enum.
     *
     * @stable ICU 53
     */
    // Be sure to update MeasureUnitTest.TestSerialFormatWidthEnum
    // when adding an enum value.
    public enum FormatWidth {

        /**
         * Spell out everything.
         *
         * @stable ICU 53
         */
        WIDE(ListFormatter.Width.WIDE, UnitWidth.FULL_NAME, UnitWidth.FULL_NAME),

        /**
         * Abbreviate when possible.
         *
         * @stable ICU 53
         */
        SHORT(ListFormatter.Width.SHORT, UnitWidth.SHORT, UnitWidth.ISO_CODE),

        /**
         * Brief. Use only a symbol for the unit when possible.
         *
         * @stable ICU 53
         */
        NARROW(ListFormatter.Width.NARROW, UnitWidth.NARROW, UnitWidth.SHORT),

        /**
         * Identical to NARROW except when formatMeasures is called with an hour and minute; minute and
         * second; or hour, minute, and second Measures. In these cases formatMeasures formats as 5:37:23
         * instead of 5h, 37m, 23s.
         *
         * @stable ICU 53
         */
        NUMERIC(ListFormatter.Width.NARROW, UnitWidth.NARROW, UnitWidth.SHORT),

        /**
         * The default format width for getCurrencyFormat(), which is to show the symbol for currency
         * (UnitWidth.SHORT) but wide for other units.
         *
         * @internal Use {@link #getCurrencyFormat()}
         * @deprecated ICU 61 This API is ICU internal only.
         */
        @Deprecated
        DEFAULT_CURRENCY(ListFormatter.Width.SHORT, UnitWidth.FULL_NAME, UnitWidth.SHORT);

        final ListFormatter.Width listWidth;

        /**
         * The {@link UnitWidth} (used for newer NumberFormatter API) that corresponds to this
         * FormatWidth (used for the older APIs) for all units except currencies.
         */
        final UnitWidth unitWidth;

        /**
         * The {@link UnitWidth} (used for newer NumberFormatter API) that corresponds to this
         * FormatWidth (used for the older APIs) for currencies.
         */
        final UnitWidth currencyWidth;

        private FormatWidth(
                ListFormatter.Width listWidth,
                UnitWidth unitWidth,
                UnitWidth currencyWidth) {
            this.listWidth = listWidth;
            this.unitWidth = unitWidth;
            this.currencyWidth = currencyWidth;
        }
    }

    /**
     * Create a format from the locale, formatWidth, and format.
     *
     * @param locale
     *            the locale.
     * @param formatWidth
     *            hints how long formatted strings should be.
     * @return The new MeasureFormat object.
     * @stable ICU 53
     */
    public static MeasureFormat getInstance(ULocale locale, FormatWidth formatWidth) {
        return getInstance(locale, formatWidth, NumberFormat.getInstance(locale));
    }

    /**
     * Create a format from the {@link java.util.Locale} and formatWidth.
     *
     * @param locale
     *            the {@link java.util.Locale}.
     * @param formatWidth
     *            hints how long formatted strings should be.
     * @return The new MeasureFormat object.
     * @stable ICU 54
     */
    public static MeasureFormat getInstance(Locale locale, FormatWidth formatWidth) {
        return getInstance(ULocale.forLocale(locale), formatWidth);
    }

    /**
     * Create a format from the locale, formatWidth, and format.
     *
     * @param locale
     *            the locale.
     * @param formatWidth
     *            hints how long formatted strings should be.
     * @param format
     *            This is defensively copied.
     * @return The new MeasureFormat object.
     * @stable ICU 53
     */
    public static MeasureFormat getInstance(
            ULocale locale,
            FormatWidth formatWidth,
            NumberFormat format) {
        return new MeasureFormat(locale, formatWidth, format, null, null);
    }

    /**
     * Create a format from the {@link java.util.Locale}, formatWidth, and format.
     *
     * @param locale
     *            the {@link java.util.Locale}.
     * @param formatWidth
     *            hints how long formatted strings should be.
     * @param format
     *            This is defensively copied.
     * @return The new MeasureFormat object.
     * @stable ICU 54
     */
    public static MeasureFormat getInstance(
            Locale locale,
            FormatWidth formatWidth,
            NumberFormat format) {
        return getInstance(ULocale.forLocale(locale), formatWidth, format);
    }

    /**
     * Able to format Collection&lt;? extends Measure&gt;, Measure[], and Measure by delegating to
     * formatMeasures. If the pos argument identifies a NumberFormat field, then its indices are set to
     * the beginning and end of the first such field encountered. MeasureFormat itself does not supply
     * any fields.
     *
     * Calling a <code>formatMeasures</code> method is preferred over calling this method as they give
     * better performance.
     *
     * @param obj
     *            must be a Collection&lt;? extends Measure&gt;, Measure[], or Measure object.
     * @param toAppendTo
     *            Formatted string appended here.
     * @param fpos
     *            Identifies a field in the formatted text.
     * @see java.text.Format#format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition)
     *
     * @stable ICU53
     */
    @Override
    public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition fpos) {
        int prevLength = toAppendTo.length();
        fpos.setBeginIndex(0);
        fpos.setEndIndex(0);
        if (obj instanceof Collection) {
            Collection<?> coll = (Collection<?>) obj;
            Measure[] measures = new Measure[coll.size()];
            int idx = 0;
            for (Object o : coll) {
                if (!(o instanceof Measure)) {
                    throw new IllegalArgumentException(obj.toString());
                }
                measures[idx++] = (Measure) o;
            }
            formatMeasuresInternal(toAppendTo, fpos, measures);
        } else if (obj instanceof Measure[]) {
            formatMeasuresInternal(toAppendTo, fpos, (Measure[]) obj);
        } else if (obj instanceof Measure) {
            FormattedStringBuilder result = formatMeasure((Measure) obj);
            // No offset: toAppendTo.length() is considered below
            FormattedValueStringBuilderImpl.nextFieldPosition(result, fpos);
            Utility.appendTo(result, toAppendTo);
        } else {
            throw new IllegalArgumentException(obj.toString());
        }
        if (prevLength > 0 && fpos.getEndIndex() != 0) {
            fpos.setBeginIndex(fpos.getBeginIndex() + prevLength);
            fpos.setEndIndex(fpos.getEndIndex() + prevLength);
        }
        return toAppendTo;
    }

    /**
     * Parses text from a string to produce a <code>Measure</code>.
     *
     * @see java.text.Format#parseObject(java.lang.String, java.text.ParsePosition)
     * @throws UnsupportedOperationException
     *             Not supported.
     * @draft ICU 53 (Retain)
     */
    @Override
    public Measure parseObject(String source, ParsePosition pos) {
        throw new UnsupportedOperationException();
    }

    /**
     * Format a sequence of measures. Uses the ListFormatter unit lists. So, for example, one could
     * format “3 feet, 2 inches”. Zero values are formatted (eg, “3 feet, 0 inches”). It is the caller’s
     * responsibility to have the appropriate values in appropriate order, and using the appropriate
     * Number values. Typically the units should be in descending order, with all but the last Measure
     * having integer values (eg, not “3.2 feet, 2 inches”).
     *
     * @param measures
     *            a sequence of one or more measures.
     * @return the formatted string.
     * @stable ICU 53
     */
    public final String formatMeasures(Measure... measures) {
        return formatMeasures(new StringBuilder(), DontCareFieldPosition.INSTANCE, measures).toString();
    }

    // NOTE: For formatMeasureRange(), see http://bugs.icu-project.org/trac/ticket/12454

    /**
     * Formats a single measure per unit.
     *
     * An example of such a formatted string is "3.5 meters per second."
     *
     * @param measure
     *            the measure object. In above example, 3.5 meters.
     * @param perUnit
     *            the per unit. In above example, it is MeasureUnit.SECOND
     * @param appendTo
     *            formatted string appended here.
     * @param pos
     *            The field position.
     * @return appendTo.
     * @stable ICU 55
     */
    public StringBuilder formatMeasurePerUnit(
            Measure measure,
            MeasureUnit perUnit,
            StringBuilder appendTo,
            FieldPosition pos) {
        DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(measure.getNumber());
        FormattedStringBuilder string = new FormattedStringBuilder();
        getUnitFormatterFromCache(
            NUMBER_FORMATTER_STANDARD, measure.getUnit(), perUnit
        ).formatImpl(dq, string);
        DecimalFormat.fieldPositionHelper(dq, string, pos, appendTo.length());
        Utility.appendTo(string, appendTo);
        return appendTo;
    }

    /**
     * Formats a sequence of measures.
     *
     * If the fieldPosition argument identifies a NumberFormat field, then its indices are set to the
     * beginning and end of the first such field encountered. MeasureFormat itself does not supply any
     * fields.
     *
     * @param appendTo
     *            the formatted string appended here.
     * @param fpos
     *            Identifies a field in the formatted text.
     * @param measures
     *            the measures to format.
     * @return appendTo.
     * @see MeasureFormat#formatMeasures(Measure...)
     * @stable ICU 53
     */
    public StringBuilder formatMeasures(
            StringBuilder appendTo,
            FieldPosition fpos,
            Measure... measures) {
        int prevLength = appendTo.length();
        formatMeasuresInternal(appendTo, fpos, measures);
        if (prevLength > 0 && fpos.getEndIndex() > 0) {
            fpos.setBeginIndex(fpos.getBeginIndex() + prevLength);
            fpos.setEndIndex(fpos.getEndIndex() + prevLength);
        }
        return appendTo;
    }

    private void formatMeasuresInternal(
            Appendable appendTo,
            FieldPosition fieldPosition,
            Measure... measures) {
        // fast track for trivial cases
        if (measures.length == 0) {
            return;
        }
        if (measures.length == 1) {
            FormattedStringBuilder result = formatMeasure(measures[0]);
            FormattedValueStringBuilderImpl.nextFieldPosition(result, fieldPosition);
            Utility.appendTo(result, appendTo);
            return;
        }

        if (formatWidth == FormatWidth.NUMERIC) {
            // If we have just hour, minute, or second follow the numeric
            // track.
            Number[] hms = toHMS(measures);
            if (hms != null) {
                formatNumeric(hms, appendTo);
                return;
            }
        }

        ListFormatter listFormatter = ListFormatter.getInstance(getLocale(),
                ListFormatter.Type.UNITS,
                formatWidth.listWidth);
        if (fieldPosition != DontCareFieldPosition.INSTANCE) {
            formatMeasuresSlowTrack(listFormatter, appendTo, fieldPosition, measures);
            return;
        }
        // Fast track: No field position.
        String[] results = new String[measures.length];
        for (int i = 0; i < measures.length; i++) {
            if (i == measures.length - 1) {
                results[i] = formatMeasure(measures[i]).toString();
            } else {
                results[i] = formatMeasureInteger(measures[i]).toString();
            }
        }
        FormattedListBuilder builder = listFormatter.formatImpl(Arrays.asList(results), false);
        builder.appendTo(appendTo);
    }

    /**
     * Gets the display name of the specified {@link MeasureUnit} corresponding to the current locale and
     * format width.
     *
     * @param unit
     *            The unit for which to get a display name.
     * @return The display name in the locale and width specified in {@link MeasureFormat#getInstance},
     *         or null if there is no display name available for the specified unit.
     *
     * @stable ICU 58
     */
    public String getUnitDisplayName(MeasureUnit unit) {
        return LongNameHandler.getUnitDisplayName(getLocale(), unit, formatWidth.unitWidth);
    }

    /**
     * Two MeasureFormats, a and b, are equal if and only if they have the same formatWidth, locale, and
     * equal number formats.
     *
     * @stable ICU 3.0
     */
    @Override
    public final boolean equals(Object other) {
        if (this == other) {
            return true;
        }
        if (!(other instanceof MeasureFormat)) {
            return false;
        }
        MeasureFormat rhs = (MeasureFormat) other;
        // A very slow but safe implementation.
        return getWidth() == rhs.getWidth()
                && getLocale().equals(rhs.getLocale())
                && getNumberFormatInternal().equals(rhs.getNumberFormatInternal());
    }

    /**
     * {@inheritDoc}
     *
     * @stable ICU 3.0
     */
    @Override
    public final int hashCode() {
        // A very slow but safe implementation.
        return (getLocale().hashCode() * 31 + getNumberFormatInternal().hashCode()) * 31 + getWidth().hashCode();
    }

    /**
     * Get the format width this instance is using.
     *
     * @stable ICU 53
     */
    public MeasureFormat.FormatWidth getWidth() {
        if (formatWidth == MeasureFormat.FormatWidth.DEFAULT_CURRENCY) {
            return MeasureFormat.FormatWidth.WIDE;
        }
        return formatWidth;
    }

    /**
     * Get the locale of this instance.
     *
     * @stable ICU 53
     */
    public final ULocale getLocale() {
        return getLocale(ULocale.VALID_LOCALE);
    }

    /**
     * Get a copy of the number format.
     *
     * @stable ICU 53
     */
    public NumberFormat getNumberFormat() {
        return (NumberFormat) numberFormat.clone();
    }

    /**
     * Get a copy of the number format without cloning. Internal method.
     */
    NumberFormat getNumberFormatInternal() {
        return numberFormat;
    }

    /**
     * Return a formatter for CurrencyAmount objects in the given locale.
     *
     * @param locale
     *            desired locale
     * @return a formatter object
     * @stable ICU 3.0
     */
    public static MeasureFormat getCurrencyFormat(ULocale locale) {
        return new CurrencyFormat(locale);
    }

    /**
     * Return a formatter for CurrencyAmount objects in the given {@link java.util.Locale}.
     *
     * @param locale
     *            desired {@link java.util.Locale}
     * @return a formatter object
     * @stable ICU 54
     */
    public static MeasureFormat getCurrencyFormat(Locale locale) {
        return getCurrencyFormat(ULocale.forLocale(locale));
    }

    /**
     * Return a formatter for CurrencyAmount objects in the default <code>FORMAT</code> locale.
     *
     * @return a formatter object
     * @see Category#FORMAT
     * @stable ICU 3.0
     */
    public static MeasureFormat getCurrencyFormat() {
        return getCurrencyFormat(ULocale.getDefault(Category.FORMAT));
    }

    // This method changes the NumberFormat object as well to match the new locale.
    MeasureFormat withLocale(ULocale locale) {
        return MeasureFormat.getInstance(locale, getWidth());
    }

    MeasureFormat withNumberFormat(NumberFormat format) {
        return new MeasureFormat(getLocale(),
                this.formatWidth,
                format,
                this.rules,
                this.numericFormatters);
    }

    MeasureFormat(ULocale locale, FormatWidth formatWidth) {
        this(locale, formatWidth, null, null, null);
    }

    private MeasureFormat(
            ULocale locale,
            FormatWidth formatWidth,
            NumberFormat numberFormat,
            PluralRules rules,
            NumericFormatters formatters) {
        // Needed for getLocale(ULocale.VALID_LOCALE).
        setLocale(locale, locale);
        this.formatWidth = formatWidth;

        if (rules == null) {
            rules = PluralRules.forLocale(locale);
        }
        this.rules = rules;

        if (numberFormat == null) {
            numberFormat = NumberFormat.getInstance(locale);
        } else {
            numberFormat = (NumberFormat) numberFormat.clone();
        }
        this.numberFormat = numberFormat;

        if (formatters == null && formatWidth == FormatWidth.NUMERIC) {
            formatters = localeToNumericDurationFormatters.get(locale);
            if (formatters == null) {
                formatters = loadNumericFormatters(locale);
                localeToNumericDurationFormatters.put(locale, formatters);
            }
        }
        this.numericFormatters = formatters;

        if (!(numberFormat instanceof DecimalFormat)) {
            throw new IllegalArgumentException();
        }
        numberFormatter = ((DecimalFormat) numberFormat).toNumberFormatter()
                .unitWidth(formatWidth.unitWidth);
    }

    MeasureFormat(
            ULocale locale,
            FormatWidth formatWidth,
            NumberFormat numberFormat,
            PluralRules rules) {
        this(locale, formatWidth, numberFormat, rules, null);
        if (formatWidth == FormatWidth.NUMERIC) {
            throw new IllegalArgumentException(
                    "The format width 'numeric' is not allowed by this constructor");
        }
    }

    static class NumericFormatters {
        private String hourMinute;
        private String minuteSecond;
        private String hourMinuteSecond;

        public NumericFormatters(
                String hourMinute,
                String minuteSecond,
                String hourMinuteSecond) {
            this.hourMinute = hourMinute;
            this.minuteSecond = minuteSecond;
            this.hourMinuteSecond = hourMinuteSecond;
        }

        public String getHourMinute() {
            return hourMinute;
        }

        public String getMinuteSecond() {
            return minuteSecond;
        }

        public String getHourMinuteSecond() {
            return hourMinuteSecond;
        }
    }

    private static NumericFormatters loadNumericFormatters(ULocale locale) {
        ICUResourceBundle r = (ICUResourceBundle) UResourceBundle
                .getBundleInstance(ICUData.ICU_UNIT_BASE_NAME, locale);
        return new NumericFormatters(loadNumericDurationFormat(r, "hm"),
                loadNumericDurationFormat(r, "ms"),
                loadNumericDurationFormat(r, "hms"));
    }

    /// BEGIN NUMBER FORMATTER CACHING MACHINERY ///

    static final int NUMBER_FORMATTER_STANDARD = 1;
    static final int NUMBER_FORMATTER_CURRENCY = 2;
    static final int NUMBER_FORMATTER_INTEGER = 3;

    static class NumberFormatterCacheEntry {
        int type;
        MeasureUnit unit;
        MeasureUnit perUnit;
        LocalizedNumberFormatter formatter;
    }

    // formatter1 is most recently used.
    private transient NumberFormatterCacheEntry formatter1 = null;
    private transient NumberFormatterCacheEntry formatter2 = null;
    private transient NumberFormatterCacheEntry formatter3 = null;

    private synchronized LocalizedNumberFormatter getUnitFormatterFromCache(
            int type,
            MeasureUnit unit,
            MeasureUnit perUnit) {
        if (formatter1 != null) {
            if (formatter1.type == type && formatter1.unit == unit && formatter1.perUnit == perUnit) {
                return formatter1.formatter;
            }
            if (formatter2 != null) {
                if (formatter2.type == type
                        && formatter2.unit == unit
                        && formatter2.perUnit == perUnit) {
                    return formatter2.formatter;
                }
                if (formatter3 != null) {
                    if (formatter3.type == type
                            && formatter3.unit == unit
                            && formatter3.perUnit == perUnit) {
                        return formatter3.formatter;
                    }
                }
            }
        }

        // No hit; create a new formatter.
        LocalizedNumberFormatter formatter;
        if (type == NUMBER_FORMATTER_STANDARD) {
            formatter = getNumberFormatter().unit(unit).perUnit(perUnit)
                    .unitWidth(formatWidth.unitWidth);
        } else if (type == NUMBER_FORMATTER_CURRENCY) {
            formatter = NumberFormatter.withLocale(getLocale()).unit(unit).perUnit(perUnit)
                    .unitWidth(formatWidth.currencyWidth);
        } else {
            assert type == NUMBER_FORMATTER_INTEGER;
            formatter = getNumberFormatter().unit(unit).perUnit(perUnit).unitWidth(formatWidth.unitWidth)
                    .precision(Precision.integer().withMode(
                            RoundingUtils.mathContextUnlimited(RoundingMode.DOWN)));
        }
        formatter3 = formatter2;
        formatter2 = formatter1;
        formatter1 = new NumberFormatterCacheEntry();
        formatter1.type = type;
        formatter1.unit = unit;
        formatter1.perUnit = perUnit;
        formatter1.formatter = formatter;
        return formatter;
    }

    synchronized void clearCache() {
        formatter1 = null;
        formatter2 = null;
        formatter3 = null;
    }

    // Can be overridden by subclasses:
    LocalizedNumberFormatter getNumberFormatter() {
        return numberFormatter;
    }

    /// END NUMBER FORMATTER CACHING MACHINERY ///

    private FormattedStringBuilder formatMeasure(Measure measure) {
        MeasureUnit unit = measure.getUnit();
        DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(measure.getNumber());
        FormattedStringBuilder string = new FormattedStringBuilder();
        if (unit instanceof Currency) {
            getUnitFormatterFromCache(NUMBER_FORMATTER_CURRENCY, unit, null)
                    .formatImpl(dq, string);
        } else {
            getUnitFormatterFromCache(NUMBER_FORMATTER_STANDARD, unit, null)
                    .formatImpl(dq, string);
        }
        return string;
    }

    private FormattedStringBuilder formatMeasureInteger(Measure measure) {
        DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(measure.getNumber());
        FormattedStringBuilder string = new FormattedStringBuilder();
        getUnitFormatterFromCache(NUMBER_FORMATTER_INTEGER, measure.getUnit(), null)
                .formatImpl(dq, string);
        return string;
    }

    private void formatMeasuresSlowTrack(
            ListFormatter listFormatter,
            Appendable appendTo,
            FieldPosition fieldPosition,
            Measure... measures) {
        String[] results = new String[measures.length];

        // Zero out our field position so that we can tell when we find our field.
        FieldPosition fpos = new FieldPosition(fieldPosition.getFieldAttribute(),
                fieldPosition.getField());

        int fieldPositionFoundIndex = -1;
        for (int i = 0; i < measures.length; ++i) {
            FormattedStringBuilder result;
            if (i == measures.length - 1) {
                result = formatMeasure(measures[i]);
            } else {
                result = formatMeasureInteger(measures[i]);
            }
            if (fieldPositionFoundIndex == -1) {
                FormattedValueStringBuilderImpl.nextFieldPosition(result, fpos);
                if (fpos.getEndIndex() != 0) {
                    fieldPositionFoundIndex = i;
                }
            }
            results[i] = result.toString();
        }
        ListFormatter.FormattedListBuilder builder = listFormatter.formatImpl(Arrays.asList(results), true);

        // Fix up FieldPosition indexes if our field is found.
        int offset = builder.getOffset(fieldPositionFoundIndex);
        if (offset != -1) {
            fieldPosition.setBeginIndex(fpos.getBeginIndex() + offset);
            fieldPosition.setEndIndex(fpos.getEndIndex() + offset);
        }
        builder.appendTo(appendTo);
    }

    // type is one of "hm", "ms" or "hms"
    private static String loadNumericDurationFormat(ICUResourceBundle r, String type) {
        r = r.getWithFallback(String.format("durationUnits/%s", type));
        // We replace 'h' with 'H' because 'h' does not make sense in the context of durations.
        return r.getString().replace("h", "H");
    }

    // Returns hours in [0]; minutes in [1]; seconds in [2] out of measures array. If
    // unsuccessful, e.g measures has other measurements besides hours, minutes, seconds;
    // hours, minutes, seconds are out of order; or have negative values, returns null.
    // If hours, minutes, or seconds is missing from measures the corresponding element in
    // returned array will be null.
    private static Number[] toHMS(Measure[] measures) {
        Number[] result = new Number[3];
        int lastIdx = -1;
        for (Measure m : measures) {
            if (m.getNumber().doubleValue() < 0.0) {
                return null;
            }
            Integer idxObj = hmsTo012.get(m.getUnit());
            if (idxObj == null) {
                return null;
            }
            int idx = idxObj.intValue();
            if (idx <= lastIdx) {
                // hour before minute before second
                return null;
            }
            lastIdx = idx;
            result[idx] = m.getNumber();
        }
        return result;
    }

    // Formats numeric time duration as 5:00:47 or 3:54. In the process, it replaces any null
    // values in hms with 0.
    private void formatNumeric(Number[] hms, Appendable appendable) {
        String pattern;

        // All possible combinations: "h", "m", "s", "hm", "hs", "ms", "hms"
        if (hms[0] != null && hms[2] != null) { // "hms" & "hs" (we add minutes if "hs")
            pattern = numericFormatters.getHourMinuteSecond();
            if (hms[1] == null)
                hms[1] = 0;
            hms[1] = Math.floor(hms[1].doubleValue());
            hms[0] = Math.floor(hms[0].doubleValue());
        } else if (hms[0] != null && hms[1] != null) { // "hm"
            pattern = numericFormatters.getHourMinute();
            hms[0] = Math.floor(hms[0].doubleValue());
        } else if (hms[1] != null && hms[2] != null) { // "ms"
            pattern = numericFormatters.getMinuteSecond();
            hms[1] = Math.floor(hms[1].doubleValue());
        } else { // h m s, handled outside formatNumeric. No value is also an error.
            throw new IllegalStateException();
        }

        // We can create it on demand, but all of the patterns (right now) have mm and ss.
        // So unless it is hours only we will need a 0-padded 2 digits formatter.
        LocalizedNumberFormatter numberFormatter2 = numberFormatter.integerWidth(IntegerWidth.zeroFillTo(2));
        FormattedStringBuilder fsb = new FormattedStringBuilder();

        boolean protect = false;
        for (int i = 0; i < pattern.length(); i++) {
            char c = pattern.charAt(i);

            // Also set the proper field in this switch
            // We don't use DateFormat.Field because this is not a date / time, is a duration.
            Number value = 0;
            switch (c) {
                case 'H': value = hms[0]; break;
                case 'm': value = hms[1]; break;
                case 's': value = hms[2]; break;
            }

            // There is not enough info to add Field(s) for the unit because all we have are plain
            // text patterns. For example in "21:51" there is no text for something like "hour",
            // while in something like "21h51" there is ("h"). But we can't really tell...
            switch (c) {
                case 'H':
                case 'm':
                case 's':
                    if (protect) {
                        fsb.appendChar16(c, null);
                    } else {
                        if ((i + 1 < pattern.length()) && pattern.charAt(i + 1) == c) { // doubled
                            fsb.append(numberFormatter2.format(value), null); // TODO: Use proper Field
                            i++;
                        } else {
                            fsb.append(numberFormatter.format(value), null); // TODO: Use proper Field
                        }
                    }
                    break;
                case '\'':
                    // '' is escaped apostrophe
                    if ((i + 1 < pattern.length()) && pattern.charAt(i + 1) == c) {
                        fsb.appendChar16(c, null);
                        i++;
                    } else {
                        protect = !protect;
                    }
                    break;
                default:
                    fsb.appendChar16(c, null);
            }
        }

        try {
            appendable.append(fsb);
        } catch (IOException e) {
            throw new ICUUncheckedIOException(e);
        }
    }

    Object toTimeUnitProxy() {
        return new MeasureProxy(getLocale(), formatWidth, getNumberFormatInternal(), TIME_UNIT_FORMAT);
    }

    Object toCurrencyProxy() {
        return new MeasureProxy(getLocale(), formatWidth, getNumberFormatInternal(), CURRENCY_FORMAT);
    }

    private Object writeReplace() throws ObjectStreamException {
        return new MeasureProxy(getLocale(), formatWidth, getNumberFormatInternal(), MEASURE_FORMAT);
    }

    static class MeasureProxy implements Externalizable {
        private static final long serialVersionUID = -6033308329886716770L;

        private ULocale locale;
        private FormatWidth formatWidth;
        private NumberFormat numberFormat;
        private int subClass;
        private HashMap<Object, Object> keyValues;

        public MeasureProxy(ULocale locale, FormatWidth width, NumberFormat numberFormat, int subClass) {
            this.locale = locale;
            this.formatWidth = width;
            this.numberFormat = numberFormat;
            this.subClass = subClass;
            this.keyValues = new HashMap<>();
        }

        // Must have public constructor, to enable Externalizable
        public MeasureProxy() {
        }

        @Override
        public void writeExternal(ObjectOutput out) throws IOException {
            out.writeByte(0); // version
            out.writeUTF(locale.toLanguageTag());
            out.writeByte(formatWidth.ordinal());
            out.writeObject(numberFormat);
            out.writeByte(subClass);
            out.writeObject(keyValues);
        }

        @Override
        @SuppressWarnings("unchecked")
        public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
            in.readByte(); // version.
            locale = ULocale.forLanguageTag(in.readUTF());
            formatWidth = fromFormatWidthOrdinal(in.readByte() & 0xFF);
            numberFormat = (NumberFormat) in.readObject();
            if (numberFormat == null) {
                throw new InvalidObjectException("Missing number format.");
            }
            subClass = in.readByte() & 0xFF;

            // This cast is safe because the serialized form of hashtable can have
            // any object as the key and any object as the value.
            keyValues = (HashMap<Object, Object>) in.readObject();
            if (keyValues == null) {
                throw new InvalidObjectException("Missing optional values map.");
            }
        }

        private TimeUnitFormat createTimeUnitFormat() throws InvalidObjectException {
            int style;
            if (formatWidth == FormatWidth.WIDE) {
                style = TimeUnitFormat.FULL_NAME;
            } else if (formatWidth == FormatWidth.SHORT) {
                style = TimeUnitFormat.ABBREVIATED_NAME;
            } else {
                throw new InvalidObjectException("Bad width: " + formatWidth);
            }
            TimeUnitFormat result = new TimeUnitFormat(locale, style);
            result.setNumberFormat(numberFormat);
            return result;
        }

        private Object readResolve() throws ObjectStreamException {
            switch (subClass) {
            case MEASURE_FORMAT:
                return MeasureFormat.getInstance(locale, formatWidth, numberFormat);
            case TIME_UNIT_FORMAT:
                return createTimeUnitFormat();
            case CURRENCY_FORMAT:
                return MeasureFormat.getCurrencyFormat(locale);
            default:
                throw new InvalidObjectException("Unknown subclass: " + subClass);
            }
        }
    }

    private static FormatWidth fromFormatWidthOrdinal(int ordinal) {
        FormatWidth[] values = FormatWidth.values();
        if (ordinal < 0 || ordinal >= values.length) {
            return FormatWidth.SHORT;
        }
        return values[ordinal];
    }

    private static final Map<ULocale, String> localeIdToRangeFormat = new ConcurrentHashMap<>();

    /**
     * Return a formatter (compiled SimpleFormatter pattern) for a range, such as "{0}–{1}".
     *
     * @param forLocale
     *            locale to get the format for
     * @param width
     *            the format width
     * @return range formatter, such as "{0}–{1}"
     * @internal
     * @deprecated This API is ICU internal only.
     */
    @Deprecated
    public static String getRangeFormat(ULocale forLocale, FormatWidth width) {
        // TODO fix Hack for French
        if (forLocale.getLanguage().equals("fr")) {
            return getRangeFormat(ULocale.ROOT, width);
        }
        String result = localeIdToRangeFormat.get(forLocale);
        if (result == null) {
            ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle
                    .getBundleInstance(ICUData.ICU_BASE_NAME, forLocale);
            ULocale realLocale = rb.getULocale();
            if (!forLocale.equals(realLocale)) { // if the child would inherit, then add a cache entry
                                                 // for it.
                result = localeIdToRangeFormat.get(forLocale);
                if (result != null) {
                    localeIdToRangeFormat.put(forLocale, result);
                    return result;
                }
            }
            // At this point, both the forLocale and the realLocale don't have an item
            // So we have to make one.
            NumberingSystem ns = NumberingSystem.getInstance(forLocale);

            String resultString = null;
            try {
                resultString = rb
                        .getStringWithFallback("NumberElements/" + ns.getName() + "/miscPatterns/range");
            } catch (MissingResourceException ex) {
                resultString = rb.getStringWithFallback("NumberElements/latn/patterns/range");
            }
            result = SimpleFormatterImpl
                    .compileToStringMinMaxArguments(resultString, new StringBuilder(), 2, 2);
            localeIdToRangeFormat.put(forLocale, result);
            if (!forLocale.equals(realLocale)) {
                localeIdToRangeFormat.put(realLocale, result);
            }
        }
        return result;
    }
}
