// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
/*
 *******************************************************************************
 * Copyright (C) 2013-2016, International Business Machines Corporation and
 * others. All Rights Reserved.
 *******************************************************************************
 */
package com.ibm.icu.text;

import java.io.InvalidObjectException;
import java.text.AttributedCharacterIterator;
import java.text.Format;
import java.util.EnumMap;
import java.util.Locale;

import com.ibm.icu.impl.CacheBase;
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.SimpleFormatterImpl;
import com.ibm.icu.impl.SoftCache;
import com.ibm.icu.impl.StandardPlural;
import com.ibm.icu.impl.UResource;
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.lang.UCharacter;
import com.ibm.icu.util.Calendar;
import com.ibm.icu.util.ICUException;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.UResourceBundle;


/**
 * Formats simple relative dates. There are two types of relative dates that
 * it handles:
 * <ul>
 *   <li>relative dates with a quantity e.g "in 5 days"</li>
 *   <li>relative dates without a quantity e.g "next Tuesday"</li>
 * </ul>
 * <p>
 * This API is very basic and is intended to be a building block for more
 * fancy APIs. The caller tells it exactly what to display in a locale
 * independent way. While this class automatically provides the correct plural
 * forms, the grammatical form is otherwise as neutral as possible. It is the
 * caller's responsibility to handle cut-off logic such as deciding between
 * displaying "in 7 days" or "in 1 week." This API supports relative dates
 * involving one single unit. This API does not support relative dates
 * involving compound units.
 * e.g "in 5 days and 4 hours" nor does it support parsing.
 * This class is both immutable and thread-safe.
 * <p>
 * Here are some examples of use:
 * <blockquote>
 * <pre>
 * RelativeDateTimeFormatter fmt = RelativeDateTimeFormatter.getInstance();
 * fmt.format(1, Direction.NEXT, RelativeUnit.DAYS); // "in 1 day"
 * fmt.format(3, Direction.NEXT, RelativeUnit.DAYS); // "in 3 days"
 * fmt.format(3.2, Direction.LAST, RelativeUnit.YEARS); // "3.2 years ago"
 *
 * fmt.format(Direction.LAST, AbsoluteUnit.SUNDAY); // "last Sunday"
 * fmt.format(Direction.THIS, AbsoluteUnit.SUNDAY); // "this Sunday"
 * fmt.format(Direction.NEXT, AbsoluteUnit.SUNDAY); // "next Sunday"
 * fmt.format(Direction.PLAIN, AbsoluteUnit.SUNDAY); // "Sunday"
 *
 * fmt.format(Direction.LAST, AbsoluteUnit.DAY); // "yesterday"
 * fmt.format(Direction.THIS, AbsoluteUnit.DAY); // "today"
 * fmt.format(Direction.NEXT, AbsoluteUnit.DAY); // "tomorrow"
 *
 * fmt.format(Direction.PLAIN, AbsoluteUnit.NOW); // "now"
 * </pre>
 * </blockquote>
 * <p>
 * In the future, we may add more forms, such as abbreviated/short forms
 * (3 secs ago), and relative day periods ("yesterday afternoon"), etc.
 *
 * @stable ICU 53
 */
public final class RelativeDateTimeFormatter {

    /**
     * The formatting style
     * @stable ICU 54
     *
     */
    public static enum Style {

        /**
         * Everything spelled out.
         * @stable ICU 54
         */
        LONG,

        /**
         * Abbreviations used when possible.
         * @stable ICU 54
         */
        SHORT,

        /**
         * Use single letters when possible.
         * @stable ICU 54
         */
        NARROW;

        private static final int INDEX_COUNT = 3;  // NARROW.ordinal() + 1
    }

    /**
     * Represents the unit for formatting a relative date. e.g "in 5 days"
     * or "in 3 months"
     * @stable ICU 53
     */
    public static enum RelativeUnit {

        /**
         * Seconds
         * @stable ICU 53
         */
        SECONDS,

        /**
         * Minutes
         * @stable ICU 53
         */
        MINUTES,

       /**
        * Hours
        * @stable ICU 53
        */
        HOURS,

        /**
         * Days
         * @stable ICU 53
         */
        DAYS,

        /**
         * Weeks
         * @stable ICU 53
         */
        WEEKS,

        /**
         * Months
         * @stable ICU 53
         */
        MONTHS,

        /**
         * Years
         * @stable ICU 53
         */
        YEARS,

        /**
         * Quarters
         * @internal TODO: propose for addition in ICU 57
         * @deprecated This API is ICU internal only.
         */
        @Deprecated
        QUARTERS,
    }

    /**
     * Represents an absolute unit.
     * @stable ICU 53
     */
    public static enum AbsoluteUnit {

       /**
        * Sunday
        * @stable ICU 53
        */
        SUNDAY,

        /**
         * Monday
         * @stable ICU 53
         */
        MONDAY,

        /**
         * Tuesday
         * @stable ICU 53
         */
        TUESDAY,

        /**
         * Wednesday
         * @stable ICU 53
         */
        WEDNESDAY,

        /**
         * Thursday
         * @stable ICU 53
         */
        THURSDAY,

        /**
         * Friday
         * @stable ICU 53
         */
        FRIDAY,

        /**
         * Saturday
         * @stable ICU 53
         */
        SATURDAY,

        /**
         * Day
         * @stable ICU 53
         */
        DAY,

        /**
         * Week
         * @stable ICU 53
         */
        WEEK,

        /**
         * Month
         * @stable ICU 53
         */
        MONTH,

        /**
         * Year
         * @stable ICU 53
         */
        YEAR,

        /**
         * Now
         * @stable ICU 53
         */
        NOW,

        /**
         * Quarter
         * @stable ICU 64
         */
        QUARTER,

        /**
         * Hour
         * @stable ICU 65
         */
        HOUR,

        /**
         * Minute
         * @stable ICU 65
         */
        MINUTE,
    }

    /**
     * Represents a direction for an absolute unit e.g "Next Tuesday"
     * or "Last Tuesday"
     * @stable ICU 53
     */
    public static enum Direction {
          /**
           * Two before. Not fully supported in every locale
           * @stable ICU 53
           */
          LAST_2,

          /**
           * Last
           * @stable ICU 53
           */
          LAST,

          /**
           * This
           * @stable ICU 53
           */
          THIS,

          /**
           * Next
           * @stable ICU 53
           */
          NEXT,

          /**
           * Two after. Not fully supported in every locale
           * @stable ICU 53
           */
          NEXT_2,

          /**
           * Plain, which means the absence of a qualifier
           * @stable ICU 53
           */
          PLAIN,
    }

