// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/*
 **********************************************************************
 * 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.
 * <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.Style.UNIT, UnitWidth.FULL_NAME, UnitWidth.FULL_NAME),

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

        /**
         * Brief. Use only a symbol for the unit when possible.
         *
         * @stable ICU 53
         */
        NARROW(ListFormatter.Style.UNIT_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.Style.UNIT_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.Style.UNIT, UnitWidth.FULL_NAME, UnitWidth.SHORT);

        private final ListFormatter.Style listFormatterStyle;

        /**
         * 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.Style style, UnitWidth unitWidth, UnitWidth currencyWidth) {
            this.listFormatterStyle = style;
            this.unitWidth = unitWidth;
            this.currencyWidth = currencyWidth;
        }

        ListFormatter.Style getListFormatterStyle() {
            return listFormatterStyle;
        }
    }

    /**
     * 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)
     * @provisional This API might change or be removed in a future release.
     */
    @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(),
                formatWidth.getListFormatterStyle());
        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;
    }
}
