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

import java.lang.ref.SoftReference;
import java.util.HashMap;
import java.util.Map;
import java.util.MissingResourceException;

import com.ibm.icu.impl.CurrencyData.CurrencyDisplayInfo;
import com.ibm.icu.impl.CurrencyData.CurrencyDisplayInfoProvider;
import com.ibm.icu.impl.CurrencyData.CurrencyFormatInfo;
import com.ibm.icu.impl.CurrencyData.CurrencySpacingInfo;
import com.ibm.icu.impl.ICUResourceBundle.OpenType;
import com.ibm.icu.util.ICUException;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.UResourceBundle;

public class ICUCurrencyDisplayInfoProvider implements CurrencyDisplayInfoProvider {
    public ICUCurrencyDisplayInfoProvider() {
    }

    /**
     * Single-item cache for ICUCurrencyDisplayInfo keyed by locale.
     */
    private volatile ICUCurrencyDisplayInfo currencyDisplayInfoCache = null;

    @Override
    public CurrencyDisplayInfo getInstance(ULocale locale, boolean withFallback) {
        // Make sure the locale is non-null (this can happen during deserialization):
        if (locale == null) { locale = ULocale.ROOT; }
        ICUCurrencyDisplayInfo instance = currencyDisplayInfoCache;
        if (instance == null || !instance.locale.equals(locale) || instance.fallback != withFallback) {
            ICUResourceBundle rb;
            if (withFallback) {
                rb = ICUResourceBundle.getBundleInstance(
                        ICUData.ICU_CURR_BASE_NAME, locale, OpenType.LOCALE_DEFAULT_ROOT);
            } else {
                try {
                    rb = ICUResourceBundle.getBundleInstance(
                            ICUData.ICU_CURR_BASE_NAME, locale, OpenType.LOCALE_ONLY);
                } catch (MissingResourceException e) {
                    return null;
                }
            }
            instance = new ICUCurrencyDisplayInfo(locale, rb, withFallback);
            currencyDisplayInfoCache = instance;
        }
        return instance;
    }

    @Override
    public boolean hasData() {
        return true;
    }

    /**
     * This class performs data loading for currencies and keeps data in lightweight cache.
     */
    static class ICUCurrencyDisplayInfo extends CurrencyDisplayInfo {
        final ULocale locale;
        final boolean fallback;
        private final ICUResourceBundle rb;

        /**
         * Single-item cache for getName(), getSymbol(), and getFormatInfo().
         * Holds data for only one currency. If another currency is requested, the old cache item is overwritten.
         */
        private volatile FormattingData formattingDataCache = null;

        /**
         * Single-item cache for getNarrowSymbol().
         * Holds data for only one currency. If another currency is requested, the old cache item is overwritten.
         */
        private volatile NarrowSymbol narrowSymbolCache = null;

        /**
         * Single-item cache for getPluralName().
         *
         * <p>
         * array[0] is the ISO code.<br>
         * array[1+p] is the plural name where p=standardPlural.ordinal().
         *
         * <p>
         * Holds data for only one currency. If another currency is requested, the old cache item is overwritten.
         */
        private volatile String[] pluralsDataCache = null;

        /**
         * Cache for symbolMap() and nameMap().
         */
        private volatile SoftReference<ParsingData> parsingDataCache = new SoftReference<>(null);

        /**
         * Cache for getUnitPatterns().
         */
        private volatile Map<String, String> unitPatternsCache = null;

        /**
         * Cache for getSpacingInfo().
         */
        private volatile CurrencySpacingInfo spacingInfoCache = null;

        static class FormattingData {
            final String isoCode;
            String displayName = null;
            String symbol = null;
            CurrencyFormatInfo formatInfo = null;

            FormattingData(String isoCode) { this.isoCode = isoCode; }
        }

        static class NarrowSymbol {
            final String isoCode;
            String narrowSymbol = null;

            NarrowSymbol(String isoCode) { this.isoCode = isoCode; }
        }

        static class ParsingData {
            Map<String, String> symbolToIsoCode = new HashMap<>();
            Map<String, String> nameToIsoCode = new HashMap<>();
        }

        ////////////////////////
        /// START PUBLIC API ///
        ////////////////////////

