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

import java.io.ObjectStreamException;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.MissingResourceException;
import java.util.Set;
import java.util.TreeMap;

import com.ibm.icu.impl.ICUData;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.UResource;
import com.ibm.icu.number.LocalizedNumberFormatter;
import com.ibm.icu.util.TimeUnit;
import com.ibm.icu.util.TimeUnitAmount;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.ULocale.Category;
import com.ibm.icu.util.UResourceBundle;


/**
 * Format or parse a TimeUnitAmount, using plural rules for the units where available.
 *
 * <P>
 * Code Sample:
 * <pre>
 *   // create a time unit instance.
 *   // only SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, and YEAR are supported
 *   TimeUnit timeUnit = TimeUnit.SECOND;
 *   // create time unit amount instance - a combination of Number and time unit
 *   TimeUnitAmount source = new TimeUnitAmount(2, timeUnit);
 *   // create time unit format instance
 *   TimeUnitFormat format = new TimeUnitFormat();
 *   // set the locale of time unit format
 *   format.setLocale(new ULocale("en"));
 *   // format a time unit amount
 *   String formatted = format.format(source);
 *   System.out.println(formatted);
 *   try {
 *       // parse a string into time unit amount
 *       TimeUnitAmount result = (TimeUnitAmount) format.parseObject(formatted);
 *       // result should equal to source
 *   } catch (ParseException e) {
 *   }
 * </pre>
 *
 * <P>
 * @see TimeUnitAmount
 * @see MeasureFormat
 * @author markdavis
 * @deprecated ICU 53 use {@link MeasureFormat} instead.
 */
@Deprecated
public class TimeUnitFormat extends MeasureFormat {

    /**
     * Constant for full name style format.
     * For example, the full name for "hour" in English is "hour" or "hours".
     * @deprecated ICU 53 see {@link MeasureFormat.FormatWidth}
     */
    @Deprecated
    public static final int FULL_NAME = 0;
    /**
     * Constant for abbreviated name style format.
     * For example, the abbreviated name for "hour" in English is "hr" or "hrs".
     * @deprecated ICU 53 see {@link MeasureFormat.FormatWidth}
     */
    @Deprecated
    public static final int ABBREVIATED_NAME = 1;

    private static final int TOTAL_STYLES = 2;

    private static final long serialVersionUID = -3707773153184971529L;

    // Unlike MeasureFormat, this class is mutable and allows a new NumberFormat to be set after
    // initialization. Keep a second copy of NumberFormat and use it instead of the one from the parent.
    private NumberFormat format;
    private ULocale locale;
    private int style;

    private transient Map<TimeUnit, Map<String, Object[]>> timeUnitToCountToPatterns;
    private transient PluralRules pluralRules;
    private transient boolean isReady;

    private static final String DEFAULT_PATTERN_FOR_SECOND = "{0} s";
    private static final String DEFAULT_PATTERN_FOR_MINUTE = "{0} min";
    private static final String DEFAULT_PATTERN_FOR_HOUR = "{0} h";
    private static final String DEFAULT_PATTERN_FOR_DAY = "{0} d";
    private static final String DEFAULT_PATTERN_FOR_WEEK = "{0} w";
    private static final String DEFAULT_PATTERN_FOR_MONTH = "{0} m";
    private static final String DEFAULT_PATTERN_FOR_YEAR = "{0} y";

    /**
     * Create empty format using full name style, for example, "hours".
     * Use setLocale and/or setFormat to modify.
     * @deprecated ICU 53 use {@link MeasureFormat} instead.
     */
    @Deprecated
    public TimeUnitFormat() {
        this(ULocale.getDefault(), FULL_NAME);
    }

    /**
     * Create TimeUnitFormat given a ULocale, and using full name style.
     * @param locale   locale of this time unit formatter.
     * @deprecated ICU 53 use {@link MeasureFormat} instead.
     */
    @Deprecated
    public TimeUnitFormat(ULocale locale) {
        this(locale, FULL_NAME);
    }

    /**
     * Create TimeUnitFormat given a Locale, and using full name style.
     * @param locale   locale of this time unit formatter.
     * @deprecated ICU 53 use {@link MeasureFormat} instead.
     */
    @Deprecated
    public TimeUnitFormat(Locale locale) {
        this(locale, FULL_NAME);
    }

