// © 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.text;

import java.util.ArrayList;
import java.util.Locale;
import java.util.MissingResourceException;

import com.ibm.icu.impl.CacheBase;
import com.ibm.icu.impl.ICUData;
import com.ibm.icu.impl.ICUResourceBundle;
import com.ibm.icu.impl.SoftCache;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.ULocale.Category;
import com.ibm.icu.util.UResourceBundle;
import com.ibm.icu.util.UResourceBundleIterator;


/**
 * <code>NumberingSystem</code> is the base class for all number
 * systems. This class provides the interface for setting different numbering
 * system types, whether it be a simple alternate digit system such as
 * Thai digits or Devanagari digits, or an algorithmic numbering system such
 * as Hebrew numbering or Chinese numbering.
 *
 * @author       John Emmons
 * @stable ICU 4.2
 */
public class NumberingSystem {
    private static final String[] OTHER_NS_KEYWORDS = { "native", "traditional", "finance" };

    /**
     * For convenience, an instance representing the <em>latn</em> numbering system, which
     * corresponds to digits in the ASCII range '0' through '9'.
     *
     * @stable ICU 60
     */
    public static final NumberingSystem LATIN = lookupInstanceByName("latn");

    /**
     * Default constructor.  Returns a numbering system that uses the Latin-script decimal
     * digits 0 through 9.  This should be equivalent to NumberingSystem.LATIN.
     *
     * @stable ICU 4.2
     */
    public NumberingSystem() {
        radix = 10;
        algorithmic = false;
        desc = "0123456789";
        name = "latn";
    }

    /**
     * Factory method for creating a numbering system.
     * @param radix_in The radix for this numbering system.  ICU currently
     * supports only numbering systems whose radix is 10.
     * @param isAlgorithmic_in Specifies whether the numbering system is algorithmic
     * (true) or numeric (false).
     * @param desc_in String used to describe the characteristics of the numbering
     * system.  For numeric systems, this string contains the digits used by the
     * numbering system, in order, starting from zero.  For algorithmic numbering
     * systems, the string contains the name of the RBNF ruleset in the locale's
     * NumberingSystemRules section that will be used to format numbers using
     * this numbering system.
     * @stable ICU 4.2
     */
    public static NumberingSystem getInstance(int radix_in, boolean isAlgorithmic_in, String desc_in ) {
        return getInstance(null,radix_in,isAlgorithmic_in,desc_in);
    }

    /**
     * Factory method for creating a numbering system.
     * @param name_in The string representing the name of the numbering system.
     * @param radix_in The radix for this numbering system.  ICU currently
     * supports only numbering systems whose radix is 10.
     * @param isAlgorithmic_in Specifies whether the numbering system is algorithmic
     * (true) or numeric (false).
     * @param desc_in String used to describe the characteristics of the numbering
     * system.  For numeric systems, this string contains the digits used by the
     * numbering system, in order, starting from zero.  For algorithmic numbering
     * systems, the string contains the name of the RBNF ruleset in the locale's
     * NumberingSystemRules section that will be used to format numbers using
     * this numbering system.
     * @stable ICU 4.6
     */

    private static NumberingSystem getInstance(String name_in, int radix_in, boolean isAlgorithmic_in, String desc_in ) {
        if ( radix_in < 2 ) {
            throw new IllegalArgumentException("Invalid radix for numbering system");
        }

        if ( !isAlgorithmic_in ) {
            if ( desc_in.codePointCount(0, desc_in.length()) != radix_in || !isValidDigitString(desc_in)) {
                throw new IllegalArgumentException("Invalid digit string for numbering system");
            }
        }
        NumberingSystem ns = new NumberingSystem();
        ns.radix = radix_in;
        ns.algorithmic = isAlgorithmic_in;
        ns.desc = desc_in;
        ns.name = name_in;
        return ns;
    }

    /**
     * Returns the default numbering system for the specified locale.
     * @stable ICU 4.2
     */
    public static NumberingSystem getInstance(Locale inLocale) {
        return getInstance(ULocale.forLocale(inLocale));
    }

