// © 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.ICUData;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.impl.SimpleFormatterImpl;
import com.ibm.icu.impl.number.LongNameHandler;
import com.ibm.icu.impl.number.RoundingUtils;
import com.ibm.icu.number.FormattedNumber;
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) {
            FormattedNumber result = formatMeasure((Measure) obj);
            result.nextFieldPosition(fpos); // No offset: toAppendTo.length() is considered below
            result.appendTo(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) {
        FormattedNumber result = getUnitFormatterFromCache(NUMBER_FORMATTER_STANDARD,
                measure.getUnit(),
                perUnit).format(measure.getNumber());
        DecimalFormat.fieldPositionHelper(result, pos, appendTo.length());
        result.appendTo(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) {
            FormattedNumber result = formatMeasure(measures[0]);
            result.nextFieldPosition(fieldPosition);
            result.appendTo(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 FormattedNumber formatMeasure(Measure measure) {
        MeasureUnit unit = measure.getUnit();
        if (unit instanceof Currency) {
            return getUnitFormatterFromCache(NUMBER_FORMATTER_CURRENCY, unit, null)
                    .format(measure.getNumber());
        } else {
            return getUnitFormatterFromCache(NUMBER_FORMATTER_STANDARD, unit, null)
                    .format(measure.getNumber());
        }
    }

    private FormattedNumber formatMeasureInteger(Measure measure) {
        return getUnitFormatterFromCache(NUMBER_FORMATTER_INTEGER, measure.getUnit(), null)
                .format(measure.getNumber());
    }

    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) {
            FormattedNumber result;
            if (i == measures.length - 1) {
                result = formatMeasure(measures[i]);
            } else {
                result = formatMeasureInteger(measures[i]);
            }
            if (fieldPositionFoundIndex == -1) {
                result.nextFieldPosition(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;
    }
}
