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

import java.util.HashMap;
import java.util.Map;
import java.util.MissingResourceException;

import com.ibm.icu.impl.ICUCache;
import com.ibm.icu.impl.ICUData;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.SimpleCache;
import com.ibm.icu.impl.UResource;
import com.ibm.icu.text.DecimalFormat.Unit;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.UResourceBundle;

/**
 * A cache containing data by locale for {@link CompactDecimalFormat}
 *
 * @author Travis Keep
 */
class CompactDecimalDataCache {

    private static final String SHORT_STYLE = "short";
    private static final String LONG_STYLE = "long";
    private static final String SHORT_CURRENCY_STYLE = "shortCurrency";
    private static final String NUMBER_ELEMENTS = "NumberElements";
    private static final String PATTERNS_LONG = "patternsLong";
    private static final String PATTERNS_SHORT = "patternsShort";
    private static final String DECIMAL_FORMAT = "decimalFormat";
    private static final String CURRENCY_FORMAT = "currencyFormat";
    private static final String LATIN_NUMBERING_SYSTEM = "latn";

    private static enum PatternsTableKey { PATTERNS_LONG, PATTERNS_SHORT };
    private static enum FormatsTableKey { DECIMAL_FORMAT, CURRENCY_FORMAT };

    public static final String OTHER = "other";

    /**
     * We can specify prefixes or suffixes for values with up to 15 digits,
     * less than 10^15.
     */
    static final int MAX_DIGITS = 15;

    private final ICUCache<ULocale, DataBundle> cache =
            new SimpleCache<ULocale, DataBundle>();

    /**
     * Data contains the compact decimal data for a particular locale. Data consists
     * of one array and two hashmaps. The index of the divisors array as well
     * as the arrays stored in the values of the two hashmaps correspond
     * to log10 of the number being formatted, so when formatting 12,345, the 4th
     * index of the arrays should be used. Divisors contain the number to divide
     * by before doing formatting. In the case of english, <code>divisors[4]</code>
     * is 1000.  So to format 12,345, divide by 1000 to get 12. Then use
     * PluralRules with the current locale to figure out which of the 6 plural variants
     * 12 matches: "zero", "one", "two", "few", "many", or "other." Prefixes and
     * suffixes are maps whose key is the plural variant and whose values are
     * arrays of strings with indexes corresponding to log10 of the original number.
     * these arrays contain the prefix or suffix to use.
     *
     * Each array in data is 15 in length, and every index is filled.
     *
     * @author Travis Keep
     *
     */
    static class Data {
        long[] divisors;
        Map<String, DecimalFormat.Unit[]> units;
        boolean fromFallback;

        Data(long[] divisors, Map<String, DecimalFormat.Unit[]> units)
        {
            this.divisors = divisors;
            this.units = units;
        }

        public boolean isEmpty() {
            return units == null || units.isEmpty();
        }
    }

    /**
     * DataBundle contains compact decimal data for all the styles in a particular
     * locale. Currently available styles are short and long for decimals, and
     * short only for currencies.
     *
     * @author Travis Keep
     */
    static class DataBundle {
        Data shortData;
        Data longData;
        Data shortCurrencyData;

        private DataBundle(Data shortData, Data longData, Data shortCurrencyData) {
            this.shortData = shortData;
            this.longData = longData;
            this.shortCurrencyData = shortCurrencyData;
        }

        private static DataBundle createEmpty() {
            return new DataBundle(
                new Data(new long[MAX_DIGITS], new HashMap<String, DecimalFormat.Unit[]>()),
                new Data(new long[MAX_DIGITS], new HashMap<String, DecimalFormat.Unit[]>()),
                new Data(new long[MAX_DIGITS], new HashMap<String, DecimalFormat.Unit[]>())
            );
        }
    }

