/*
 *******************************************************************************
 * Copyright (C) 2009-2012, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
package com.ibm.icu.impl;

import java.lang.ref.SoftReference;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

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.util.ULocale;
import com.ibm.icu.util.UResourceBundle;

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

    public CurrencyDisplayInfo getInstance(ULocale locale, boolean withFallback) {
        ICUResourceBundle rb = (ICUResourceBundle) UResourceBundle.getBundleInstance(
                ICUResourceBundle.ICU_CURR_BASE_NAME, locale);
        if (!withFallback) {
            int status = rb.getLoadingStatus();
            if (status == ICUResourceBundle.FROM_DEFAULT || status == ICUResourceBundle.FROM_ROOT) {
                return CurrencyData.DefaultInfo.getWithFallback(false);
            }
        }
        return new ICUCurrencyDisplayInfo(rb, withFallback);
    }

    public boolean hasData() {
        return true;
    }

    static class ICUCurrencyDisplayInfo extends CurrencyDisplayInfo {
        private final boolean fallback;
        private final ICUResourceBundle rb;
        private final ICUResourceBundle currencies;
        private final ICUResourceBundle plurals;
        private SoftReference<Map<String, String>> _symbolMapRef;
        private SoftReference<Map<String, String>> _nameMapRef;

        public ICUCurrencyDisplayInfo(ICUResourceBundle rb, boolean fallback) {
            this.fallback = fallback;
            this.rb = rb;
            this.currencies = rb.findTopLevel("Currencies");
            this.plurals = rb.findTopLevel("CurrencyPlurals");
       }

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

        @Override
        public String getName(String isoCode) {
            return getName(isoCode, false);
        }

        @Override
        public String getSymbol(String isoCode) {
            return getName(isoCode, true);
        }

        private String getName(String isoCode, boolean symbolName) {
            if (currencies != null) {
                ICUResourceBundle result = currencies.findWithFallback(isoCode);
                if (result != null) {
                    if (!fallback) {
                        int status = result.getLoadingStatus();
                        if (status == ICUResourceBundle.FROM_DEFAULT ||
                                status == ICUResourceBundle.FROM_ROOT) {
                            return null;
                        }
                    }
                    return result.getString(symbolName ? 0 : 1);
                }
            }

            return fallback ? isoCode : null;
        }

        @Override
        public String getPluralName(String isoCode, String pluralKey ) {
            // See http://unicode.org/reports/tr35/#Currencies, especially the fallback rule.
            if (plurals != null) {
                ICUResourceBundle pluralsBundle = plurals.findWithFallback(isoCode);
                if (pluralsBundle != null) {
                    ICUResourceBundle pluralBundle = pluralsBundle.findWithFallback(pluralKey);
                    if (pluralBundle == null) {
                        if (!fallback) {
                            return null;
                        }
                        pluralBundle = pluralsBundle.findWithFallback("other");
                        if (pluralBundle == null) {
                            return getName(isoCode);
                        }
                    }
                    return pluralBundle.getString();
                }
            }

            return fallback ? getName(isoCode) : null;
        }

        @Override
        public Map<String, String> symbolMap() {
            Map<String, String> map = _symbolMapRef == null ? null : _symbolMapRef.get();
            if (map == null) {
                map = _createSymbolMap();
                // atomic and idempotent
                _symbolMapRef = new SoftReference<Map<String, String>>(map);
            }
            return map;
        }

        @Override
        public Map<String, String> nameMap() {
            Map<String, String> map = _nameMapRef == null ? null : _nameMapRef.get();
            if (map == null) {
                map = _createNameMap();
                // atomic and idempotent
                _nameMapRef = new SoftReference<Map<String, String>>(map);
            }
            return map;
        }

       @Override
        public Map<String, String> getUnitPatterns() {
            Map<String, String> result = new HashMap<String, String>();

            ULocale locale = rb.getULocale();
            for (;locale != null; locale = locale.getFallback()) {
                ICUResourceBundle r = (ICUResourceBundle) UResourceBundle.getBundleInstance(
                        ICUResourceBundle.ICU_CURR_BASE_NAME, locale);
                if (r == null) {
                    continue;
                }
                ICUResourceBundle cr = r.findWithFallback("CurrencyUnitPatterns");
                if (cr == null) {
                    continue;
                }
                for (int index = 0, size = cr.getSize(); index < size; ++index) {
                    ICUResourceBundle b = (ICUResourceBundle) cr.get(index);
                    String key = b.getKey();
                    if (result.containsKey(key)) {
                        continue;
                    }
                    result.put(key, b.getString());
                }
            }

            // Default result is the empty map. Callers who require a pattern will have to
            // supply a default.
            return Collections.unmodifiableMap(result);
        }

        @Override
        public CurrencyFormatInfo getFormatInfo(String isoCode) {
            ICUResourceBundle crb = currencies.findWithFallback(isoCode);
            if (crb != null && crb.getSize() > 2) {
                crb = crb.at(2);
                if (crb != null) {
                  String pattern = crb.getString(0);
                  char separator = crb.getString(1).charAt(0);
                  char groupingSeparator = crb.getString(2).charAt(0);
                  return new CurrencyFormatInfo(pattern, separator, groupingSeparator);
                }
            }
            return null;
        }

        @Override
        public CurrencySpacingInfo getSpacingInfo() {
            ICUResourceBundle srb = rb.findWithFallback("currencySpacing");
            if (srb != null) {
                ICUResourceBundle brb = srb.findWithFallback("beforeCurrency");
                ICUResourceBundle arb = srb.findWithFallback("afterCurrency");
                if (arb != null && brb != null) {
                    String beforeCurrencyMatch = brb.findWithFallback("currencyMatch").getString();
                    String beforeContextMatch = brb.findWithFallback("surroundingMatch").getString();
                    String beforeInsert = brb.findWithFallback("insertBetween").getString();
                    String afterCurrencyMatch = arb.findWithFallback("currencyMatch").getString();
                    String afterContextMatch = arb.findWithFallback("surroundingMatch").getString();
                    String afterInsert = arb.findWithFallback("insertBetween").getString();

                    return new CurrencySpacingInfo(
                            beforeCurrencyMatch, beforeContextMatch, beforeInsert,
                            afterCurrencyMatch, afterContextMatch, afterInsert);
                }
            }
            return fallback ? CurrencySpacingInfo.DEFAULT : null;
        }

        private Map<String, String> _createSymbolMap() {
            Map<String, String> result = new HashMap<String, String>();

            for (ULocale locale = rb.getULocale(); locale != null; locale = locale.getFallback()) {
                ICUResourceBundle bundle = (ICUResourceBundle)
                    UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_CURR_BASE_NAME, locale);
                ICUResourceBundle curr = bundle.findTopLevel("Currencies");
                if (curr == null) {
                    continue;
                }
                for (int i = 0; i < curr.getSize(); ++i) {
                    ICUResourceBundle item = curr.at(i);
                    String isoCode = item.getKey();
                    if (!result.containsKey(isoCode)) {
                        // put the code itself
                        result.put(isoCode, isoCode);
                        // 0 == symbol element
                        String symbol = item.getString(0);
                        result.put(symbol, isoCode);
                    }
                }
            }

            return Collections.unmodifiableMap(result);
        }

        private Map<String, String> _createNameMap() {
            // ignore case variants
            Map<String, String> result = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);

            Set<String> visited = new HashSet<String>();
            Map<String, Set<String>> visitedPlurals = new HashMap<String, Set<String>>();
            for (ULocale locale = rb.getULocale(); locale != null; locale = locale.getFallback()) {
                ICUResourceBundle bundle = (ICUResourceBundle)
                    UResourceBundle.getBundleInstance(ICUResourceBundle.ICU_CURR_BASE_NAME, locale);
                ICUResourceBundle curr = bundle.findTopLevel("Currencies");
                if (curr != null) {
                    for (int i = 0; i < curr.getSize(); ++i) {
                        ICUResourceBundle item = curr.at(i);
                        String isoCode = item.getKey();
                        if (!visited.contains(isoCode)) {
                            visited.add(isoCode);
                            // 1 == name element
                            String name = item.getString(1);
                            result.put(name, isoCode);
                        }
                    }
                }

                ICUResourceBundle plurals = bundle.findTopLevel("CurrencyPlurals");
                if (plurals != null) {
                    for (int i = 0; i < plurals.getSize(); ++i) {
                        ICUResourceBundle item = plurals.at(i);
                        String isoCode = item.getKey();
                        Set<String> pluralSet = visitedPlurals.get(isoCode);
                        if (pluralSet == null) {
                            pluralSet = new HashSet<String>();
                            visitedPlurals.put(isoCode, pluralSet);
                        }
                        for (int j = 0; j < item.getSize(); ++j) {
                            ICUResourceBundle plural = item.at(j);
                            String pluralType = plural.getKey();
                            if (!pluralSet.contains(pluralType)) {
                                String pluralName = plural.getString();
                                result.put(pluralName, isoCode);
                                pluralSet.add(pluralType);
                            }
                        }
                    }
                }
            }

            return Collections.unmodifiableMap(result);
        }
    }
}
