/*
**********************************************************************
* Copyright (c) 2004-2014, 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.text.FieldPosition;
import java.text.ParsePosition;
import java.util.Arrays;
import java.util.Collection;
import java.util.Date;
import java.util.EnumMap;
import java.util.HashMap;
import java.util.Map;
import java.util.MissingResourceException;

import com.ibm.icu.impl.DontCareFieldPosition;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.impl.SimplePatternFormatter;
import com.ibm.icu.math.BigDecimal;
import com.ibm.icu.util.Currency;
import com.ibm.icu.util.CurrencyAmount;
import com.ibm.icu.util.Measure;
import com.ibm.icu.util.MeasureUnit;
import com.ibm.icu.util.TimeZone;
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>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 ImmutableNumberFormat numberFormat;
    
    private final transient FormatWidth formatWidth;
    
    // PluralRules is documented as being immutable which implies thread-safety.
    private final transient PluralRules rules;
    
    // Measure unit -> format width -> plural form -> pattern ("{0} meters")
    private final transient Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>> unitToStyleToCountToFormat;
    
    private final transient NumericFormatters numericFormatters;
    
    private final transient ImmutableNumberFormat currencyFormat;
    
    private final transient ImmutableNumberFormat integerFormat;

    private static final SimpleCache<ULocale,Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>>> localeToUnitToStyleToCountToFormat
            = new SimpleCache<ULocale,Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>>>();
  
    private static final SimpleCache<ULocale, NumericFormatters> localeToNumericDurationFormatters
            = new SimpleCache<ULocale,NumericFormatters>();
    
    private static final Map<MeasureUnit, Integer> hmsTo012 =
            new HashMap<MeasureUnit, Integer>();
    
    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.
     * 
     * @draft ICU 53
     * @provisional
     */
    // Be sure to update MeasureUnitTest.TestSerialFormatWidthEnum
    // when adding an enum value.
    public enum FormatWidth {
        
        /**
         * Spell out everything.
         * 
         * @draft ICU 53
         * @provisional
         */
        WIDE("units", ListFormatter.Style.DURATION, NumberFormat.PLURALCURRENCYSTYLE), 
        
        /**
         * Abbreviate when possible.
         * 
         * @draft ICU 53
         * @provisional
         */
        SHORT("unitsShort", ListFormatter.Style.DURATION_SHORT, NumberFormat.ISOCURRENCYSTYLE), 
        
        /**
         * Brief. Use only a symbol for the unit when possible.
         * 
         * @draft ICU 53
         * @provisional
         */
        NARROW("unitsNarrow", ListFormatter.Style.DURATION_NARROW, NumberFormat.CURRENCYSTYLE),
        
        /**
         * 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.
         * 
         * @draft ICU 53
         * @provisional
         */
        NUMERIC("unitsNarrow", ListFormatter.Style.DURATION_NARROW, NumberFormat.CURRENCYSTYLE);
        
        // Be sure to update the toFormatWidth and fromFormatWidth() functions
        // when adding an enum value.
    
        final String resourceKey;
        private final ListFormatter.Style listFormatterStyle;
        private final int currencyStyle;
    
        private FormatWidth(String resourceKey, ListFormatter.Style style, int currencyStyle) {
            this.resourceKey = resourceKey;
            this.listFormatterStyle = style;
            this.currencyStyle = currencyStyle;
        }
        
        ListFormatter.Style getListFormatterStyle() {
            return listFormatterStyle;
        }
        
        int getCurrencyStyle() {
            return currencyStyle;
        }
    }
    
    /**
     * 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.
     * @draft ICU 53
     * @provisional
     */
    public static MeasureFormat getInstance(ULocale locale, FormatWidth formatWidth) {
        return getInstance(locale, formatWidth, NumberFormat.getInstance(locale));
    }
    
    /**
     * 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.
     * @draft ICU 53
     * @provisional
     */
    public static MeasureFormat getInstance(ULocale locale, FormatWidth formatWidth, NumberFormat format) {
        PluralRules rules = PluralRules.forLocale(locale);
        Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>> unitToStyleToCountToFormat;
        NumericFormatters formatters = null;
        unitToStyleToCountToFormat = localeToUnitToStyleToCountToFormat.get(locale);
        if (unitToStyleToCountToFormat == null) {
            unitToStyleToCountToFormat = loadLocaleData(locale, rules);
            localeToUnitToStyleToCountToFormat.put(locale, unitToStyleToCountToFormat);
        }
        if (formatWidth == FormatWidth.NUMERIC) {
            formatters = localeToNumericDurationFormatters.get(locale);
            if (formatters == null) {
                formatters = loadNumericFormatters(locale);
                localeToNumericDurationFormatters.put(locale, formatters);
            }
        }
        NumberFormat intFormat = NumberFormat.getInstance(locale);
        intFormat.setMaximumFractionDigits(0);
        intFormat.setMinimumFractionDigits(0);
        intFormat.setRoundingMode(BigDecimal.ROUND_DOWN);
        return new MeasureFormat(
                locale,
                formatWidth,
                new ImmutableNumberFormat(format),
                rules,
                unitToStyleToCountToFormat,
                formatters,
                new ImmutableNumberFormat(
                        NumberFormat.getInstance(locale, formatWidth.getCurrencyStyle())),
                new ImmutableNumberFormat(intFormat));
    }
    
    /**
     * 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<? extends Measure>, Measure[], or Measure object.
     * @param toAppendTo Formatted string appended here.
     * @param pos Identifies a field in the formatted text.
     * @see java.text.Format#format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition)
     * 
     * @draft ICU53
     * @provisional
     */
    @Override
    public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
        int prevLength = toAppendTo.length();
        FieldPosition fpos =
                new FieldPosition(pos.getFieldAttribute(), pos.getField());
        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;
            }
            toAppendTo.append(formatMeasures(new StringBuilder(), fpos, measures));
        } else if (obj instanceof Measure[]) {
            toAppendTo.append(formatMeasures(new StringBuilder(), fpos, (Measure[]) obj));
        } else if (obj instanceof Measure){
            toAppendTo.append(formatMeasure((Measure) obj, numberFormat, new StringBuilder(), fpos));
        } else {
            throw new IllegalArgumentException(obj.toString());            
        }
        if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) {
            pos.setBeginIndex(fpos.getBeginIndex() + prevLength);
            pos.setEndIndex(fpos.getEndIndex() + prevLength);
        }
        return toAppendTo;
    }
    
    /**
     * @see java.text.Format#parseObject(java.lang.String, java.text.ParsePosition)
     * @throws UnsupportedOperationException Not supported.
     * @draft ICU 53
     * @provisional
     */
    @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.
     * @draft ICU 53
     * @provisional
     */
    public final String formatMeasures(Measure... measures) {
        return formatMeasures(
                new StringBuilder(),
                DontCareFieldPosition.INSTANCE,
                measures).toString();
    }
    
    /**
     * 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 fieldPosition Identifies a field in the formatted text.
     * @param measures the measures to format.
     * @return appendTo.
     * @see MeasureFormat#formatMeasures(Measure...)
     * @draft ICU 53
     * @provisional
     */
    public StringBuilder formatMeasures(
            StringBuilder appendTo, FieldPosition fieldPosition, Measure... measures) {
        // fast track for trivial cases
        if (measures.length == 0) {
            return appendTo;
        }
        if (measures.length == 1) {
            return formatMeasure(measures[0], numberFormat, appendTo, fieldPosition);
        }
        
        if (formatWidth == FormatWidth.NUMERIC) {
            // If we have just hour, minute, or second follow the numeric
            // track.
            Number[] hms = toHMS(measures);
            if (hms != null) {
                return formatNumeric(hms, appendTo);
            }
        }
        
        ListFormatter listFormatter = ListFormatter.getInstance(
                getLocale(), formatWidth.getListFormatterStyle());
        if (fieldPosition != DontCareFieldPosition.INSTANCE) {
            return formatMeasuresSlowTrack(listFormatter, appendTo, fieldPosition, measures);
        }
        // Fast track: No field position.
        String[] results = new String[measures.length];
        for (int i = 0; i < measures.length; i++) {
            results[i] = formatMeasure(
                    measures[i],
                    i == measures.length - 1 ? numberFormat : integerFormat);
        }
        return appendTo.append(listFormatter.format((Object[]) results));                 
       
    }   
    
    /**
     * Two MeasureFormats, a and b, are equal if and only if they have the same formatWidth,
     * locale, and equal number formats.
     * @draft ICU 53
     * @provisional
     */
    @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()) 
                && getNumberFormat().equals(rhs.getNumberFormat());
    }
    
    /**
     * @draft ICU 53
     * @provisional
     */
    @Override
    public final int hashCode() {
        // A very slow but safe implementation.
        return (getLocale().hashCode() * 31 
                + getNumberFormat().hashCode()) * 31 + getWidth().hashCode();
    }
    
    /**
     * Get the format width this instance is using.
     * @draft ICU 53
     * @provisional
     */
    public MeasureFormat.FormatWidth getWidth() {
        return formatWidth;
    }
    
    /**
     * Get the locale of this instance.
     * @draft ICU 53
     * @provisional
     */
    public final ULocale getLocale() {
        return getLocale(ULocale.VALID_LOCALE);
    }
    
    /**
     * Get a copy of the number format.
     * @draft ICU 53
     * @provisional
     */
    public NumberFormat getNumberFormat() {
        return numberFormat.get();
    }

    /**
     * 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 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,
                new ImmutableNumberFormat(format),
                this.rules,
                this.unitToStyleToCountToFormat,
                this.numericFormatters,
                this.currencyFormat,
                this.integerFormat);
    }
    
    private MeasureFormat(
            ULocale locale,
            FormatWidth formatWidth,
            ImmutableNumberFormat format,
            PluralRules rules,
            Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>> unitToStyleToCountToFormat,
            NumericFormatters formatters,
            ImmutableNumberFormat currencyFormat,
            ImmutableNumberFormat integerFormat) {
        setLocale(locale, locale);
        this.formatWidth = formatWidth;
        this.numberFormat = format;
        this.rules = rules;
        this.unitToStyleToCountToFormat = unitToStyleToCountToFormat;
        this.numericFormatters = formatters;
        this.currencyFormat = currencyFormat;
        this.integerFormat = integerFormat;
    }
    
    MeasureFormat() {
        // Make compiler happy by setting final fields to null.
        this.formatWidth = null;
        this.numberFormat = null;
        this.rules = null;
        this.unitToStyleToCountToFormat = null;
        this.numericFormatters = null;
        this.currencyFormat = null;
        this.integerFormat = null;
    }
    
    static class NumericFormatters {
        private DateFormat hourMinute;
        private DateFormat minuteSecond;
        private DateFormat hourMinuteSecond;
        
        public NumericFormatters(
                DateFormat hourMinute,
                DateFormat minuteSecond,
                DateFormat hourMinuteSecond) {
            this.hourMinute = hourMinute;
            this.minuteSecond = minuteSecond;
            this.hourMinuteSecond = hourMinuteSecond;
        }
        
        public DateFormat getHourMinute() { return hourMinute; }
        public DateFormat getMinuteSecond() { return minuteSecond; }
        public DateFormat getHourMinuteSecond() { return hourMinuteSecond; }
    }
    
    private static NumericFormatters loadNumericFormatters(
            ULocale locale) {
        ICUResourceBundle r = (ICUResourceBundle)UResourceBundle.
                getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, locale);
        return new NumericFormatters(
                loadNumericDurationFormat(r, "hm"),
                loadNumericDurationFormat(r, "ms"),
                loadNumericDurationFormat(r, "hms"));
    }
    
    /**
     * Returns formatting data for all MeasureUnits except for currency ones.
     */
    private static Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>> loadLocaleData(
            ULocale locale, PluralRules rules) {
        QuantityFormatter.Builder builder = new QuantityFormatter.Builder();
        Map<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>> unitToStyleToCountToFormat
                = new HashMap<MeasureUnit, EnumMap<FormatWidth, QuantityFormatter>>();
        ICUResourceBundle resource = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_BASE_NAME, locale);
        for (MeasureUnit unit : MeasureUnit.getAvailable()) {
            // Currency data cannot be found here. Skip.
            if (unit instanceof Currency) {
                continue;
            }
            EnumMap<FormatWidth, QuantityFormatter> styleToCountToFormat = unitToStyleToCountToFormat.get(unit);
            if (styleToCountToFormat == null) {
                unitToStyleToCountToFormat.put(unit, styleToCountToFormat = new EnumMap<FormatWidth, QuantityFormatter>(FormatWidth.class));
            }
            for (FormatWidth styleItem : FormatWidth.values()) {
                try {
                    ICUResourceBundle unitTypeRes = resource.getWithFallback(styleItem.resourceKey);
                    ICUResourceBundle unitsRes = unitTypeRes.getWithFallback(unit.getType());
                    ICUResourceBundle oneUnitRes = unitsRes.getWithFallback(unit.getSubtype());
                    builder.reset();
                    int len = oneUnitRes.getSize();
                    for (int i = 0; i < len; i++) {
                        UResourceBundle countBundle;
                        try {
                            countBundle = oneUnitRes.get(i);
                        } catch (MissingResourceException e) {
                            continue;
                        }
                        builder.add(countBundle.getKey(), countBundle.getString());
                    }
                    styleToCountToFormat.put(styleItem, builder.build());
                } catch (MissingResourceException e) {
                    continue;
                }
            }
            // now fill in the holes
            fillin:
                if (styleToCountToFormat.size() != FormatWidth.values().length) {
                    QuantityFormatter fallback = styleToCountToFormat.get(FormatWidth.SHORT);
                    if (fallback == null) {
                        fallback = styleToCountToFormat.get(FormatWidth.WIDE);
                    }
                    if (fallback == null) {
                        break fillin; // TODO use root
                    }
                    for (FormatWidth styleItem : FormatWidth.values()) {
                        QuantityFormatter countToFormat = styleToCountToFormat.get(styleItem);
                        if (countToFormat == null) {
                            styleToCountToFormat.put(styleItem, fallback);
                        }
                    }
                }
        }
        return unitToStyleToCountToFormat;
    }
    
    private String formatMeasure(Measure measure, ImmutableNumberFormat nf) {
        return formatMeasure(
                measure, nf, new StringBuilder(),
                DontCareFieldPosition.INSTANCE).toString();
    }
    
    private StringBuilder formatMeasure(
            Measure measure,
            ImmutableNumberFormat nf,
            StringBuilder appendTo,
            FieldPosition fieldPosition) {
        if (measure.getUnit() instanceof Currency) {
            return appendTo.append(
                    currencyFormat.format(
                    new CurrencyAmount(measure.getNumber(), (Currency) measure.getUnit()),
                    new StringBuffer(),
                    fieldPosition));
            
        }
        Number n = measure.getNumber();
        MeasureUnit unit = measure.getUnit(); 
        UFieldPosition fpos = new UFieldPosition(fieldPosition.getFieldAttribute(), fieldPosition.getField());
        StringBuffer formattedNumber = nf.format(n, new StringBuffer(), fpos);
        String keyword = rules.select(new PluralRules.FixedDecimal(n.doubleValue(), fpos.getCountVisibleFractionDigits(), fpos.getFractionDigits()));

        Map<FormatWidth, QuantityFormatter> styleToCountToFormat = unitToStyleToCountToFormat.get(unit);
        QuantityFormatter countToFormat = styleToCountToFormat.get(formatWidth);
        SimplePatternFormatter formatter = countToFormat.getByVariant(keyword);
        int[] offsets = new int[1];
        formatter.format(appendTo, offsets, formattedNumber);
        if (offsets[0] != -1) { // there is a number (may not happen with, say, Arabic dual)
            // Fix field position
            if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) {
                fieldPosition.setBeginIndex(fpos.getBeginIndex() + offsets[0]);
                fieldPosition.setEndIndex(fpos.getEndIndex() + offsets[0]);
            }
        }
        return appendTo;
    }
    
    // Wrapper around NumberFormat that provides immutability and thread-safety.
    private static final class ImmutableNumberFormat {
        private NumberFormat nf;
        
        public ImmutableNumberFormat(NumberFormat nf) {
            this.nf = (NumberFormat) nf.clone();
        }
        
        public synchronized NumberFormat get() {
            return (NumberFormat) nf.clone();
        }
        
        public synchronized StringBuffer format(
                Number n, StringBuffer buffer, FieldPosition pos) {
            return nf.format(n, buffer, pos);
        }
        
        public synchronized StringBuffer format(
                CurrencyAmount n, StringBuffer buffer, FieldPosition pos) {
            return nf.format(n, buffer, pos);
        }

        public synchronized String format(Number number) {
            return nf.format(number);
        }
    }
    
    static final class PatternData {
        final String prefix;
        final String suffix;
        public PatternData(String pattern) {
            int pos = pattern.indexOf("{0}");
            if (pos < 0) {
                prefix = pattern;
                suffix = null;
            } else {
                prefix = pattern.substring(0,pos);
                suffix = pattern.substring(pos+3);
            }
        }
        public String toString() {
            return prefix + "; " + suffix;
        }

    }
    
    Object toTimeUnitProxy() {
        return new MeasureProxy(getLocale(), formatWidth, numberFormat.get(), TIME_UNIT_FORMAT);
    }
    
    Object toCurrencyProxy() {
        return new MeasureProxy(getLocale(), formatWidth, numberFormat.get(), CURRENCY_FORMAT);
    }
    
    private StringBuilder formatMeasuresSlowTrack(
            ListFormatter listFormatter,
            StringBuilder 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) {
            ImmutableNumberFormat nf = (i == measures.length - 1 ? numberFormat : integerFormat);
            if (fieldPositionFoundIndex == -1) {
                results[i] = formatMeasure(measures[i], nf, new StringBuilder(), fpos).toString();
                if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) {
                    fieldPositionFoundIndex = i;    
                }
            } else {
                results[i] = formatMeasure(measures[i], nf);
            }
        }
        ListFormatter.FormattedListBuilder builder =
                listFormatter.format(Arrays.asList(results), fieldPositionFoundIndex);
        
        // Fix up FieldPosition indexes if our field is found.
        if (builder.getOffset() != -1) {
            fieldPosition.setBeginIndex(fpos.getBeginIndex() + builder.getOffset() + appendTo.length());
            fieldPosition.setEndIndex(fpos.getEndIndex() + builder.getOffset() + appendTo.length());
        }
        return appendTo.append(builder.toString());
    }
    
    // type is one of "hm", "ms" or "hms"
    private static DateFormat 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.
        DateFormat result = new SimpleDateFormat(r.getString().replace("h", "H"));
        result.setTimeZone(TimeZone.GMT_ZONE);
        return result;
    }
    
    // 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 StringBuilder formatNumeric(Number[] hms, StringBuilder appendable) {
        
        // find the start and end of non-nil values in hms array. We have to know if we
        // have hour-minute; minute-second; or hour-minute-second.
        int startIndex = -1;
        int endIndex = -1;
        for (int i = 0; i < hms.length; i++) {
            if (hms[i] != null) {
                endIndex = i;
                if (startIndex == -1) {
                    startIndex = endIndex;
                }
            } else {
                // Replace nil value with 0.
                hms[i] = Integer.valueOf(0);
            }
        }
        // convert hours, minutes, seconds into milliseconds.
        long millis = (long) (((Math.floor(hms[0].doubleValue()) * 60.0
                + Math.floor(hms[1].doubleValue())) * 60.0
                + Math.floor(hms[2].doubleValue())) * 1000.0);
        Date d = new Date(millis);
        // if hour-minute-second
        if (startIndex == 0 && endIndex == 2) {
            return formatNumeric(
                    d, 
                    numericFormatters.getHourMinuteSecond(),
                    DateFormat.Field.SECOND,
                    hms[endIndex],
                    appendable);
        }
        // if minute-second
        if (startIndex == 1 && endIndex == 2) {
            return formatNumeric(
                    d, 
                    numericFormatters.getMinuteSecond(),
                    DateFormat.Field.SECOND,
                    hms[endIndex],
                    appendable);
        }
        // if hour-minute
        if (startIndex == 0 && endIndex == 1) {
            return formatNumeric(
                    d, 
                    numericFormatters.getHourMinute(),
                    DateFormat.Field.MINUTE,
                    hms[endIndex],
                    appendable);
        }
        throw new IllegalStateException();
    }
    
    // Formats a duration as 5:00:37 or 23:59.
    // duration is a particular duration after epoch.
    // formatter is a hour-minute-second, hour-minute, or minute-second formatter.
    // smallestField denotes what the smallest field is in duration: either
    // hour, minute, or second.
    // smallestAmount is the value of that smallest field. for 5:00:37.3,
    // smallestAmount is 37.3. This smallest field is formatted with this object's
    // NumberFormat instead of formatter.
    // appendTo is where the formatted string is appended.
    private StringBuilder formatNumeric(
            Date duration,
            DateFormat formatter,
            DateFormat.Field smallestField,
            Number smallestAmount,
            StringBuilder appendTo) {
        // Format the smallest amount ahead of time.
        String smallestAmountFormatted;
        
        // Format the smallest amount using this object's number format, but keep track
        // of the integer portion of this formatted amount. We have to replace just the
        // integer part with the corresponding value from formatting the date. Otherwise
        // when formatting 0 minutes 9 seconds, we may get "00:9" instead of "00:09"
        FieldPosition intFieldPosition = new FieldPosition(NumberFormat.INTEGER_FIELD);
        smallestAmountFormatted = numberFormat.format(
                smallestAmount, new StringBuffer(), intFieldPosition).toString();
        // Give up if there is no integer field.
        if (intFieldPosition.getBeginIndex() == 0 && intFieldPosition.getEndIndex() == 0) {
            throw new IllegalStateException();
        }
        // Format our duration as a date, but keep track of where the smallest field is
        // so that we can use it to replace the integer portion of the smallest value.
        FieldPosition smallestFieldPosition = new FieldPosition(smallestField);
        String draft = formatter.format(
                duration, new StringBuffer(), smallestFieldPosition).toString();
        
        // If we find the smallest field
        if (smallestFieldPosition.getBeginIndex() != 0
                || smallestFieldPosition.getEndIndex() != 0) {
            // add everything up to the start of the smallest field in duration.
            appendTo.append(draft, 0, smallestFieldPosition.getBeginIndex());
            
            // add everything in the smallest field up to the integer portion
            appendTo.append(smallestAmountFormatted, 0, intFieldPosition.getBeginIndex());
            
            // Add the smallest field in formatted duration in lieu of the integer portion
            // of smallest field
            appendTo.append(
                    draft,
                    smallestFieldPosition.getBeginIndex(),
                    smallestFieldPosition.getEndIndex());
            
            // Add the rest of the smallest field
            appendTo.append(
                    smallestAmountFormatted,
                    intFieldPosition.getEndIndex(),
                    smallestAmountFormatted.length());
            appendTo.append(draft, smallestFieldPosition.getEndIndex(), draft.length());
        } else {
            // As fallback, just use the formatted duration.
            appendTo.append(draft);
        }
        return appendTo;
    }
    
    private Object writeReplace() throws ObjectStreamException {
        return new MeasureProxy(
                getLocale(), formatWidth, numberFormat.get(), 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<Object, Object>();
        }

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

        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);
        }

        @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 new CurrencyFormat(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.WIDE;
        }
        return values[ordinal];
    }
}