    /**
     * Create TimeUnitFormat given a ULocale and a formatting style.
     * @param locale   locale of this time unit formatter.
     * @param style    format style, either FULL_NAME or ABBREVIATED_NAME style.
     * @throws IllegalArgumentException if the style is not FULL_NAME or
     *                                  ABBREVIATED_NAME style.
     * @deprecated ICU 53 use {@link MeasureFormat} instead.
     */
    @Deprecated
    public TimeUnitFormat(ULocale locale, int style) {
        super(locale, style == FULL_NAME ? FormatWidth.WIDE : FormatWidth.SHORT);
        format = super.getNumberFormatInternal();
        if (style < FULL_NAME || style >= TOTAL_STYLES) {
            throw new IllegalArgumentException("style should be either FULL_NAME or ABBREVIATED_NAME style");
        }
        this.style = style;
        isReady = false;
    }

    private TimeUnitFormat(ULocale locale, int style, NumberFormat numberFormat) {
        this(locale, style);
        if (numberFormat != null) {
            setNumberFormat((NumberFormat) numberFormat.clone());
        }
    }

    /**
     * Create TimeUnitFormat given a Locale and a formatting style.
     * @deprecated ICU 53 use {@link MeasureFormat} instead.
     */
    @Deprecated
    public TimeUnitFormat(Locale locale, int style) {
        this(ULocale.forLocale(locale),  style);
    }

    /**
     * Set the locale used for formatting or parsing.
     * @param locale   locale of this time unit formatter.
     * @return this, for chaining.
     * @deprecated ICU 53 see {@link MeasureFormat}.
     */
    @Deprecated
    public TimeUnitFormat setLocale(ULocale locale) {
        setLocale(locale, locale);
        clearCache();
        return this;
    }

    /**
     * Set the locale used for formatting or parsing.
     * @param locale   locale of this time unit formatter.
     * @return this, for chaining.
     * @deprecated ICU 53 see {@link MeasureFormat}.
     */
    @Deprecated
    public TimeUnitFormat setLocale(Locale locale) {
        return setLocale(ULocale.forLocale(locale));
    }

    /**
     * Set the format used for formatting or parsing. Passing null is equivalent to passing
     * {@link NumberFormat#getNumberInstance(ULocale)}.
     * @param format   the number formatter.
     * @return this, for chaining.
     * @deprecated ICU 53 see {@link MeasureFormat}.
     */
    @Deprecated
    public TimeUnitFormat setNumberFormat(NumberFormat format) {
        if (format == this.format) {
            return this;
        }
        if (format == null) {
            if (locale == null) {
                isReady = false;
            } else {
                this.format = NumberFormat.getNumberInstance(locale);
            }
        } else {
            this.format = format;
        }
        clearCache();
        return this;
    }

    /**
     * {@inheritDoc}
     * @deprecated ICU 53 see {@link MeasureFormat}.
     */
    @Override
    @Deprecated
    public NumberFormat getNumberFormat() {
        return (NumberFormat) format.clone();
    }

    @Override
    NumberFormat getNumberFormatInternal() {
        return format;
    }

    @Override
    LocalizedNumberFormatter getNumberFormatter() {
        return ((DecimalFormat)format).toNumberFormatter();
    }