    /**
     * Represents the unit for formatting a relative date. e.g "in 5 days"
     * or "next year"
     * @stable ICU 57
     */
    public static enum RelativeDateTimeUnit {
        /**
         * Specifies that relative unit is year, e.g. "last year",
         * "in 5 years".
         * @stable ICU 57
         */
        YEAR,
        /**
         * Specifies that relative unit is quarter, e.g. "last quarter",
         * "in 5 quarters".
         * @stable ICU 57
         */
        QUARTER,
        /**
         * Specifies that relative unit is month, e.g. "last month",
         * "in 5 months".
         * @stable ICU 57
         */
        MONTH,
        /**
         * Specifies that relative unit is week, e.g. "last week",
         * "in 5 weeks".
         * @stable ICU 57
         */
        WEEK,
        /**
         * Specifies that relative unit is day, e.g. "yesterday",
         * "in 5 days".
         * @stable ICU 57
         */
        DAY,
        /**
         * Specifies that relative unit is hour, e.g. "1 hour ago",
         * "in 5 hours".
         * @stable ICU 57
         */
        HOUR,
        /**
         * Specifies that relative unit is minute, e.g. "1 minute ago",
         * "in 5 minutes".
         * @stable ICU 57
         */
        MINUTE,
        /**
         * Specifies that relative unit is second, e.g. "1 second ago",
         * "in 5 seconds".
         * @stable ICU 57
         */
        SECOND,
        /**
         * Specifies that relative unit is Sunday, e.g. "last Sunday",
         * "this Sunday", "next Sunday", "in 5 Sundays".
         * @stable ICU 57
         */
        SUNDAY,
        /**
         * Specifies that relative unit is Monday, e.g. "last Monday",
         * "this Monday", "next Monday", "in 5 Mondays".
         * @stable ICU 57
         */
        MONDAY,
        /**
         * Specifies that relative unit is Tuesday, e.g. "last Tuesday",
         * "this Tuesday", "next Tuesday", "in 5 Tuesdays".
         * @stable ICU 57
         */
        TUESDAY,
        /**
         * Specifies that relative unit is Wednesday, e.g. "last Wednesday",
         * "this Wednesday", "next Wednesday", "in 5 Wednesdays".
         * @stable ICU 57
         */
        WEDNESDAY,
        /**
         * Specifies that relative unit is Thursday, e.g. "last Thursday",
         * "this Thursday", "next Thursday", "in 5 Thursdays".
         * @stable ICU 57
         */
        THURSDAY,
        /**
         * Specifies that relative unit is Friday, e.g. "last Friday",
         * "this Friday", "next Friday", "in 5 Fridays".
         * @stable ICU 57
         */
        FRIDAY,
        /**
         * Specifies that relative unit is Saturday, e.g. "last Saturday",
         * "this Saturday", "next Saturday", "in 5 Saturdays".
         * @stable ICU 57
         */
        SATURDAY,
    }

    /**
     * Field constants used when accessing field information for relative
     * datetime strings in FormattedValue.
     * <p>
     * There is no public constructor to this class; the only instances are the
     * constants defined here.
     * <p>
     * @stable ICU 64
     */
    public static class Field extends Format.Field {
        private static final long serialVersionUID = -5327685528663492325L;

        /**
         * Represents a literal text string, like "tomorrow" or "days ago".
         *
         * @stable ICU 64
         */
        public static final Field LITERAL = new Field("literal");

        /**
         * Represents a number quantity, like "3" in "3 days ago".
         *
         * @stable ICU 64
         */
        public static final Field NUMERIC = new Field("numeric");

        private Field(String fieldName) {
            super(fieldName);
        }

        /**
         * Serizalization method resolve instances to the constant Field values
         *
         * @draft ICU 64
         * @provisional This API might change or be removed in a future release.
         */
        @Override
        protected Object readResolve() throws InvalidObjectException {
            if (this.getName().equals(LITERAL.getName()))
                return LITERAL;
            if (this.getName().equals(NUMERIC.getName()))
                return NUMERIC;

            throw new InvalidObjectException("An invalid object.");
        }
    }

    /**
     * Represents the result of a formatting operation of a relative datetime.
     * Access the string value or field information.
     *
     * Instances of this class are immutable and thread-safe.
     *
     * Not intended for public subclassing.
     *
     * @author sffc
     * @stable ICU 64
     */
    public static class FormattedRelativeDateTime implements FormattedValue {

        private final FormattedStringBuilder string;

        private FormattedRelativeDateTime(FormattedStringBuilder string) {
            this.string = string;
        }

        /**
         * {@inheritDoc}
         *
         * @stable ICU 64
         */
        @Override
        public String toString() {
            return string.toString();
        }

        /**
         * {@inheritDoc}
         *
         * @stable ICU 64
         */
        @Override
        public int length() {
            return string.length();
        }

        /**
         * {@inheritDoc}
         *
         * @stable ICU 64
         */
        @Override
        public char charAt(int index) {
            return string.charAt(index);
        }

        /**
         * {@inheritDoc}
         *
         * @stable ICU 64
         */
        @Override
        public CharSequence subSequence(int start, int end) {
            return string.subString(start, end);
        }

        /**
         * {@inheritDoc}
         *
         * @stable ICU 64
         */
        @Override
        public <A extends Appendable> A appendTo(A appendable) {
            return Utility.appendTo(string, appendable);
        }

        /**
         * {@inheritDoc}
         *
         * @stable ICU 64
         */
        @Override
        public boolean nextPosition(ConstrainedFieldPosition cfpos) {
            return FormattedValueStringBuilderImpl.nextPosition(string, cfpos, Field.NUMERIC);
        }

        /**
         * {@inheritDoc}
         *
         * @stable ICU 64
         */
        @Override
        public AttributedCharacterIterator toCharacterIterator() {
            return FormattedValueStringBuilderImpl.toCharacterIterator(string, Field.NUMERIC);
        }
    }

    /**
     * Returns a RelativeDateTimeFormatter for the default locale.
     * @stable ICU 53
     */
    public static RelativeDateTimeFormatter getInstance() {
        return getInstance(ULocale.getDefault(), null, Style.LONG, DisplayContext.CAPITALIZATION_NONE);
    }

    /**
     * Returns a RelativeDateTimeFormatter for a particular locale.
     *
     * @param locale the locale.
     * @return An instance of RelativeDateTimeFormatter.
     * @stable ICU 53
     */
    public static RelativeDateTimeFormatter getInstance(ULocale locale) {
        return getInstance(locale, null, Style.LONG, DisplayContext.CAPITALIZATION_NONE);
    }

