/**
 *******************************************************************************
 * Copyright (C) 2001-2002, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 *
 * $Source: /xsrl/Nsvn/icu/icu4j/src/com/ibm/icu/util/Currency.java,v $
 * $Date: 2002/12/11 23:36:08 $
 * $Revision: 1.11 $
 *
 *******************************************************************************
 */
package com.ibm.icu.util;

import java.util.Locale;
import java.util.ResourceBundle;
import java.util.MissingResourceException;
import java.io.Serializable;
import com.ibm.icu.impl.ICULocaleData;
import com.ibm.icu.text.DecimalFormatSymbols;

import com.ibm.icu.impl.ICUService;
import com.ibm.icu.impl.ICUService.Key;
import com.ibm.icu.impl.ICUService.Factory;
import com.ibm.icu.impl.ICULocaleService;
import com.ibm.icu.impl.ICULocaleService.ICUResourceBundleFactory;

/**
 * A class encapsulating a currency, as defined by ISO 4217.  A
 * <tt>Currency</tt> object can be created given a <tt>Locale</tt> or
 * given an ISO 4217 code.  Once created, the <tt>Currency</tt> object
 * can return various data necessary to its proper display:
 *
 * <ul><li>A display symbol, for a specific locale
 * <li>The number of fraction digits to display
 * <li>A rounding increment
 * </ul>
 *
 * The <tt>DecimalFormat</tt> class uses these data to display
 * currencies.
 *
 * <p>Note: This class deliberately resembles
 * <tt>java.util.Currency</tt> but it has a completely independent
 * implementation, and adds features not present in the JDK.
 * @author Alan Liu
 * @draft ICU 2.2
 */
public class Currency implements Serializable {

    /**
     * ISO 4217 3-letter code.
     */
    private String isoCode;

    // begin registry stuff 
    ///CLOVER:OFF
    private static ICULocaleService service;

    private static ICULocaleService getService() {
        if (service == null) {
            ICULocaleService newService = new ICULocaleService("Currency");

            class CurrencyFactory extends ICUResourceBundleFactory {
                protected Object handleCreate(Locale loc, int kind, ICUService service) {
                    ResourceBundle bundle = ICULocaleData.getLocaleElements(loc);
                    String[] ce = bundle.getStringArray("CurrencyElements");
                    // System.out.println("currency factory loc: " + loc + " rb: " + bundle + "ce[1]" + ce[1]);
                    return new Currency(ce[1]);
                }
            }
            
            newService.registerFactory(new CurrencyFactory());
            synchronized (Currency.class) {
                if (service == null) {
                    service = newService;
                }
            }
        }
        return service;
    }
    ///CLOVER:ON
    /**
     * Returns a currency object for the default currency in the given
     * locale.
     * @draft ICU 2.2
     */
    public static Currency getInstance(Locale locale) {
        return (Currency)getService().get(locale);
    }

    /**
     * Returns a currency object given an ISO 4217 3-letter code.
     * @draft ICU 2.2
     */
    public static Currency getInstance(String theISOCode) {
        return new Currency(theISOCode);
    }
    ///CLOVER:OFF
    /**
     * Registers a new currency for the provided locale.  The returned object
     * is a key that can be used to unregister this currency object.
     * @prototype
     */
    /* public */ static Object register(Currency currency, Locale locale) {
        return getService().registerObject(currency, locale);
    }

    /**
     * Unregister the currency associated with this key (obtained from
     * registerInstance).
     * @prototype
     */
    /* public */ static boolean unregister(Object registryKey) {
        return getService().unregisterFactory((Factory)registryKey);
    }
    ///CLOVER:ON
    /**
     * Return an array of the locales for which a currency
     * is defined.
     * @draft ICU 2.2
     */
    public static Locale[] getAvailableLocales() {
        if (service == null) {
            return ICULocaleData.getAvailableLocales();
        } else {
            return service.getAvailableLocales();
        }
    }

    // end registry stuff

    /**
     * Return a hashcode for this currency.
     * @draft ICU 2.2
     */
    public int hashCode() {
        return isoCode.hashCode();
    }

    /**
     * Return true if rhs is a Currency instance, 
     * is non-null, and has the same currency code.
     * @draft ICU 2.2
     */
    public boolean equals(Object rhs) {
        try {
            return equals((Currency)rhs);
        }
        catch (ClassCastException e) {
            return false;
        }
    }

    /**
     * Return true if c is non-null and has the same currency code.
     * @draft ICU 2.2
     */
    public boolean equals(Currency c) {
        if (c == null) return false;
        if (c == this) return true;
        return c.getClass() == Currency.class &&
            this.isoCode.equals(c.isoCode);
    }

    /**
     * Returns the ISO 4217 3-letter code for this currency object.
     * @draft ICU 2.2
     */
    public String getCurrencyCode() {
        return isoCode;
    }