    /**
     * Parse a TimeUnitAmount.
     * @see java.text.Format#parseObject(java.lang.String, java.text.ParsePosition)
     * @deprecated ICU 53 see {@link MeasureFormat}.
     */
    @Deprecated
    @Override
    public TimeUnitAmount parseObject(String source, ParsePosition pos) {
        if (!isReady) {
            setup();
        }
        Number resultNumber = null;
        TimeUnit resultTimeUnit = null;
        int oldPos = pos.getIndex();
        int newPos = -1;
        int longestParseDistance = 0;
        String countOfLongestMatch = null;
        // we don't worry too much about speed on parsing, but this can be optimized later if needed.
        // Parse by iterating through all available patterns
        // and looking for the longest match.
        for (TimeUnit timeUnit : timeUnitToCountToPatterns.keySet()) {
            Map<String, Object[]> countToPattern = timeUnitToCountToPatterns.get(timeUnit);
            for (Entry<String, Object[]> patternEntry : countToPattern.entrySet()) {
                String count = patternEntry.getKey();
                for (int styl = FULL_NAME; styl < TOTAL_STYLES; ++styl) {
                    MessageFormat pattern = (MessageFormat) (patternEntry.getValue())[styl];
                    pos.setErrorIndex(-1);
                    pos.setIndex(oldPos);
                    // see if we can parse
                    Object parsed = pattern.parseObject(source, pos);
                    if (pos.getErrorIndex() != -1 || pos.getIndex() == oldPos) {
                        // nothing parsed
                        continue;
                    }
                    Number temp = null;
                    if (((Object[]) parsed).length != 0) {
                        // pattern with Number as beginning,
                        // such as "{0} d".
                        // check to make sure that the timeUnit is consistent
                        Object tempObj = ((Object[]) parsed)[0];
                        if (tempObj instanceof Number) {
                            temp = (Number) tempObj;
                        } else {
                            // Since we now format the number ourselves, parseObject will likely give us back a String
                            // for
                            // the number. When this happens we must parse the formatted number ourselves.
                            try {
                                temp = format.parse(tempObj.toString());
                            } catch (ParseException e) {
                                continue;
                            }
                        }
                    }
                    int parseDistance = pos.getIndex() - oldPos;
                    if (parseDistance > longestParseDistance) {
                        resultNumber = temp;
                        resultTimeUnit = timeUnit;
                        newPos = pos.getIndex();
                        longestParseDistance = parseDistance;
                        countOfLongestMatch = count;
                    }
                }
            }
        }
        /*
         * After find the longest match, parse the number. Result number could be null for the pattern without number
         * pattern. such as unit pattern in Arabic. When result number is null, use plural rule to set the number.
         */
        if (resultNumber == null && longestParseDistance != 0) {
            // set the number using plurrual count
            if (countOfLongestMatch.equals("zero")) {
                resultNumber = Integer.valueOf(0);
            } else if (countOfLongestMatch.equals("one")) {
                resultNumber = Integer.valueOf(1);
            } else if (countOfLongestMatch.equals("two")) {
                resultNumber = Integer.valueOf(2);
            } else {
                // should not happen.
                // TODO: how to handle?
                resultNumber = Integer.valueOf(3);
            }
        }
        if (longestParseDistance == 0) {
            pos.setIndex(oldPos);
            pos.setErrorIndex(0);
            return null;
        } else {
            pos.setIndex(newPos);
            pos.setErrorIndex(-1);
            return new TimeUnitAmount(resultNumber, resultTimeUnit);
        }
    }

    private void setup() {
        if (locale == null) {
            if (format != null) {
                locale = format.getLocale(null);
            } else {
                locale = ULocale.getDefault(Category.FORMAT);
            }
            // Needed for getLocale(ULocale.VALID_LOCALE)
            setLocale(locale, locale);
        }
        if (format == null) {
            format = NumberFormat.getNumberInstance(locale);
        }
        pluralRules = PluralRules.forLocale(locale);
        timeUnitToCountToPatterns = new HashMap<>();
        Set<String> pluralKeywords = pluralRules.getKeywords();
        setup("units/duration", timeUnitToCountToPatterns, FULL_NAME, pluralKeywords);
        setup("unitsShort/duration", timeUnitToCountToPatterns, ABBREVIATED_NAME, pluralKeywords);
        isReady = true;
    }

    private static final class TimeUnitFormatSetupSink extends UResource.Sink {
        Map<TimeUnit, Map<String, Object[]>> timeUnitToCountToPatterns;
        int style;
        Set<String> pluralKeywords;
        ULocale locale;
        boolean beenHere;

        TimeUnitFormatSetupSink(Map<TimeUnit, Map<String, Object[]>> timeUnitToCountToPatterns,
                int style, Set<String> pluralKeywords, ULocale locale) {
            this.timeUnitToCountToPatterns = timeUnitToCountToPatterns;
            this.style = style;
            this.pluralKeywords = pluralKeywords;
            this.locale = locale;
            this.beenHere = false;
        }