    /**
     * Returns a RelativeDateTimeFormatter for a particular {@link java.util.Locale}.
     *
     * @param locale the {@link java.util.Locale}.
     * @return An instance of RelativeDateTimeFormatter.
     * @stable ICU 54
     */
    public static RelativeDateTimeFormatter getInstance(Locale locale) {
        return getInstance(ULocale.forLocale(locale));
    }

    /**
     * Returns a RelativeDateTimeFormatter for a particular locale that uses a particular
     * NumberFormat object.
     *
     * @param locale the locale
     * @param nf the number format object. It is defensively copied to ensure thread-safety
     * and immutability of this class.
     * @return An instance of RelativeDateTimeFormatter.
     * @stable ICU 53
     */
    public static RelativeDateTimeFormatter getInstance(ULocale locale, NumberFormat nf) {
        return getInstance(locale, nf, Style.LONG, DisplayContext.CAPITALIZATION_NONE);
    }

    /**
     * Returns a RelativeDateTimeFormatter for a particular locale that uses a particular
     * NumberFormat object, style, and capitalization context
     *
     * @param locale the locale
     * @param nf the number format object. It is defensively copied to ensure thread-safety
     * and immutability of this class. May be null.
     * @param style the style.
     * @param capitalizationContext the capitalization context.
     * @stable ICU 54
     */
    public static RelativeDateTimeFormatter getInstance(
            ULocale locale,
            NumberFormat nf,
            Style style,
            DisplayContext capitalizationContext) {
        RelativeDateTimeFormatterData data = cache.get(locale);
        if (nf == null) {
            nf = NumberFormat.getInstance(locale);
        } else {
            nf = (NumberFormat) nf.clone();
        }
        return new RelativeDateTimeFormatter(
                data.qualitativeUnitMap,
                data.relUnitPatternMap,
                SimpleFormatterImpl.compileToStringMinMaxArguments(
                        data.dateTimePattern, new StringBuilder(), 2, 2),
                PluralRules.forLocale(locale),
                nf,
                style,
                capitalizationContext,
                capitalizationContext == DisplayContext.CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ?
                    BreakIterator.getSentenceInstance(locale) : null,
                locale);
    }

    /**
     * Returns a RelativeDateTimeFormatter for a particular {@link java.util.Locale} that uses a
     * particular NumberFormat object.
     *
     * @param locale the {@link java.util.Locale}
     * @param nf the number format object. It is defensively copied to ensure thread-safety
     * and immutability of this class.
     * @return An instance of RelativeDateTimeFormatter.
     * @stable ICU 54
     */
    public static RelativeDateTimeFormatter getInstance(Locale locale, NumberFormat nf) {
        return getInstance(ULocale.forLocale(locale), nf);
    }

    /**
     * Formats a relative date with a quantity such as "in 5 days" or
     * "3 months ago".
     *
     * This method returns a String. To get more information about the
     * formatting result, use formatToValue().
     *
     * @param quantity The numerical amount e.g 5. This value is formatted
     * according to this object's {@link NumberFormat} object.
     * @param direction NEXT means a future relative date; LAST means a past
     * relative date.
     * @param unit the unit e.g day? month? year?
     * @return the formatted string
     * @throws IllegalArgumentException if direction is something other than
     * NEXT or LAST.
     * @stable ICU 53
     */
    public String format(double quantity, Direction direction, RelativeUnit unit) {
        FormattedStringBuilder output = formatImpl(quantity, direction, unit);
        return adjustForContext(output.toString());
    }

    /**
     * Formats a relative date with a quantity such as "in 5 days" or
     * "3 months ago".
     *
     * This method returns a FormattedRelativeDateTime, which exposes more
     * information than the String returned by format().
     *
     * @param quantity The numerical amount e.g 5. This value is formatted
     * according to this object's {@link NumberFormat} object.
     * @param direction NEXT means a future relative date; LAST means a past
     * relative date.
     * @param unit the unit e.g day? month? year?
     * @return the formatted relative datetime
     * @throws IllegalArgumentException if direction is something other than
     * NEXT or LAST.
     * @stable ICU 64
     */
    public FormattedRelativeDateTime formatToValue(double quantity, Direction direction, RelativeUnit unit) {
        checkNoAdjustForContext();
        return new FormattedRelativeDateTime(formatImpl(quantity, direction, unit));
    }

    /** Implementation method for format and formatToValue with RelativeUnit */
    private FormattedStringBuilder formatImpl(double quantity, Direction direction, RelativeUnit unit) {
        if (direction != Direction.LAST && direction != Direction.NEXT) {
            throw new IllegalArgumentException("direction must be NEXT or LAST");
        }
        int pastFutureIndex = (direction == Direction.NEXT ? 1 : 0);

        FormattedStringBuilder output = new FormattedStringBuilder();
        String pluralKeyword;
        if (numberFormat instanceof DecimalFormat) {
            DecimalQuantity dq = new DecimalQuantity_DualStorageBCD(quantity);
            ((DecimalFormat) numberFormat).toNumberFormatter().formatImpl(dq, output);
            pluralKeyword = pluralRules.select(dq);
        } else {
            String result = numberFormat.format(quantity);
            output.append(result, null);
            pluralKeyword = pluralRules.select(quantity);
        }
        StandardPlural pluralForm = StandardPlural.orOtherFromString(pluralKeyword);

        String compiledPattern = getRelativeUnitPluralPattern(style, unit, pastFutureIndex, pluralForm);
        SimpleFormatterImpl.formatPrefixSuffix(compiledPattern, Field.LITERAL, 0, output.length(), output);
        return output;
    }

    /**
     * Format a combination of RelativeDateTimeUnit and numeric offset
     * using a numeric style, e.g. "1 week ago", "in 1 week",
     * "5 weeks ago", "in 5 weeks".
     *
     * This method returns a String. To get more information about the
     * formatting result, use formatNumericToValue().
     *
     * @param offset    The signed offset for the specified unit. This
     *                  will be formatted according to this object's
     *                  NumberFormat object.
     * @param unit      The unit to use when formatting the relative
     *                  date, e.g. RelativeDateTimeUnit.WEEK,
     *                  RelativeDateTimeUnit.FRIDAY.
     * @return          The formatted string (may be empty in case of error)
     * @stable ICU 57
     */
    public String formatNumeric(double offset, RelativeDateTimeUnit unit) {
        FormattedStringBuilder output = formatNumericImpl(offset, unit);
        return adjustForContext(output.toString());
    }