    /**
     * Returns the default numbering system for the specified ULocale.
     * @stable ICU 4.2
     */
    public static NumberingSystem getInstance(ULocale locale) {
        // Check for @numbers
        boolean nsResolved = true;
        String numbersKeyword = locale.getKeywordValue("numbers");
        if (numbersKeyword != null ) {
            for ( String keyword : OTHER_NS_KEYWORDS ) {
                if ( numbersKeyword.equals(keyword)) {
                    nsResolved = false;
                    break;
                }
            }
        } else {
            numbersKeyword = "default";
            nsResolved = false;
        }

        if (nsResolved) {
            NumberingSystem ns = getInstanceByName(numbersKeyword);
            if (ns != null) {
                return ns;
            }
            // If the @numbers keyword points to a bogus numbering system name,
            // we return the default for the locale.
            numbersKeyword = "default";
        }

        // Attempt to get the numbering system from the cache
        String baseName = locale.getBaseName();
        // TODO: Caching by locale+numbersKeyword could yield a large cache.
        // Try to load for each locale the mappings from OTHER_NS_KEYWORDS and default
        // to real numbering system names; can we get those from supplemental data?
        // Then look up those mappings for the locale and resolve the keyword.
        String key = baseName+"@numbers="+numbersKeyword;
        LocaleLookupData localeLookupData = new LocaleLookupData(locale, numbersKeyword);
        return cachedLocaleData.getInstance(key, localeLookupData);
    }

    private static class LocaleLookupData {
        public final ULocale locale;
        public final String numbersKeyword;

        LocaleLookupData(ULocale locale, String numbersKeyword) {
            this.locale = locale;
            this.numbersKeyword = numbersKeyword;
        }
    }

    static NumberingSystem lookupInstanceByLocale(LocaleLookupData localeLookupData) {
        ULocale locale = localeLookupData.locale;
        ICUResourceBundle rb;
        try {
            rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, locale);
            rb = rb.getWithFallback("NumberElements");
        } catch (MissingResourceException ex) {
            return new NumberingSystem();
        }

        String numbersKeyword = localeLookupData.numbersKeyword;
        String resolvedNumberingSystem = null;
        for (;;) {
            try {
                resolvedNumberingSystem = rb.getStringWithFallback(numbersKeyword);
                break;
            } catch (MissingResourceException ex) { // Fall back behavior as defined in TR35
                if (numbersKeyword.equals("native") || numbersKeyword.equals("finance")) {
                    numbersKeyword = "default";
                } else if (numbersKeyword.equals("traditional")) {
                    numbersKeyword = "native";
                } else {
                    break;
                }
            }
        }

        NumberingSystem ns = null;
        if (resolvedNumberingSystem != null) {
            ns = getInstanceByName(resolvedNumberingSystem);
        }