        public ICUCurrencyDisplayInfo(ULocale locale, ICUResourceBundle rb, boolean fallback) {
            this.locale = locale;
            this.fallback = fallback;
            this.rb = rb;
        }

        @Override
        public ULocale getULocale() {
            return rb.getULocale();
        }

        @Override
        public String getName(String isoCode) {
            FormattingData formattingData = fetchFormattingData(isoCode);

            // Fall back to ISO Code
            if (formattingData.displayName == null && fallback) {
                return isoCode;
            }
            return formattingData.displayName;
        }

        @Override
        public String getSymbol(String isoCode) {
            FormattingData formattingData = fetchFormattingData(isoCode);

            // Fall back to ISO Code
            if (formattingData.symbol == null && fallback) {
                return isoCode;
            }
            return formattingData.symbol;
        }

        @Override
        public String getNarrowSymbol(String isoCode) {
            NarrowSymbol narrowSymbol = fetchNarrowSymbol(isoCode);

            // Fall back to ISO Code
            if (narrowSymbol.narrowSymbol == null && fallback) {
                return getSymbol(isoCode);
            }
            return narrowSymbol.narrowSymbol;
        }

        @Override
        public String getPluralName(String isoCode, String pluralKey ) {
            StandardPlural plural = StandardPlural.orNullFromString(pluralKey);
            String[] pluralsData = fetchPluralsData(isoCode);

            // See http://unicode.org/reports/tr35/#Currencies, especially the fallback rule.
            String result = null;
            if (plural != null) {
                result = pluralsData[1 + plural.ordinal()];
            }
            if (result == null && fallback) {
                // First fall back to the "other" plural variant
                // Note: If plural is already "other", this fallback is benign
                result = pluralsData[1 + StandardPlural.OTHER.ordinal()];
            }
            if (result == null && fallback) {
                // If that fails, fall back to the display name
                FormattingData formattingData = fetchFormattingData(isoCode);
                result = formattingData.displayName;
            }
            if (result == null && fallback) {
                // If all else fails, return the ISO code
                result = isoCode;
            }
            return result;
        }

        @Override
        public Map<String, String> symbolMap() {
            ParsingData parsingData = fetchParsingData();
            return parsingData.symbolToIsoCode;
        }

        @Override
        public Map<String, String> nameMap() {
            ParsingData parsingData = fetchParsingData();
            return parsingData.nameToIsoCode;
        }

        @Override
        public Map<String, String> getUnitPatterns() {
            // Default result is the empty map. Callers who require a pattern will have to
            // supply a default.
            Map<String,String> unitPatterns = fetchUnitPatterns();
            return unitPatterns;
        }

        @Override
        public CurrencyFormatInfo getFormatInfo(String isoCode) {
            FormattingData formattingData = fetchFormattingData(isoCode);
            return formattingData.formatInfo;
        }

        @Override
        public CurrencySpacingInfo getSpacingInfo() {
            CurrencySpacingInfo spacingInfo = fetchSpacingInfo();

            // Fall back to DEFAULT
            if ((!spacingInfo.hasBeforeCurrency || !spacingInfo.hasAfterCurrency) && fallback) {
                return CurrencySpacingInfo.DEFAULT;
            }
            return spacingInfo;
        }

        /////////////////////////////////////////////
        /// END PUBLIC API -- START DATA FRONTEND ///
        /////////////////////////////////////////////

        FormattingData fetchFormattingData(String isoCode) {
            FormattingData result = formattingDataCache;
            if (result == null || !result.isoCode.equals(isoCode)) {
                result = new FormattingData(isoCode);
                CurrencySink sink = new CurrencySink(!fallback, CurrencySink.EntrypointTable.CURRENCIES);
                sink.formattingData = result;
                rb.getAllItemsWithFallbackNoFail("Currencies/" + isoCode, sink);
                formattingDataCache = result;
            }
            return result;
        }