    /**
     * Format a combination of RelativeDateTimeUnit and numeric offset
     * using a numeric style, e.g. "1 week ago", "in 1 week",
     * "5 weeks ago", "in 5 weeks".
     *
     * This method returns a FormattedRelativeDateTime, which exposes more
     * information than the String returned by formatNumeric().
     *
     * @param offset    The signed offset for the specified unit. This
     *                  will be formatted according to this object's
     *                  NumberFormat object.
     * @param unit      The unit to use when formatting the relative
     *                  date, e.g. RelativeDateTimeUnit.WEEK,
     *                  RelativeDateTimeUnit.FRIDAY.
     * @return          The formatted string (may be empty in case of error)
     * @stable ICU 64
     */
    public FormattedRelativeDateTime formatNumericToValue(double offset, RelativeDateTimeUnit unit) {
        checkNoAdjustForContext();
        return new FormattedRelativeDateTime(formatNumericImpl(offset, unit));
    }

    /** Implementation method for formatNumeric and formatNumericToValue */
    private FormattedStringBuilder formatNumericImpl(double offset, RelativeDateTimeUnit unit) {
        // TODO:
        // The full implementation of this depends on CLDR data that is not yet available,
        // see: http://unicode.org/cldr/trac/ticket/9165 Add more relative field data.
        // In the meantime do a quick bring-up by calling the old format method. When the
        // new CLDR data is available, update the data storage accordingly, rewrite this
        // to use it directly, and rewrite the old format method to call this new one;
        // that is covered by http://bugs.icu-project.org/trac/ticket/12171.
        RelativeUnit relunit = RelativeUnit.SECONDS;
        switch (unit) {
            case YEAR:      relunit = RelativeUnit.YEARS; break;
            case QUARTER:   relunit = RelativeUnit.QUARTERS; break;
            case MONTH:     relunit = RelativeUnit.MONTHS; break;
            case WEEK:      relunit = RelativeUnit.WEEKS; break;
            case DAY:       relunit = RelativeUnit.DAYS; break;
            case HOUR:      relunit = RelativeUnit.HOURS; break;
            case MINUTE:    relunit = RelativeUnit.MINUTES; break;
            case SECOND:    break; // set above
            default: // SUNDAY..SATURDAY
                throw new UnsupportedOperationException("formatNumeric does not currently support RelativeUnit.SUNDAY..SATURDAY");
        }
        Direction direction = Direction.NEXT;
        if (Double.compare(offset,0.0) < 0) { // needed to handle -0.0
            direction = Direction.LAST;
            offset = -offset;
        }
        return formatImpl(offset, direction, relunit);
    }

    private int[] styleToDateFormatSymbolsWidth = {
                DateFormatSymbols.WIDE, DateFormatSymbols.SHORT, DateFormatSymbols.NARROW
    };

    /**
     * Formats a relative date without a quantity.
     *
     * This method returns a String. To get more information about the
     * formatting result, use formatToValue().
     *
     * @param direction NEXT, LAST, THIS, etc.
     * @param unit e.g SATURDAY, DAY, MONTH
     * @return the formatted string. If direction has a value that is documented as not being
     *  fully supported in every locale (for example NEXT_2 or LAST_2) then this function may
     *  return null to signal that no formatted string is available.
     * @throws IllegalArgumentException if the direction is incompatible with
     * unit this can occur with NOW which can only take PLAIN.
     * @stable ICU 53
     */
    public String format(Direction direction, AbsoluteUnit unit) {
        String result = formatAbsoluteImpl(direction, unit);
        return result != null ? adjustForContext(result) : null;
    }

    /**
     * Formats a relative date without a quantity.
     *
     * This method returns a FormattedRelativeDateTime, which exposes more
     * information than the String returned by format().
     *
     * @param direction NEXT, LAST, THIS, etc.
     * @param unit e.g SATURDAY, DAY, MONTH
     * @return the formatted string. If direction has a value that is documented as not being
     *  fully supported in every locale (for example NEXT_2 or LAST_2) then this function may
     *  return null to signal that no formatted string is available.
     * @throws IllegalArgumentException if the direction is incompatible with
     * unit this can occur with NOW which can only take PLAIN.
     * @stable ICU 64
     */
    public FormattedRelativeDateTime formatToValue(Direction direction, AbsoluteUnit unit) {
        checkNoAdjustForContext();
        String string = formatAbsoluteImpl(direction, unit);
        if (string == null) {
            return null;
        }
        FormattedStringBuilder nsb = new FormattedStringBuilder();
        nsb.append(string, Field.LITERAL);
        return new FormattedRelativeDateTime(nsb);
    }

    /** Implementation method for format and formatToValue with AbsoluteUnit */
    private String formatAbsoluteImpl(Direction direction, AbsoluteUnit unit) {
        if (unit == AbsoluteUnit.NOW && direction != Direction.PLAIN) {
            throw new IllegalArgumentException("NOW can only accept direction PLAIN.");
        }
        String result;
        // Get plain day of week names from DateFormatSymbols.
        if ((direction == Direction.PLAIN) &&  (AbsoluteUnit.SUNDAY.ordinal() <= unit.ordinal() &&
                unit.ordinal() <= AbsoluteUnit.SATURDAY.ordinal())) {
            // Convert from AbsoluteUnit days to Calendar class indexing.
            int dateSymbolsDayOrdinal = (unit.ordinal() - AbsoluteUnit.SUNDAY.ordinal()) + Calendar.SUNDAY;
            String[] dayNames =
                    dateFormatSymbols.getWeekdays(DateFormatSymbols.STANDALONE,
                    styleToDateFormatSymbolsWidth[style.ordinal()]);
            result = dayNames[dateSymbolsDayOrdinal];
        } else {
            // Not PLAIN, or not a weekday.
            result = getAbsoluteUnitString(style, unit, direction);
        }
        return result;
    }

    /**
     * Format a combination of RelativeDateTimeUnit and numeric offset
     * using a text style if possible, e.g. "last week", "this week",
     * "next week", "yesterday", "tomorrow". Falls back to numeric
     * style if no appropriate text term is available for the specified
     * offset in the object’s locale.
     *
     * This method returns a String. To get more information about the
     * formatting result, use formatToValue().
     *
     * @param offset    The signed offset for the specified field.
     * @param unit      The unit to use when formatting the relative
     *                  date, e.g. RelativeDateTimeUnit.WEEK,
     *                  RelativeDateTimeUnit.FRIDAY.
     * @return          The formatted string (may be empty in case of error)
     * @stable ICU 57
     */
    public String format(double offset, RelativeDateTimeUnit unit) {
        return adjustForContext(formatRelativeImpl(offset, unit).toString());
    }