        if (ns == null) {
            ns = new NumberingSystem();
        }
        return ns;
    }

    /**
     * Returns the default numbering system for the default <code>FORMAT</code> locale.
     * @see Category#FORMAT
     * @stable ICU 4.2
     */
    public static NumberingSystem getInstance() {
        return getInstance(ULocale.getDefault(Category.FORMAT));
    }

    /**
     * Returns a numbering system from one of the predefined numbering systems
     * known to ICU.  Numbering system names are based on the numbering systems
     * defined in CLDR.  To get a list of available numbering systems, use the
     * getAvailableNames method.
     * @param name The name of the desired numbering system.  Numbering system
     * names often correspond with the name of the script they are associated
     * with.  For example, "thai" for Thai digits, "hebr" for Hebrew numerals.
     * @return The NumberingSystem instance, or null if not available.
     * @stable ICU 4.2
     */
    public static NumberingSystem getInstanceByName(String name) {
        // Get the numbering system from the cache.
        return cachedStringData.getInstance(name, null /* unused */);
    }

    private static NumberingSystem lookupInstanceByName(String name) {
        int radix;
        boolean isAlgorithmic;
        String description;
        try {
            UResourceBundle numberingSystemsInfo = UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, "numberingSystems");
            UResourceBundle nsCurrent = numberingSystemsInfo.get("numberingSystems");
            UResourceBundle nsTop = nsCurrent.get(name);

            description = nsTop.getString("desc");
            UResourceBundle nsRadixBundle = nsTop.get("radix");
            UResourceBundle nsAlgBundle = nsTop.get("algorithmic");
            radix = nsRadixBundle.getInt();
            int algorithmic = nsAlgBundle.getInt();

            isAlgorithmic = ( algorithmic == 1 );

        } catch (MissingResourceException ex) {
            return null;
        }

        return getInstance(name, radix, isAlgorithmic, description);
    }

    /**
     * Returns a string array containing a list of the names of numbering systems
     * currently known to ICU.
     *
     * @return An array of strings in alphabetical (invariant) order.
     * @stable ICU 4.2
     */
    public static String [] getAvailableNames() {

            UResourceBundle numberingSystemsInfo = UResourceBundle.getBundleInstance(ICUData.ICU_BASE_NAME, "numberingSystems");
            UResourceBundle nsCurrent = numberingSystemsInfo.get("numberingSystems");
            UResourceBundle temp;

            String nsName;
            ArrayList<String> output = new ArrayList<>();
            UResourceBundleIterator it = nsCurrent.getIterator();
            while (it.hasNext()) {
                temp = it.next();
                nsName = temp.getKey();
                output.add(nsName);
            }
            return output.toArray(new String[output.size()]);
    }

    /**
     * Convenience method to determine if a given digit string is valid for use as a
     * descriptor of a numeric ( non-algorithmic ) numbering system.  In order for
     * a digit string to be valid, it must contain exactly ten Unicode code points.
     * @stable ICU 4.2
     */
    public static boolean isValidDigitString(String str) {
        int numCodepoints = str.codePointCount(0, str.length());
        return (numCodepoints == 10);
    }

    /**
     * Returns the radix of the current numbering system.
     * @stable ICU 4.2
     */
    public int getRadix() {
        return radix;
    }

    /**
     * Returns the description string of the current numbering system.
     * The description string describes the characteristics of the numbering
     * system.  For numeric systems, this string contains the digits used by the
     * numbering system, in order, starting from zero.  For algorithmic numbering
     * systems, the string contains the name of the RBNF ruleset in the locale's
     * NumberingSystemRules section that will be used to format numbers using
     * this numbering system.
     * @stable ICU 4.2
     */
    public String getDescription() {
        return desc;
    }

    /**
     * Returns the string representing the name of the numbering system.
     * @stable ICU 4.6
     */
    public String getName() {
        return name;
    }
    /**
     * Returns the numbering system's algorithmic status.  If true,
     * the numbering system is algorithmic and uses an RBNF formatter to
     * format numerals.  If false, the numbering system is numeric and
     * uses a fixed set of digits.
     * @stable ICU 4.2
     */
    public boolean isAlgorithmic() {
        return algorithmic;
    }

    private String desc;
    private int radix;
    private boolean algorithmic;
    private String name;

    /**
     * Cache to hold the NumberingSystems by Locale.
     */
    private static CacheBase<String, NumberingSystem, LocaleLookupData> cachedLocaleData =
            new SoftCache<String, NumberingSystem, LocaleLookupData>() {
        @Override
        protected NumberingSystem createInstance(String key, LocaleLookupData localeLookupData) {
            return lookupInstanceByLocale(localeLookupData);
        }
    };

    /**
     * Cache to hold the NumberingSystems by name.
     */
    private static CacheBase<String, NumberingSystem, Void>  cachedStringData =
            new SoftCache<String, NumberingSystem, Void>() {
        @Override
        protected NumberingSystem createInstance(String key, Void unused) {
            return lookupInstanceByName(key);
        }
    };
}