        NarrowSymbol fetchNarrowSymbol(String isoCode) {
            NarrowSymbol result = narrowSymbolCache;
            if (result == null || !result.isoCode.equals(isoCode)) {
                result = new NarrowSymbol(isoCode);
                CurrencySink sink = new CurrencySink(!fallback, CurrencySink.EntrypointTable.CURRENCY_NARROW);
                sink.narrowSymbol = result;
                rb.getAllItemsWithFallbackNoFail("Currencies%narrow/" + isoCode, sink);
                narrowSymbolCache = result;
            }
            return result;
        }

        String[] fetchPluralsData(String isoCode) {
            String[] result = pluralsDataCache;
            if (result == null || !result[0].equals(isoCode)) {
                result = new String[1 + StandardPlural.COUNT];
                result[0] = isoCode;
                CurrencySink sink = new CurrencySink(!fallback, CurrencySink.EntrypointTable.CURRENCY_PLURALS);
                sink.pluralsData = result;
                rb.getAllItemsWithFallbackNoFail("CurrencyPlurals/" + isoCode, sink);
                pluralsDataCache = result;
            }
            return result;
        }

        ParsingData fetchParsingData() {
            ParsingData result = parsingDataCache.get();
            if (result == null) {
                result = new ParsingData();
                CurrencySink sink = new CurrencySink(!fallback, CurrencySink.EntrypointTable.TOP);
                sink.parsingData = result;
                rb.getAllItemsWithFallback("", sink);
                parsingDataCache = new SoftReference<>(result);
            }
            return result;
        }

        Map<String, String> fetchUnitPatterns() {
            Map<String, String> result = unitPatternsCache;
            if (result == null) {
                result = new HashMap<>();
                CurrencySink sink = new CurrencySink(!fallback, CurrencySink.EntrypointTable.CURRENCY_UNIT_PATTERNS);
                sink.unitPatterns = result;
                rb.getAllItemsWithFallback("CurrencyUnitPatterns", sink);
                unitPatternsCache = result;
            }
            return result;
        }

        CurrencySpacingInfo fetchSpacingInfo() {
            CurrencySpacingInfo result = spacingInfoCache;
            if (result == null) {
                result = new CurrencySpacingInfo();
                CurrencySink sink = new CurrencySink(!fallback, CurrencySink.EntrypointTable.CURRENCY_SPACING);
                sink.spacingInfo = result;
                rb.getAllItemsWithFallback("currencySpacing", sink);
                spacingInfoCache = result;
            }
            return result;
        }

        ////////////////////////////////////////////
        /// END DATA FRONTEND -- START DATA SINK ///
        ////////////////////////////////////////////

        private static final class CurrencySink extends UResource.Sink {
            final boolean noRoot;
            final EntrypointTable entrypointTable;

            // The fields to be populated on this run of the data sink will be non-null.
            FormattingData formattingData = null;
            String[] pluralsData = null;
            ParsingData parsingData = null;
            Map<String, String> unitPatterns = null;
            CurrencySpacingInfo spacingInfo = null;
            NarrowSymbol narrowSymbol = null;

            enum EntrypointTable {
                // For Parsing:
                TOP,

                // For Formatting:
                CURRENCIES,
                CURRENCY_PLURALS,
                CURRENCY_NARROW,
                CURRENCY_SPACING,
                CURRENCY_UNIT_PATTERNS
            }

            CurrencySink(boolean noRoot, EntrypointTable entrypointTable) {
                this.noRoot = noRoot;
                this.entrypointTable = entrypointTable;
            }

            /**
             * The entrypoint method delegates to helper methods for each of the types of tables
             * found in the currency data.
             */
            @Override
            public void put(UResource.Key key, UResource.Value value, boolean isRoot) {
                if (noRoot && isRoot) {
                    // Don't consume the root bundle
                    return;
                }

                switch (entrypointTable) {
                case TOP:
                    consumeTopTable(key, value);
                    break;
                case CURRENCIES:
                    consumeCurrenciesEntry(key, value);
                    break;
                case CURRENCY_PLURALS:
                    consumeCurrencyPluralsEntry(key, value);
                    break;
                case CURRENCY_NARROW:
                    consumeCurrenciesNarrowEntry(key, value);
                    break;
                case CURRENCY_SPACING:
                    consumeCurrencySpacingTable(key, value);
                    break;
                case CURRENCY_UNIT_PATTERNS:
                    consumeCurrencyUnitPatternsTable(key, value);
                    break;
                }
            }