    /**
     * Format a combination of RelativeDateTimeUnit and numeric offset
     * using a text style if possible, e.g. "last week", "this week",
     * "next week", "yesterday", "tomorrow". Falls back to numeric
     * style if no appropriate text term is available for the specified
     * offset in the object’s locale.
     *
     * This method returns a FormattedRelativeDateTime, which exposes more
     * information than the String returned by format().
     *
     * @param offset    The signed offset for the specified field.
     * @param unit      The unit to use when formatting the relative
     *                  date, e.g. RelativeDateTimeUnit.WEEK,
     *                  RelativeDateTimeUnit.FRIDAY.
     * @return          The formatted string (may be empty in case of error)
     * @stable ICU 64
     */
    public FormattedRelativeDateTime formatToValue(double offset, RelativeDateTimeUnit unit) {
        checkNoAdjustForContext();
        CharSequence cs = formatRelativeImpl(offset, unit);
        FormattedStringBuilder nsb;
        if (cs instanceof FormattedStringBuilder) {
            nsb = (FormattedStringBuilder) cs;
        } else {
            nsb = new FormattedStringBuilder();
            nsb.append(cs, Field.LITERAL);
        }
        return new FormattedRelativeDateTime(nsb);
    }


    /** Implementation method for format and formatToValue with RelativeDateTimeUnit. */
    private CharSequence formatRelativeImpl(double offset, RelativeDateTimeUnit unit) {
        // TODO:
        // The full implementation of this depends on CLDR data that is not yet available,
        // see: http://unicode.org/cldr/trac/ticket/9165 Add more relative field data.
        // In the meantime do a quick bring-up by calling the old format method. When the
        // new CLDR data is available, update the data storage accordingly, rewrite this
        // to use it directly, and rewrite the old format method to call this new one;
        // that is covered by http://bugs.icu-project.org/trac/ticket/12171.
        boolean useNumeric = true;
        Direction direction = Direction.THIS;
        if (offset > -2.1 && offset < 2.1) {
            // Allow a 1% epsilon, so offsets in -1.01..-0.99 map to LAST
            double offsetx100 = offset * 100.0;
            int intoffsetx100 = (offsetx100 < 0)? (int)(offsetx100-0.5) : (int)(offsetx100+0.5);
            switch (intoffsetx100) {
                case -200/*-2*/: direction = Direction.LAST_2; useNumeric = false; break;
                case -100/*-1*/: direction = Direction.LAST;   useNumeric = false; break;
                case    0/* 0*/: useNumeric = false; break; // direction = Direction.THIS was set above
                case  100/* 1*/: direction = Direction.NEXT;   useNumeric = false; break;
                case  200/* 2*/: direction = Direction.NEXT_2; useNumeric = false; break;
                default: break;
            }
        }
        AbsoluteUnit absunit = AbsoluteUnit.NOW;
        switch (unit) {
            case YEAR:      absunit = AbsoluteUnit.YEAR;    break;
            case QUARTER:   absunit = AbsoluteUnit.QUARTER; break;
            case MONTH:     absunit = AbsoluteUnit.MONTH;   break;
            case WEEK:      absunit = AbsoluteUnit.WEEK;    break;
            case DAY:       absunit = AbsoluteUnit.DAY;     break;
            case SUNDAY:    absunit = AbsoluteUnit.SUNDAY;  break;
            case MONDAY:    absunit = AbsoluteUnit.MONDAY;  break;
            case TUESDAY:   absunit = AbsoluteUnit.TUESDAY; break;
            case WEDNESDAY: absunit = AbsoluteUnit.WEDNESDAY; break;
            case THURSDAY:  absunit = AbsoluteUnit.THURSDAY; break;
            case FRIDAY:    absunit = AbsoluteUnit.FRIDAY;  break;
            case SATURDAY:  absunit = AbsoluteUnit.SATURDAY; break;
            case HOUR:      absunit = AbsoluteUnit.HOUR;    break;
            case MINUTE:    absunit = AbsoluteUnit.MINUTE;  break;
            case SECOND:
                if (direction == Direction.THIS) {
                    // absunit = AbsoluteUnit.NOW was set above
                    direction = Direction.PLAIN;
                    break;
                }
                // could just fall through here but that produces warnings
                useNumeric = true;
                break;
            default:
                useNumeric = true;
                break;
        }
        if (!useNumeric) {
            String result = formatAbsoluteImpl(direction, absunit);
            if (result != null && result.length() > 0) {
                return result;
            }
        }
        // otherwise fallback to formatNumeric
        return formatNumericImpl(offset, unit);
    }

    /**
     * Gets the string value from qualitativeUnitMap with fallback based on style.
     */
    private String getAbsoluteUnitString(Style style, AbsoluteUnit unit, Direction direction) {
        EnumMap<AbsoluteUnit, EnumMap<Direction, String>> unitMap;
        EnumMap<Direction, String> dirMap;

        do {
            unitMap = qualitativeUnitMap.get(style);
            if (unitMap != null) {
                dirMap = unitMap.get(unit);
                if (dirMap != null) {
                    String result = dirMap.get(direction);
                    if (result != null) {
                        return result;
                    }
                }

            }

            // Consider other styles from alias fallback.
            // Data loading guaranteed no endless loops.
        } while ((style = fallbackCache[style.ordinal()]) != null);
        return null;
    }

    /**
     * Combines a relative date string and a time string in this object's
     * locale. This is done with the same date-time separator used for the
     * default calendar in this locale.
     * @param relativeDateString the relative date e.g 'yesterday'
     * @param timeString the time e.g '3:45'
     * @return the date and time concatenated according to the default
     * calendar in this locale e.g 'yesterday, 3:45'
     * @stable ICU 53
     */
    public String combineDateAndTime(String relativeDateString, String timeString) {
        return SimpleFormatterImpl.formatCompiledPattern(
                combinedDateAndTime, timeString, relativeDateString);
    }

    /**
     * Returns a copy of the NumberFormat this object is using.
     * @return A copy of the NumberFormat.
     * @stable ICU 53
     */
    public NumberFormat getNumberFormat() {
        // This class is thread-safe, yet numberFormat is not. To ensure thread-safety of this
        // class we must guarantee that only one thread at a time uses our numberFormat.
        synchronized (numberFormat) {
            return (NumberFormat) numberFormat.clone();
        }
    }

    /**
     * Return capitalization context.
     * @return The capitalization context.
     * @stable ICU 54
     */
    public DisplayContext getCapitalizationContext() {
        return capitalizationContext;
    }