    /**
     * Returns the display string for this currency object in the
     * given locale.  For example, the display string for the USD
     * currency object in the en_US locale is "$".
     * @draft ICU 2.2
     */
    public String getSymbol(Locale locale) {
        // Look up the Currencies resource for the given locale.  The
        // Currencies locale looks like this in the original C
        // resource file:
        //|en {
        //|  Currencies { 
        //|    USD { "$" }
        //|    CHF { "sFr" }
        //|    //...
        //|  }
        //|}
        ResourceBundle rb = ICULocaleData.getLocaleElements(locale);
        // We can't cast this to String[][]; the cast has to happen later
        try {
            Object[][] currencies = (Object[][]) rb.getObject("Currencies");
            // Do a linear search
            for (int i=0; i<currencies.length; ++i) {
                if (isoCode.equals((String) currencies[i][0])) {
                    return (String) currencies[i][1];
                }
            }
        }
        catch (MissingResourceException e) {}

        try {
            // Since the Currencies resource is not fully populated yet,
            // check to see if we can find what we want in the CurrencyElements
            // resource.
            String[] currencyElements = rb.getStringArray("CurrencyElements");
            if (currencyElements[1].equals(isoCode)) {
                return currencyElements[0];
            }
        }
        catch (MissingResourceException e2) {}

        // If we fail to find a match, use the full ISO code
        return isoCode;
    }

    /**
     * Returns the number of the number of fraction digits that should
     * be displayed for this currency.
     * @return a non-negative number of fraction digits to be
     * displayed
     * @draft ICU 2.2
     */
    public int getDefaultFractionDigits() {
        return (findData())[0].intValue();
    }

    /**
     * Returns the rounding increment for this currency, or 0.0 if no
     * rounding is done by this currency.
     * @return the non-negative rounding increment, or 0.0 if none
     * @draft ICU 2.2
     */
    public double getRoundingIncrement() {
        Integer[] data = findData();

        int data1 = data[1].intValue(); // rounding increment

        // If there is no rounding return 0.0 to indicate no rounding.
        // This is the high-runner case, by far.
        if (data1 == 0) {
            return 0.0;
        }

        int data0 = data[0].intValue(); // fraction digits

        // If the meta data is invalid, return 0.0 to indicate no rounding.
        if (data0 < 0 || data0 >= POW10.length) {
            return 0.0;
        }

        // Return data[1] / 10^(data[0]).  The only actual rounding data,
        // as of this writing, is CHF { 2, 25 }.
        return (double) data1 / POW10[data0];
    }

    /**
     * Returns the ISO 4217 code for this currency.
     * @draft ICU 2.2
     */
    public String toString() {
        return isoCode;
    }

    /**
     * Constructs a currency object for the given ISO 4217 3-letter
     * code.  This constructor assumes that the code is valid.
     */
    private Currency(String theISOCode) {
        isoCode = theISOCode;
    }

    /**
     * Internal function to look up currency data.  Result is an array of
     * two Integers.  The first is the fraction digits.  The second is the
     * rounding increment, or 0 if none.  The rounding increment is in
     * units of 10^(-fraction_digits).
     */
    private Integer[] findData() {

        try {
            // Get CurrencyMeta resource out of root locale file.  [This may
            // move out of the root locale file later; if it does, update this
            // code.]
            ResourceBundle root = ICULocaleData.getLocaleElements("");

            Object[][] currencyMeta = (Object[][]) root.getObject("CurrencyMeta");

            Integer[] i = null;
            int defaultPos = -1;

            // Do a linear search for isoCode.  At the same time,
            // record the position of the DEFAULT meta data.  If the
            // meta data becomes large, make this faster.
            for (int j=0; j<currencyMeta.length; ++j) {
                Object[] row = currencyMeta[j];
                String s = (String) row[0];
                int c = isoCode.compareToIgnoreCase(s);
                if (c == 0) {
                    i = (Integer[]) row[1];
                    break;
                }
                if ("DEFAULT".equalsIgnoreCase(s)) {
                    defaultPos = j;
                }
                if (c < 0 && defaultPos >= 0) {
                    break;
                }
            }

            if (i == null && defaultPos >= 0) {
                i = (Integer[]) currencyMeta[defaultPos][1];
            }

            if (i != null && i.length >= 2) {
                return i;
            }
        }
        catch (MissingResourceException e) {}

        // Config/build error; return hard-coded defaults
        return LAST_RESORT_DATA;
    }

    // Default currency meta data of last resort.  We try to use the
    // defaults encoded in the meta data resource bundle.  If there is a
    // configuration/build error and these are not available, we use these
    // hard-coded defaults (which should be identical).
    private static final Integer[] LAST_RESORT_DATA =
        new Integer[] { new Integer(2), new Integer(0) };

    // POW10[i] = 10^i
    private static final int[] POW10 = { 1, 10, 100, 1000, 10000, 100000,
                                1000000, 10000000, 100000000, 1000000000 };
}

//eof