        @Override
        public void put(UResource.Key key, UResource.Value value, boolean noFallback) {
            // Skip all put() calls except the first one -- discard all fallback data.
            if (beenHere) {
                return;
            } else {
                beenHere = true;
            }

            UResource.Table units = value.getTable();
            for (int i = 0; units.getKeyAndValue(i, key, value); ++i) {
                String timeUnitName = key.toString();
                TimeUnit timeUnit = null;

                if (timeUnitName.equals("year")) {
                    timeUnit = TimeUnit.YEAR;
                } else if (timeUnitName.equals("month")) {
                    timeUnit = TimeUnit.MONTH;
                } else if (timeUnitName.equals("day")) {
                    timeUnit = TimeUnit.DAY;
                } else if (timeUnitName.equals("hour")) {
                    timeUnit = TimeUnit.HOUR;
                } else if (timeUnitName.equals("minute")) {
                    timeUnit = TimeUnit.MINUTE;
                } else if (timeUnitName.equals("second")) {
                    timeUnit = TimeUnit.SECOND;
                } else if (timeUnitName.equals("week")) {
                    timeUnit = TimeUnit.WEEK;
                } else {
                    continue;
                }

                Map<String, Object[]> countToPatterns = timeUnitToCountToPatterns.get(timeUnit);
                if (countToPatterns == null) {
                    countToPatterns = new TreeMap<>();
                    timeUnitToCountToPatterns.put(timeUnit, countToPatterns);
                }

                UResource.Table countsToPatternTable = value.getTable();
                for (int j = 0; countsToPatternTable.getKeyAndValue(j, key, value); ++j) {
                    String pluralCount = key.toString();
                    if (!pluralKeywords.contains(pluralCount))
                        continue;
                    // save both full name and abbreviated name in one table
                    // is good space-wise, but it degrades performance,
                    // since it needs to check whether the needed space
                    // is already allocated or not.
                    Object[] pair = countToPatterns.get(pluralCount);
                    if (pair == null) {
                        pair = new Object[2];
                        countToPatterns.put(pluralCount, pair);
                    }
                    if (pair[style] == null) {
                        String pattern = value.getString();
                        final MessageFormat messageFormat = new MessageFormat(pattern, locale);
                        pair[style] = messageFormat;
                    }
                }
            }
        }
    }

    private void setup(String resourceKey, Map<TimeUnit, Map<String, Object[]>> timeUnitToCountToPatterns, int style,
            Set<String> pluralKeywords) {
        // fill timeUnitToCountToPatterns from resource file
        try {

            ICUResourceBundle resource = (ICUResourceBundle) UResourceBundle.getBundleInstance(
                    ICUData.ICU_UNIT_BASE_NAME, locale);

            TimeUnitFormatSetupSink sink = new TimeUnitFormatSetupSink(
                    timeUnitToCountToPatterns, style, pluralKeywords, locale);
            resource.getAllItemsWithFallback(resourceKey, sink);
        } catch (MissingResourceException e) {
        }
        // there should be patterns for each plural rule in each time unit.
        // For each time unit,
        // for each plural rule, following is unit pattern fall-back rule:
        // ( for example: "one" hour )
        // look for its unit pattern in its locale tree.
        // if pattern is not found in its own locale, such as de_DE,
        // look for the pattern in its parent, such as de,
        // keep looking till found or till root.
        // if the pattern is not found in root either,
        // fallback to plural count "other",
        // look for the pattern of "other" in the locale tree:
        // "de_DE" to "de" to "root".
        // If not found, fall back to value of
        // static variable DEFAULT_PATTERN_FOR_xxx, such as "{0} h".
        //
        // Following is consistency check to create pattern for each
        // plural rule in each time unit using above fall-back rule.
        //
        final TimeUnit[] timeUnits = TimeUnit.values();
        Set<String> keywords = pluralRules.getKeywords();
        for (int i = 0; i < timeUnits.length; ++i) {
            // for each time unit,
            // get all the patterns for each plural rule in this locale.
            final TimeUnit timeUnit = timeUnits[i];
            Map<String, Object[]> countToPatterns = timeUnitToCountToPatterns.get(timeUnit);
            if (countToPatterns == null) {
                countToPatterns = new TreeMap<>();
                timeUnitToCountToPatterns.put(timeUnit, countToPatterns);
            }
            for (String pluralCount : keywords) {
                if (countToPatterns.get(pluralCount) == null || countToPatterns.get(pluralCount)[style] == null) {
                    // look through parents
                    searchInTree(resourceKey, style, timeUnit, pluralCount, pluralCount, countToPatterns);
                }
            }
        }
    }