    /**
     * Return style
     * @return The formatting style.
     * @stable ICU 54
     */
    public Style getFormatStyle() {
        return style;
    }

    private String adjustForContext(String originalFormattedString) {
        if (breakIterator == null || originalFormattedString.length() == 0
                || !UCharacter.isLowerCase(UCharacter.codePointAt(originalFormattedString, 0))) {
            return originalFormattedString;
        }
        synchronized (breakIterator) {
            return UCharacter.toTitleCase(
                    locale,
                    originalFormattedString,
                    breakIterator,
                    UCharacter.TITLECASE_NO_LOWERCASE | UCharacter.TITLECASE_NO_BREAK_ADJUSTMENT);
        }
    }

    private void checkNoAdjustForContext() {
        if (breakIterator != null) {
            throw new UnsupportedOperationException("Capitalization context is not supported in formatV");
        }
    }

    private RelativeDateTimeFormatter(
            EnumMap<Style, EnumMap<AbsoluteUnit, EnumMap<Direction, String>>> qualitativeUnitMap,
            EnumMap<Style, EnumMap<RelativeUnit, String[][]>> patternMap,
            String combinedDateAndTime,
            PluralRules pluralRules,
            NumberFormat numberFormat,
            Style style,
            DisplayContext capitalizationContext,
            BreakIterator breakIterator,
            ULocale locale) {
        this.qualitativeUnitMap = qualitativeUnitMap;
        this.patternMap = patternMap;
        this.combinedDateAndTime = combinedDateAndTime;
        this.pluralRules = pluralRules;
        this.numberFormat = numberFormat;
        this.style = style;
        if (capitalizationContext.type() != DisplayContext.Type.CAPITALIZATION) {
            throw new IllegalArgumentException(capitalizationContext.toString());
        }
        this.capitalizationContext = capitalizationContext;
        this.breakIterator = breakIterator;
        this.locale = locale;
        this.dateFormatSymbols = new DateFormatSymbols(locale);
    }

    private String getRelativeUnitPluralPattern(
            Style style, RelativeUnit unit, int pastFutureIndex, StandardPlural pluralForm) {
        if (pluralForm != StandardPlural.OTHER) {
            String formatter = getRelativeUnitPattern(style, unit, pastFutureIndex, pluralForm);
            if (formatter != null) {
                return formatter;
            }
        }
        return getRelativeUnitPattern(style, unit, pastFutureIndex, StandardPlural.OTHER);
    }

    private String getRelativeUnitPattern(
            Style style, RelativeUnit unit, int pastFutureIndex, StandardPlural pluralForm) {
        int pluralIndex = pluralForm.ordinal();
        do {
            EnumMap<RelativeUnit, String[][]> unitMap = patternMap.get(style);
            if (unitMap != null) {
                String[][] spfCompiledPatterns = unitMap.get(unit);
                if (spfCompiledPatterns != null) {
                    if (spfCompiledPatterns[pastFutureIndex][pluralIndex] != null) {
                        return spfCompiledPatterns[pastFutureIndex][pluralIndex];
                    }
                }

            }

            // Consider other styles from alias fallback.
            // Data loading guaranteed no endless loops.
        } while ((style = fallbackCache[style.ordinal()]) != null);
        return null;
    }

    private final EnumMap<Style, EnumMap<AbsoluteUnit, EnumMap<Direction, String>>> qualitativeUnitMap;
    private final EnumMap<Style, EnumMap<RelativeUnit, String[][]>> patternMap;

    private final String combinedDateAndTime;  // compiled SimpleFormatter pattern
    private final PluralRules pluralRules;
    private final NumberFormat numberFormat;

    private final Style style;
    private final DisplayContext capitalizationContext;
    private final BreakIterator breakIterator;
    private final ULocale locale;

    private final DateFormatSymbols dateFormatSymbols;

    private static final Style fallbackCache[] = new Style[Style.INDEX_COUNT];

    private static class RelativeDateTimeFormatterData {
        public RelativeDateTimeFormatterData(
                EnumMap<Style, EnumMap<AbsoluteUnit, EnumMap<Direction, String>>> qualitativeUnitMap,
                EnumMap<Style, EnumMap<RelativeUnit, String[][]>> relUnitPatternMap,
                String dateTimePattern) {
            this.qualitativeUnitMap = qualitativeUnitMap;
            this.relUnitPatternMap = relUnitPatternMap;

            this.dateTimePattern = dateTimePattern;
        }

        public final EnumMap<Style, EnumMap<AbsoluteUnit, EnumMap<Direction, String>>> qualitativeUnitMap;
        EnumMap<Style, EnumMap<RelativeUnit, String[][]>> relUnitPatternMap;
        public final String dateTimePattern;  // Example: "{1}, {0}"
    }

    private static class Cache {
        private final CacheBase<String, RelativeDateTimeFormatterData, ULocale> cache =
            new SoftCache<String, RelativeDateTimeFormatterData, ULocale>() {
                @Override
                protected RelativeDateTimeFormatterData createInstance(String key, ULocale locale) {
                    return new Loader(locale).load();
                }
            };

        public RelativeDateTimeFormatterData get(ULocale locale) {
            String key = locale.toString();
            return cache.getInstance(key, locale);
        }
    }

    private static Direction keyToDirection(UResource.Key key) {
        if (key.contentEquals("-2")) {
            return Direction.LAST_2;
        }
        if (key.contentEquals("-1")) {
            return Direction.LAST;
        }
        if (key.contentEquals("0")) {
            return Direction.THIS;
        }
        if (key.contentEquals("1")) {
            return Direction.NEXT;
        }
        if (key.contentEquals("2")) {
            return Direction.NEXT_2;
        }
        return null;
    }

    /**
     * Sink for enumerating all of the relative data time formatter names.
     *
     * More specific bundles (en_GB) are enumerated before their parents (en_001, en, root):
     * Only store a value if it is still missing, that is, it has not been overridden.
     */
    private static final class RelDateTimeDataSink extends UResource.Sink {