    /**
     * Sink for enumerating all of the compact decimal format patterns.
     *
     * 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 CompactDecimalDataSink extends UResource.Sink {

        private DataBundle dataBundle; // Where to save values when they are read
        private ULocale locale; // The locale we are traversing (for exception messages)
        private boolean isLatin; // Whether or not we are traversing the Latin table
        private boolean isFallback; // Whether or not we are traversing the Latin table as fallback

        /*
         * NumberElements{              <-- top (numbering system table)
         *  latn{                       <-- patternsTable (one per numbering system)
         *    patternsLong{             <-- formatsTable (one per pattern)
         *      decimalFormat{          <-- powersOfTenTable (one per format)
         *        1000{                 <-- pluralVariantsTable (one per power of ten)
         *          one{"0 thousand"}   <-- plural variant and template
         */

        public CompactDecimalDataSink(DataBundle dataBundle, ULocale locale) {
            this.dataBundle = dataBundle;
            this.locale = locale;
        }

        @Override
        public void put(UResource.Key key, UResource.Value value, boolean isRoot) {
            // SPECIAL CASE: Don't consume root in the non-Latin numbering system
            if (isRoot && !isLatin) { return; }

            UResource.Table patternsTable = value.getTable();
            for (int i1 = 0; patternsTable.getKeyAndValue(i1, key, value); ++i1) {

                // patterns table: check for patternsShort or patternsLong
                PatternsTableKey patternsTableKey;
                if (key.contentEquals(PATTERNS_SHORT)) {
                    patternsTableKey = PatternsTableKey.PATTERNS_SHORT;
                } else if (key.contentEquals(PATTERNS_LONG)) {
                    patternsTableKey = PatternsTableKey.PATTERNS_LONG;
                } else {
                    continue;
                }

                // traverse into the table of formats
                UResource.Table formatsTable = value.getTable();
                for (int i2 = 0; formatsTable.getKeyAndValue(i2, key, value); ++i2) {

                    // formats table: check for decimalFormat or currencyFormat
                    FormatsTableKey formatsTableKey;
                    if (key.contentEquals(DECIMAL_FORMAT)) {
                        formatsTableKey = FormatsTableKey.DECIMAL_FORMAT;
                    } else if (key.contentEquals(CURRENCY_FORMAT)) {
                        formatsTableKey = FormatsTableKey.CURRENCY_FORMAT;
                    } else {
                        continue;
                    }

                    // Set the current style and destination based on the lvl1 and lvl2 keys
                    String style = null;
                    Data destination = null;
                    if (patternsTableKey == PatternsTableKey.PATTERNS_LONG
                            && formatsTableKey == FormatsTableKey.DECIMAL_FORMAT) {
                        style = LONG_STYLE;
                        destination = dataBundle.longData;
                    } else if (patternsTableKey == PatternsTableKey.PATTERNS_SHORT
                            && formatsTableKey == FormatsTableKey.DECIMAL_FORMAT) {
                        style = SHORT_STYLE;
                        destination = dataBundle.shortData;
                    } else if (patternsTableKey == PatternsTableKey.PATTERNS_SHORT
                            && formatsTableKey == FormatsTableKey.CURRENCY_FORMAT) {
                        style = SHORT_CURRENCY_STYLE;
                        destination = dataBundle.shortCurrencyData;
                    } else {
                        // Silently ignore this case
                        continue;
                    }

                    // SPECIAL CASE: RULES FOR WHETHER OR NOT TO CONSUME THIS TABLE:
                    //   1) Don't consume longData if shortData was consumed from the non-Latin
                    //      locale numbering system
                    //   2) Don't consume longData for the first time if this is the root bundle and
                    //      shortData is already populated from a more specific locale. Note that if
                    //      both longData and shortData are both only in root, longData will be
                    //      consumed since it is alphabetically before shortData in the bundle.
                    if (isFallback
                            && style == LONG_STYLE
                            && !dataBundle.shortData.isEmpty()
                            && !dataBundle.shortData.fromFallback) {
                        continue;
                    }
                    if (isRoot
                            && style == LONG_STYLE
                            && dataBundle.longData.isEmpty()
                            && !dataBundle.shortData.isEmpty()) {
                        continue;
                    }

                    // Set the "fromFallback" flag on the data object
                    destination.fromFallback = isFallback;

                    // traverse into the table of powers of ten
                    UResource.Table powersOfTenTable = value.getTable();
                    for (int i3 = 0; powersOfTenTable.getKeyAndValue(i3, key, value); ++i3) {

                        // This value will always be some even power of 10. e.g 10000.
                        long power10 = Long.parseLong(key.toString());
                        int log10Value = (int) Math.log10(power10);

                        // Silently ignore divisors that are too big.
                        if (log10Value >= MAX_DIGITS) continue;

                        // Iterate over the plural variants ("one", "other", etc)
                        UResource.Table pluralVariantsTable = value.getTable();
                        for (int i4 = 0; pluralVariantsTable.getKeyAndValue(i4, key, value); ++i4) {
                            // TODO: Use StandardPlural rather than String.
                            String pluralVariant = key.toString();
                            String template = value.toString();

                            // Copy the data into the in-memory data bundle (do not overwrite
                            // existing values)
                            int numZeros = populatePrefixSuffix(
                                    pluralVariant, log10Value, template, locale, style, destination, false);

                            // If populatePrefixSuffix returns -1, it means that this key has been
                            // encountered already.
                            if (numZeros < 0) {
                                continue;
                            }

                            // Set the divisor, which is based on the number of zeros in the template
                            // string.  If the divisor from here is different from the one previously
                            // stored, it means that the number of zeros in different plural variants
                            // differs; throw an exception.
                            long divisor = calculateDivisor(power10, numZeros);
                            if (destination.divisors[log10Value] != 0L
                                    && destination.divisors[log10Value] != divisor) {
                                throw new IllegalArgumentException("Plural variant '" + pluralVariant
                                        + "' template '" + template
                                        + "' for 10^" + log10Value
                                        + " has wrong number of zeros in " + localeAndStyle(locale, style));
                            }
                            destination.divisors[log10Value] = divisor;
                        }
                    }
                }
            }
        }
    }

    /**
     * Fetch data for a particular locale. Clients must not modify any part of the returned data. Portions of returned
     * data may be shared so modifying it will have unpredictable results.
     */
    DataBundle get(ULocale locale) {
        DataBundle result = cache.get(locale);
        if (result == null) {
            result = load(locale);
            cache.put(locale, result);
        }
        return result;
    }

    private static DataBundle load(ULocale ulocale) throws MissingResourceException {
        DataBundle dataBundle = DataBundle.createEmpty();
        String nsName = NumberingSystem.getInstance(ulocale).getName();
        ICUResourceBundle r = (ICUResourceBundle) UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME,
                ulocale);
        CompactDecimalDataSink sink = new CompactDecimalDataSink(dataBundle, ulocale);
        sink.isFallback = false;

        // First load the number elements data from nsName if nsName is not Latin.
        if (!nsName.equals(LATIN_NUMBERING_SYSTEM)) {
            sink.isLatin = false;

            try {
                r.getAllItemsWithFallback(NUMBER_ELEMENTS + "/" + nsName, sink);
            } catch (MissingResourceException e) {
                // Silently ignore and use Latin
            }

            // Set the "isFallback" flag for when we read Latin
            sink.isFallback = true;
        }

        // Now load Latin, which will fill in things that were left out from above.
        sink.isLatin = true;
        r.getAllItemsWithFallback(NUMBER_ELEMENTS + "/" + LATIN_NUMBERING_SYSTEM, sink);

        // If longData is empty, default it to be equal to shortData
        if (dataBundle.longData.isEmpty()) {
            dataBundle.longData = dataBundle.shortData;
        }

        // Check for "other" variants in each of the three data classes
        checkForOtherVariants(dataBundle.longData, ulocale, LONG_STYLE);
        checkForOtherVariants(dataBundle.shortData, ulocale, SHORT_STYLE);
        checkForOtherVariants(dataBundle.shortCurrencyData, ulocale, SHORT_CURRENCY_STYLE);

        // Resolve missing elements
        fillInMissing(dataBundle.longData);
        fillInMissing(dataBundle.shortData);
        fillInMissing(dataBundle.shortCurrencyData);

        // Return the data bundle
        return dataBundle;
    }


    /**
     * Populates prefix and suffix information for a particular plural variant
     * and index (log10 value).
     * @param pluralVariant e.g "one", "other"
     * @param idx the index (log10 value of the number) 0 <= idx < MAX_DIGITS
     * @param template e.g "00K"
     * @param locale the locale
     * @param style the style
     * @param destination Extracted prefix and suffix stored here.
     * @return number of zeros found before any decimal point in template, or -1 if it was not saved.
     */
    private static int populatePrefixSuffix(
            String pluralVariant, int idx, String template, ULocale locale, String style,
            Data destination, boolean overwrite) {
        int firstIdx = template.indexOf("0");
        int lastIdx = template.lastIndexOf("0");
        if (firstIdx == -1) {
            throw new IllegalArgumentException(
                "Expect at least one zero in template '" + template +
                "' for variant '" +pluralVariant + "' for 10^" + idx +
                " in " + localeAndStyle(locale, style));
        }
        String prefix = template.substring(0, firstIdx);
        String suffix = template.substring(lastIdx + 1);

        // Save the unit, and return -1 if it was not saved
        boolean saved = saveUnit(new DecimalFormat.Unit(prefix, suffix), pluralVariant, idx, destination.units, overwrite);
        if (!saved) {
            return -1;
        }

        // If there is effectively no prefix or suffix, ignore the actual
        // number of 0's and act as if the number of 0's matches the size
        // of the number
        if (prefix.trim().length() == 0 && suffix.trim().length() == 0) {
          return idx + 1;
        }

        // Calculate number of zeros before decimal point.
        int i = firstIdx + 1;
        while (i <= lastIdx && template.charAt(i) == '0') {
            i++;
        }
        return i - firstIdx;
    }

    /**
     * Calculate a divisor based on the magnitude and number of zeros in the
     * template string.
     * @param power10
     * @param numZeros
     * @return
     */
    private static long calculateDivisor(long power10, int numZeros) {
        // We craft our divisor such that when we divide by it, we get a
        // number with the same number of digits as zeros found in the
        // plural variant templates. If our magnitude is 10000 and we have
        // two 0's in our plural variants, then we want a divisor of 1000.
        // Note that if we have 43560 which is of same magnitude as 10000.
        // When we divide by 1000 we a quotient which rounds to 44 (2 digits)
        long divisor = power10;
        for (int i = 1; i < numZeros; i++) {
            divisor /= 10;
        }
        return divisor;
    }


    /**
     * Returns locale and style. Used to form useful messages in thrown exceptions.
     *
     * Note: This is not covered by unit tests since no exceptions are thrown on the default CLDR data.  It is too
     * cumbersome to cover via reflection.
     *
     * @param locale the locale
     * @param style the style
     */
    private static String localeAndStyle(ULocale locale, String style) {
        return "locale '" + locale + "' style '" + style + "'";
    }

    /**
     * Checks to make sure that an "other" variant is present in all powers of 10.
     * @param data
     */
    private static void checkForOtherVariants(Data data, ULocale locale, String style) {
        DecimalFormat.Unit[] otherByBase = data.units.get(OTHER);

        if (otherByBase == null) {
            throw new IllegalArgumentException("No 'other' plural variants defined in "
                    + localeAndStyle(locale, style));
        }

        // Check all other plural variants, and make sure that if any of them are populated, then
        // other is also populated
        for (Map.Entry<String, Unit[]> entry : data.units.entrySet()) {
            if (entry.getKey() == OTHER) continue;
            DecimalFormat.Unit[] variantByBase = entry.getValue();
            for (int log10Value = 0; log10Value < MAX_DIGITS; log10Value++) {
                if (variantByBase[log10Value] != null && otherByBase[log10Value] == null) {
                    throw new IllegalArgumentException(
                            "No 'other' plural variant defined for 10^" + log10Value
                            + " but a '" + entry.getKey() + "' variant is defined"
                            + " in " +localeAndStyle(locale, style));
                }
            }
        }
    }

    /**
     * After reading information from resource bundle into a Data object, there
     * is guarantee that it is complete.
     *
     * This method fixes any incomplete data it finds within <code>result</code>.
     * It looks at each log10 value applying the two rules.
     *   <p>
     *   If no prefix is defined for the "other" variant, use the divisor, prefixes and
     *   suffixes for all defined variants from the previous log10. For log10 = 0,
     *   use all empty prefixes and suffixes and a divisor of 1.
     *   </p><p>
     *   Otherwise, examine each plural variant defined for the given log10 value.
     *   If it has no prefix and suffix for a particular variant, use the one from the
     *   "other" variant.
     *   </p>
     *
     * @param result this instance is fixed in-place.
     */
    private static void fillInMissing(Data result) {
        // Initially we assume that previous divisor is 1 with no prefix or suffix.
        long lastDivisor = 1L;
        for (int i = 0; i < result.divisors.length; i++) {
            if (result.units.get(OTHER)[i] == null) {
                result.divisors[i] = lastDivisor;
                copyFromPreviousIndex(i, result.units);
            } else {
                lastDivisor = result.divisors[i];
                propagateOtherToMissing(i, result.units);
            }
        }
    }

    private static void propagateOtherToMissing(
            int idx, Map<String, DecimalFormat.Unit[]> units) {
        DecimalFormat.Unit otherVariantValue = units.get(OTHER)[idx];
        for (DecimalFormat.Unit[] byBase : units.values()) {
            if (byBase[idx] == null) {
                byBase[idx] = otherVariantValue;
            }
        }
    }

    private static void copyFromPreviousIndex(int idx, Map<String, DecimalFormat.Unit[]> units) {
        for (DecimalFormat.Unit[] byBase : units.values()) {
            if (idx == 0) {
                byBase[idx] = DecimalFormat.NULL_UNIT;
            } else {
                byBase[idx] = byBase[idx - 1];
            }
        }
    }

    private static boolean saveUnit(
            DecimalFormat.Unit unit, String pluralVariant, int idx,
            Map<String, DecimalFormat.Unit[]> units,
            boolean overwrite) {
        DecimalFormat.Unit[] byBase = units.get(pluralVariant);
        if (byBase == null) {
            byBase = new DecimalFormat.Unit[MAX_DIGITS];
            units.put(pluralVariant, byBase);
        }

        // Don't overwrite a pre-existing value unless the "overwrite" flag is true.
        if (!overwrite && byBase[idx] != null) {
            return false;
        }

        // Save the value and return
        byBase[idx] = unit;
        return true;
    }

    /**
     * Fetches a prefix or suffix given a plural variant and log10 value. If it
     * can't find the given variant, it falls back to "other".
     * @param prefixOrSuffix the prefix or suffix map
     * @param variant the plural variant
     * @param base log10 value. 0 <= base < MAX_DIGITS.
     * @return the prefix or suffix.
     */
    static DecimalFormat.Unit getUnit(
            Map<String, DecimalFormat.Unit[]> units, String variant, int base) {
        DecimalFormat.Unit[] byBase = units.get(variant);
        if (byBase == null) {
            byBase = units.get(CompactDecimalDataCache.OTHER);
        }
        return byBase[base];
    }
}