    // srcPluralCount is the original plural count on which the pattern is
    // searched for.
    // searchPluralCount is the fallback plural count.
    // For example, to search for pattern for ""one" hour",
    // "one" is the srcPluralCount,
    // if the pattern is not found even in root, fallback to
    // using patterns of plural count "other",
    // then, "other" is the searchPluralCount.
    private void searchInTree(String resourceKey, int styl, TimeUnit timeUnit, String srcPluralCount,
            String searchPluralCount, Map<String, Object[]> countToPatterns) {
        ULocale parentLocale = locale;
        String srcTimeUnitName = timeUnit.toString();
        while (parentLocale != null) {
            try {
                // look for pattern for srcPluralCount in locale tree
                ICUResourceBundle unitsRes = (ICUResourceBundle) UResourceBundle.getBundleInstance(
                        ICUData.ICU_UNIT_BASE_NAME, parentLocale);
                unitsRes = unitsRes.getWithFallback(resourceKey);
                ICUResourceBundle oneUnitRes = unitsRes.getWithFallback(srcTimeUnitName);
                String pattern = oneUnitRes.getStringWithFallback(searchPluralCount);
                final MessageFormat messageFormat = new MessageFormat(pattern, locale);
                Object[] pair = countToPatterns.get(srcPluralCount);
                if (pair == null) {
                    pair = new Object[2];
                    countToPatterns.put(srcPluralCount, pair);
                }
                pair[styl] = messageFormat;
                return;
            } catch (MissingResourceException e) {
            }
            parentLocale = parentLocale.getFallback();
        }
        // if no unitsShort resource was found even after fallback to root locale
        // then search the units resource fallback from the current level to root
        if (parentLocale == null && resourceKey.equals("unitsShort")) {
            searchInTree("units", styl, timeUnit, srcPluralCount, searchPluralCount, countToPatterns);
            if (countToPatterns.get(srcPluralCount) != null
                    && countToPatterns.get(srcPluralCount)[styl] != null) {
                return;
            }
        }
        // if not found the pattern for this plural count at all,
        // fall-back to plural count "other"
        if (searchPluralCount.equals("other")) {
            // set default fall back the same as the resource in root
            MessageFormat messageFormat = null;
            if (timeUnit == TimeUnit.SECOND) {
                messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_SECOND, locale);
            } else if (timeUnit == TimeUnit.MINUTE) {
                messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_MINUTE, locale);
            } else if (timeUnit == TimeUnit.HOUR) {
                messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_HOUR, locale);
            } else if (timeUnit == TimeUnit.WEEK) {
                messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_WEEK, locale);
            } else if (timeUnit == TimeUnit.DAY) {
                messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_DAY, locale);
            } else if (timeUnit == TimeUnit.MONTH) {
                messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_MONTH, locale);
            } else if (timeUnit == TimeUnit.YEAR) {
                messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_YEAR, locale);
            }
            Object[] pair = countToPatterns.get(srcPluralCount);
            if (pair == null) {
                pair = new Object[2];
                countToPatterns.put(srcPluralCount, pair);
            }
            pair[styl] = messageFormat;
        } else {
            // fall back to rule "other", and search in parents
            searchInTree(resourceKey, styl, timeUnit, srcPluralCount, "other", countToPatterns);
        }
    }

    // boilerplate code to make TimeUnitFormat otherwise follow the contract of
    // MeasureFormat

    /**
     * @deprecated ICU 53 see {@link MeasureFormat}
     */
    @Deprecated
    @Override
    public Object clone() {
        TimeUnitFormat result = (TimeUnitFormat) super.clone();
        result.format = (NumberFormat) format.clone();
        return result;
    }
    // End boilerplate.

    // Serialization

    private Object writeReplace() throws ObjectStreamException {
        return super.toTimeUnitProxy();
    }

    // Preserve backward serialize backward compatibility.
    private Object readResolve() throws ObjectStreamException {
        return new TimeUnitFormat(locale, style, format);
    }
}