        // For white list of units to handle in RelativeDateTimeFormatter.
        private enum DateTimeUnit {
            SECOND(RelativeUnit.SECONDS, null),
            MINUTE(RelativeUnit.MINUTES, AbsoluteUnit.MINUTE),
            HOUR(RelativeUnit.HOURS, AbsoluteUnit.HOUR),
            DAY(RelativeUnit.DAYS, AbsoluteUnit.DAY),
            WEEK(RelativeUnit.WEEKS, AbsoluteUnit.WEEK),
            MONTH(RelativeUnit.MONTHS, AbsoluteUnit.MONTH),
            QUARTER(RelativeUnit.QUARTERS, AbsoluteUnit.QUARTER),
            YEAR(RelativeUnit.YEARS, AbsoluteUnit.YEAR),
            SUNDAY(null, AbsoluteUnit.SUNDAY),
            MONDAY(null, AbsoluteUnit.MONDAY),
            TUESDAY(null, AbsoluteUnit.TUESDAY),
            WEDNESDAY(null, AbsoluteUnit.WEDNESDAY),
            THURSDAY(null, AbsoluteUnit.THURSDAY),
            FRIDAY(null, AbsoluteUnit.FRIDAY),
            SATURDAY(null, AbsoluteUnit.SATURDAY);

            RelativeUnit relUnit;
            AbsoluteUnit absUnit;

            DateTimeUnit(RelativeUnit relUnit, AbsoluteUnit absUnit) {
                this.relUnit = relUnit;
                this.absUnit = absUnit;
            }

            private static final DateTimeUnit orNullFromString(CharSequence keyword) {
                // Quick check from string to enum.
                switch (keyword.length()) {
                case 3:
                    if ("day".contentEquals(keyword)) {
                        return DAY;
                    } else if ("sun".contentEquals(keyword)) {
                        return SUNDAY;
                    } else if ("mon".contentEquals(keyword)) {
                        return MONDAY;
                    } else if ("tue".contentEquals(keyword)) {
                        return TUESDAY;
                    } else if ("wed".contentEquals(keyword)) {
                        return WEDNESDAY;
                    } else if ("thu".contentEquals(keyword)) {
                        return THURSDAY;
                    }    else if ("fri".contentEquals(keyword)) {
                        return FRIDAY;
                    } else if ("sat".contentEquals(keyword)) {
                        return SATURDAY;
                    }
                    break;
                case 4:
                    if ("hour".contentEquals(keyword)) {
                        return HOUR;
                    } else if ("week".contentEquals(keyword)) {
                        return WEEK;
                    } else if ("year".contentEquals(keyword)) {
                        return YEAR;
                    }
                    break;
                case 5:
                    if ("month".contentEquals(keyword)) {
                        return MONTH;
                    }
                    break;
                case 6:
                    if ("minute".contentEquals(keyword)) {
                        return MINUTE;
                    }else if ("second".contentEquals(keyword)) {
                        return SECOND;
                    }
                    break;
                case 7:
                    if ("quarter".contentEquals(keyword)) {
                        return QUARTER;  // TODO: Check @provisional
                    }
                    break;
                default:
                    break;
                }
                return null;
            }
        }

        EnumMap<Style, EnumMap<AbsoluteUnit, EnumMap<Direction, String>>> qualitativeUnitMap =
                new EnumMap<>(Style.class);
        EnumMap<Style, EnumMap<RelativeUnit, String[][]>> styleRelUnitPatterns =
                new EnumMap<>(Style.class);

        StringBuilder sb = new StringBuilder();

        // Values keep between levels of parsing the CLDR data.
        int pastFutureIndex;
        Style style;                        // {LONG, SHORT, NARROW} Derived from unit key string.
        DateTimeUnit unit;                  // From the unit key string, with the style (e.g., "-short") separated out.

        private Style styleFromKey(UResource.Key key) {
            if (key.endsWith("-short")) {
                return Style.SHORT;
            } else if (key.endsWith("-narrow")) {
                return Style.NARROW;
            } else {
                return Style.LONG;
            }
        }

        private Style styleFromAlias(UResource.Value value) {
                String s = value.getAliasString();
                if (s.endsWith("-short")) {
                    return Style.SHORT;
                } else if (s.endsWith("-narrow")) {
                    return Style.NARROW;
                } else {
                    return Style.LONG;
                }
        }

        private static int styleSuffixLength(Style style) {
            switch (style) {
            case SHORT: return 6;
            case NARROW: return 7;
            default: return 0;
            }
        }

        public void consumeTableRelative(UResource.Key key, UResource.Value value) {
            UResource.Table unitTypesTable = value.getTable();
            for (int i = 0; unitTypesTable.getKeyAndValue(i, key, value); i++) {
                if (value.getType() == ICUResourceBundle.STRING) {
                    String valueString = value.getString();

                    EnumMap<AbsoluteUnit, EnumMap<Direction, String>> absMap = qualitativeUnitMap.get(style);

                    if (unit.relUnit == RelativeUnit.SECONDS) {
                        if (key.contentEquals("0")) {
                            // Handle Zero seconds for "now".
                            EnumMap<Direction, String> unitStrings = absMap.get(AbsoluteUnit.NOW);
                            if (unitStrings == null) {
                                unitStrings = new EnumMap<>(Direction.class);
                                absMap.put(AbsoluteUnit.NOW, unitStrings);
                            }
                            if (unitStrings.get(Direction.PLAIN) == null) {
                                unitStrings.put(Direction.PLAIN, valueString);
                            }
                            continue;
                        }
                    }
                    Direction keyDirection = keyToDirection(key);
                    if (keyDirection == null) {
                        continue;
                    }
                    AbsoluteUnit absUnit = unit.absUnit;
                    if (absUnit == null) {
                        continue;
                    }

                    if (absMap == null) {
                        absMap = new EnumMap<>(AbsoluteUnit.class);
                        qualitativeUnitMap.put(style, absMap);
                    }
                    EnumMap<Direction, String> dirMap = absMap.get(absUnit);
                    if (dirMap == null) {
                        dirMap = new EnumMap<>(Direction.class);
                        absMap.put(absUnit, dirMap);
                    }
                    if (dirMap.get(keyDirection) == null) {
                        // Do not override values already entered.
                        dirMap.put(keyDirection, value.getString());
                    }
                }
            }
        }

        // Record past or future and
        public void consumeTableRelativeTime(UResource.Key key, UResource.Value value) {
            if (unit.relUnit == null) {
                return;
            }
            UResource.Table unitTypesTable = value.getTable();
            for (int i = 0; unitTypesTable.getKeyAndValue(i, key, value); i++) {
                if (key.contentEquals("past")) {
                    pastFutureIndex = 0;
                } else if (key.contentEquals("future")) {
                    pastFutureIndex = 1;
                } else {
                    continue;
                }
                // Get the details of the relative time.
                consumeTimeDetail(key, value);
            }
        }

