// © 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.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;
    }
}