            private void consumeTopTable(UResource.Key key, UResource.Value value) {
                UResource.Table table = value.getTable();
                for (int i = 0; table.getKeyAndValue(i, key, value); i++) {
                    if (key.contentEquals("Currencies")) {
                        consumeCurrenciesTable(key, value);
                    } else if (key.contentEquals("Currencies%variant")) {
                        consumeCurrenciesVariantTable(key, value);
                    } else if (key.contentEquals("CurrencyPlurals")) {
                        consumeCurrencyPluralsTable(key, value);
                    }
                }
            }

            /*
             *  Currencies{
             *      ...
             *      USD{
             *          "US$",        => symbol
             *          "US Dollar",  => display name
             *      }
             *      ...
             *      ESP{
             *          "₧",                  => symbol
             *          "pesseta espanyola",  => display name
             *          {
             *              "¤ #,##0.00",     => currency-specific pattern
             *              ",",              => currency-specific grouping separator
             *              ".",              => currency-specific decimal separator
             *          }
             *      }
             *      ...
             *  }
             */
            void consumeCurrenciesTable(UResource.Key key, UResource.Value value) {
                // The full Currencies table is consumed for parsing only.
                assert parsingData != null;
                UResource.Table table = value.getTable();
                for (int i = 0; table.getKeyAndValue(i, key, value); i++) {
                    String isoCode = key.toString();
                    if (value.getType() != UResourceBundle.ARRAY) {
                        throw new ICUException("Unexpected data type in Currencies table for " + isoCode);
                    }
                    UResource.Array array = value.getArray();

                    parsingData.symbolToIsoCode.put(isoCode, isoCode); // Add the ISO code itself as a symbol
                    array.getValue(0, value);
                    parsingData.symbolToIsoCode.put(value.getString(), isoCode);
                    array.getValue(1, value);
                    parsingData.nameToIsoCode.put(value.getString(), isoCode);
                }
            }

            void consumeCurrenciesEntry(UResource.Key key, UResource.Value value) {
                assert formattingData != null;
                String isoCode = key.toString();
                if (value.getType() != UResourceBundle.ARRAY) {
                    throw new ICUException("Unexpected data type in Currencies table for " + isoCode);
                }
                UResource.Array array = value.getArray();

                if (formattingData.symbol == null) {
                    array.getValue(0, value);
                    formattingData.symbol = value.getString();
                }
                if (formattingData.displayName == null) {
                    array.getValue(1, value);
                    formattingData.displayName = value.getString();
                }

                // If present, the third element is the currency format info.
                // TODO: Write unit test to ensure that this data is being used by number formatting.
                if (array.getSize() > 2 && formattingData.formatInfo == null) {
                    array.getValue(2, value);
                    UResource.Array formatArray = value.getArray();
                    formatArray.getValue(0, value);
                    String formatPattern = value.getString();
                    formatArray.getValue(1, value);
                    String decimalSeparator = value.getString();
                    formatArray.getValue(2, value);
                    String groupingSeparator = value.getString();
                    formattingData.formatInfo = new CurrencyFormatInfo(
                            isoCode, formatPattern, decimalSeparator, groupingSeparator);
                }
            }

            /*
             *  Currencies%narrow{
             *      AOA{"Kz"}
             *      ARS{"$"}
             *      ...
             *  }
             */
            void consumeCurrenciesNarrowEntry(UResource.Key key, UResource.Value value) {
                assert narrowSymbol != null;
                // No extra structure to traverse.
                if (narrowSymbol.narrowSymbol == null) {
                    narrowSymbol.narrowSymbol = value.getString();
                }
            }

            /*
             *  Currencies%variant{
             *      TRY{"TL"}
             *  }
             */
            void consumeCurrenciesVariantTable(UResource.Key key, UResource.Value value) {
                // Note: This data is used for parsing but not formatting.
                assert parsingData != null;
                UResource.Table table = value.getTable();
                for (int i = 0; table.getKeyAndValue(i, key, value); i++) {
                    String isoCode = key.toString();
                    parsingData.symbolToIsoCode.put(value.getString(), isoCode);
                }
            }