        public void consumeTimeDetail(UResource.Key key, UResource.Value value) {
            UResource.Table unitTypesTable = value.getTable();

            EnumMap<RelativeUnit, String[][]> unitPatterns  = styleRelUnitPatterns.get(style);
            if (unitPatterns == null) {
                unitPatterns = new EnumMap<>(RelativeUnit.class);
                styleRelUnitPatterns.put(style, unitPatterns);
            }
            String[][] patterns = unitPatterns.get(unit.relUnit);
            if (patterns == null) {
                patterns = new String[2][StandardPlural.COUNT];
                unitPatterns.put(unit.relUnit, patterns);
            }

            // Stuff the pattern for the correct plural index with a simple formatter.
            for (int i = 0; unitTypesTable.getKeyAndValue(i, key, value); i++) {
                if (value.getType() == ICUResourceBundle.STRING) {
                    int pluralIndex = StandardPlural.indexFromString(key.toString());
                    if (patterns[pastFutureIndex][pluralIndex] == null) {
                        patterns[pastFutureIndex][pluralIndex] =
                                SimpleFormatterImpl.compileToStringMinMaxArguments(
                                        value.getString(), sb, 0, 1);
                    }
                }
            }
        }

        private void handlePlainDirection(UResource.Key key, UResource.Value value) {
            AbsoluteUnit absUnit = unit.absUnit;
            if (absUnit == null) {
                return;  // Not interesting.
            }
            EnumMap<AbsoluteUnit, EnumMap<Direction, String>> unitMap =
                    qualitativeUnitMap.get(style);
            if (unitMap == null) {
                unitMap = new EnumMap<>(AbsoluteUnit.class);
                qualitativeUnitMap.put(style, unitMap);
            }
            EnumMap<Direction,String> dirMap = unitMap.get(absUnit);
            if (dirMap == null) {
                dirMap = new EnumMap<>(Direction.class);
                unitMap.put(absUnit, dirMap);
            }
            if (dirMap.get(Direction.PLAIN) == null) {
                dirMap.put(Direction.PLAIN, value.toString());
            }
        }

        // Handle at the Unit level,
        public void consumeTimeUnit(UResource.Key key, UResource.Value value) {
            UResource.Table unitTypesTable = value.getTable();
            for (int i = 0; unitTypesTable.getKeyAndValue(i, key, value); i++) {
                if (key.contentEquals("dn") && value.getType() == ICUResourceBundle.STRING) {
                    handlePlainDirection(key, value);
                }
                if (value.getType() == ICUResourceBundle.TABLE) {
                    if (key.contentEquals("relative")) {
                        consumeTableRelative(key, value);
                    } else if (key.contentEquals("relativeTime")) {
                        consumeTableRelativeTime(key, value);
                    }
                }
            }
        }

        private void handleAlias(UResource.Key key, UResource.Value value, boolean noFallback) {
            Style sourceStyle = styleFromKey(key);
            int limit = key.length() - styleSuffixLength(sourceStyle);
            DateTimeUnit unit = DateTimeUnit.orNullFromString(key.substring(0, limit));
            if (unit != null) {
                // Record the fallback chain for the values.
                // At formatting time, limit to 2 levels of fallback.
                Style targetStyle = styleFromAlias(value);
                if (sourceStyle == targetStyle) {
                    throw new ICUException("Invalid style fallback from " + sourceStyle + " to itself");
                }

                // Check for inconsistent fallbacks.
                if (fallbackCache[sourceStyle.ordinal()] == null) {
                    fallbackCache[sourceStyle.ordinal()] = targetStyle;
                } else if (fallbackCache[sourceStyle.ordinal()] != targetStyle) {
                    throw new ICUException(
                            "Inconsistent style fallback for style " + sourceStyle + " to " + targetStyle);
                }
                return;
            }
        }

        @Override
        public void put(UResource.Key key, UResource.Value value, boolean noFallback) {
            // Main entry point to sink
            if (value.getType() == ICUResourceBundle.ALIAS) {
                return;
            }

            UResource.Table table = value.getTable();
            // Process each key / value in this table.
            for (int i = 0; table.getKeyAndValue(i, key, value); i++) {
                if (value.getType() == ICUResourceBundle.ALIAS) {
                    handleAlias(key, value, noFallback);
                } else {
                    // Remember style and unit for deeper levels.
                    style = styleFromKey(key);
                    int limit = key.length() - styleSuffixLength(style);
                    unit = DateTimeUnit.orNullFromString(key.substring(0, limit));
                    if (unit != null) {
                        // Process only if unitString is in the white list.
                        consumeTimeUnit(key, value);
                    }
                }
            }
        }

        RelDateTimeDataSink() {
        }
    }

    private static class Loader {
        private final ULocale ulocale;

        public Loader(ULocale ulocale) {
            this.ulocale = ulocale;
        }

        private String getDateTimePattern(ICUResourceBundle r) {
            String calType = r.getStringWithFallback("calendar/default");
            if (calType == null || calType.equals("")) {
                calType = "gregorian";
            }
            String resourcePath = "calendar/" + calType + "/DateTimePatterns";
            ICUResourceBundle patternsRb = r.findWithFallback(resourcePath);
            if (patternsRb == null && calType.equals("gregorian")) {
                // Try with gregorian.
                patternsRb = r.findWithFallback("calendar/gregorian/DateTimePatterns");
            }
            if (patternsRb == null || patternsRb.getSize() < 9) {
                // Undefined or too few elements.
                return "{1} {0}";
            } else {
                int elementType = patternsRb.get(8).getType();
                if (elementType == UResourceBundle.ARRAY) {
                    return patternsRb.get(8).getString(0);
                } else {
                    return patternsRb.getString(8);
                }
            }
        }

        public RelativeDateTimeFormatterData load() {
            // Sink for traversing data.
            RelDateTimeDataSink sink = new RelDateTimeDataSink();

            ICUResourceBundle r = (ICUResourceBundle)UResourceBundle.
                    getBundleInstance(ICUData.ICU_BASE_NAME, ulocale);
            r.getAllItemsWithFallback("fields", sink);

            // Check fallbacks array for loops or too many levels.
            for (Style testStyle : Style.values()) {
                Style newStyle1 = fallbackCache[testStyle.ordinal()];
                // Data loading guaranteed newStyle1 != testStyle.
                if (newStyle1 != null) {
                    Style newStyle2 = fallbackCache[newStyle1.ordinal()];
                    if (newStyle2 != null) {
                        // No fallback should take more than 2 steps.
                        if (fallbackCache[newStyle2.ordinal()] != null) {
                            throw new IllegalStateException("Style fallback too deep");
                        }
                    }
                }
            }

            return new RelativeDateTimeFormatterData(
                    sink.qualitativeUnitMap, sink.styleRelUnitPatterns,
                    getDateTimePattern(r));
        }
    }

    private static final Cache cache = new Cache();
}