            /*
             *  CurrencyPlurals{
             *      BYB{
             *          one{"Belarusian new rouble (1994–1999)"}
             *          other{"Belarusian new roubles (1994–1999)"}
             *      }
             *      ...
             *  }
             */
            void consumeCurrencyPluralsTable(UResource.Key key, UResource.Value value) {
                // The full CurrencyPlurals table is consumed for parsing only.
                assert parsingData != null;
                UResource.Table table = value.getTable();
                for (int i = 0; table.getKeyAndValue(i, key, value); i++) {
                    String isoCode = key.toString();
                    UResource.Table pluralsTable = value.getTable();
                    for (int j=0; pluralsTable.getKeyAndValue(j, key, value); j++) {
                        StandardPlural plural = StandardPlural.orNullFromString(key.toString());
                        if (plural == null) {
                            throw new ICUException("Could not make StandardPlural from keyword " + key);
                        }

                        parsingData.nameToIsoCode.put(value.getString(), isoCode);
                    }
                }
            }

            void consumeCurrencyPluralsEntry(UResource.Key key, UResource.Value value) {
                assert pluralsData != null;
                UResource.Table pluralsTable = value.getTable();
                for (int j=0; pluralsTable.getKeyAndValue(j, key, value); j++) {
                    StandardPlural plural = StandardPlural.orNullFromString(key.toString());
                    if (plural == null) {
                        throw new ICUException("Could not make StandardPlural from keyword " + key);
                    }

                    if (pluralsData[1 + plural.ordinal()] == null) {
                        pluralsData[1 + plural.ordinal()] = value.getString();
                    }
                }
            }

            /*
             *  currencySpacing{
             *      afterCurrency{
             *          currencyMatch{"[:^S:]"}
             *          insertBetween{" "}
             *          surroundingMatch{"[:digit:]"}
             *      }
             *      beforeCurrency{
             *          currencyMatch{"[:^S:]"}
             *          insertBetween{" "}
             *          surroundingMatch{"[:digit:]"}
             *      }
             *  }
             */
            void consumeCurrencySpacingTable(UResource.Key key, UResource.Value value) {
                assert spacingInfo != null;
                UResource.Table spacingTypesTable = value.getTable();
                for (int i = 0; spacingTypesTable.getKeyAndValue(i, key, value); ++i) {
                    CurrencySpacingInfo.SpacingType type;
                    if (key.contentEquals("beforeCurrency")) {
                        type = CurrencySpacingInfo.SpacingType.BEFORE;
                        spacingInfo.hasBeforeCurrency = true;
                    } else if (key.contentEquals("afterCurrency")) {
                        type = CurrencySpacingInfo.SpacingType.AFTER;
                        spacingInfo.hasAfterCurrency = true;
                    } else {
                        continue;
                    }

                    UResource.Table patternsTable = value.getTable();
                    for (int j = 0; patternsTable.getKeyAndValue(j, key, value); ++j) {
                        CurrencySpacingInfo.SpacingPattern pattern;
                        if (key.contentEquals("currencyMatch")) {
                            pattern = CurrencySpacingInfo.SpacingPattern.CURRENCY_MATCH;
                        } else if (key.contentEquals("surroundingMatch")) {
                            pattern = CurrencySpacingInfo.SpacingPattern.SURROUNDING_MATCH;
                        } else if (key.contentEquals("insertBetween")) {
                            pattern = CurrencySpacingInfo.SpacingPattern.INSERT_BETWEEN;
                        } else {
                            continue;
                        }

                        spacingInfo.setSymbolIfNull(type, pattern, value.getString());
                    }
                }
            }

            /*
             *  CurrencyUnitPatterns{
             *      other{"{0} {1}"}
             *      ...
             *  }
             */
            void consumeCurrencyUnitPatternsTable(UResource.Key key, UResource.Value value) {
                assert unitPatterns != null;
                UResource.Table table = value.getTable();
                for (int i = 0; table.getKeyAndValue(i, key, value); i++) {
                    String pluralKeyword = key.toString();
                    if (unitPatterns.get(pluralKeyword) == null) {
                        unitPatterns.put(pluralKeyword, value.getString());
                    }
                }
            }
        }
    }
}
