package org.apache.fulcrum.localization;

/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import org.apache.avalon.framework.activity.Initializable;
import org.apache.avalon.framework.configuration.Configurable;
import org.apache.avalon.framework.configuration.Configuration;
import org.apache.avalon.framework.configuration.ConfigurationException;
import org.apache.avalon.framework.logger.AbstractLogEnabled;
import org.apache.commons.lang.StringUtils;

/**
 * <p>This class is the single point of access to all localization
 * resources.  It caches different ResourceBundles for different
 * Locales.</p>
 *
 * <p>Usage example:</p>
 *
 * <blockquote><code><pre>
 * SimpleLocalizationService ls = (SimpleLocalizationService) TurbineServices
 *     .getInstance().getService(SimpleLocalizationService.SERVICE_NAME);
 * </pre></code></blockquote>
 *
 * <p>Then call {@link #getString(String, Locale, String)}, or one of
 * two methods to retrieve a ResourceBundle:
 *
 * <ul>
 * <li>getBundle("MyBundleName")</li>
 * <li>getBundle("MyBundleName", Locale)</li>
 * <li>etc.</li>
 * </ul></p>
 *
 * @author <a href="mailto:jm@mediaphil.de">Jonas Maurus</a>
 * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
 * @author <a href="mailto:novalidemail@foo.com">Frank Y. Kim</a>
 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
 * @author <a href="mailto:leonardr@collab.net">Leonard Richardson</a>
 * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
 * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
 * @version $Id: DefaultLocalizationService.java 535465 2007-05-05 06:58:06Z tv $
 * @avalon.component name="localization" lifestyle="singleton"
 * @avalon.service type="org.apache.fulcrum.localization.SimpleLocalizationService"
 */
public class SimpleLocalizationServiceImpl
    extends AbstractLogEnabled
    implements SimpleLocalizationService, Configurable, Initializable
{
    /** Key Prefix for our bundles */
    private static final String BUNDLES = "bundles";
    /**
     * The value to pass to <code>MessageFormat</code> if a
     * <code>null</code> reference is passed to <code>format()</code>.
     */
    private static final Object[] NO_ARGS = new Object[0];
    /**
     * Bundle name keys a HashMap of the ResourceBundles in this
     * service (which is in turn keyed by Locale).
     */
    private HashMap bundles = null;
    /**
     * The list of default bundles to search.
     */
    private String[] bundleNames = null;
    /**
     * The default bundle name to use if not specified.
     */
    private String defaultBundleName = null;
    /**
     * The name of the default locale to use (includes language and
     * country).
     */
    private Locale defaultLocale = null;
    /** The name of the default language to use. */
    private String defaultLanguage;
    /** The name of the default country to use. */
    private String defaultCountry = null;

    /**
     * Creates a new instance.
     */
    public SimpleLocalizationServiceImpl()
    {
        bundles = new HashMap();
    }

    /**
     * Avalon lifecycle method
     * 
     * @see {@link Configurable}
     */
    public void configure(Configuration conf) throws ConfigurationException
    {
        Locale jvmDefault = Locale.getDefault();
        defaultLanguage =
            conf
                .getAttribute(
                    "locale-default-language",
                    jvmDefault.getLanguage())
                .trim();
        defaultCountry =
            conf
                .getAttribute("locale-default-country", jvmDefault.getCountry())
                .trim();
        // FIXME! need to add bundle names
        getLogger().info(
            "initialized lang="
                + defaultLanguage
                + " country="
                + defaultCountry);
        final Configuration bundles = conf.getChild(BUNDLES, false);
        if (bundles != null)
        {
            Configuration[] nameVal = bundles.getChildren();
            String bundleName[] = new String[nameVal.length];
            for (int i = 0; i < nameVal.length; i++)
            {
                String val = nameVal[i].getValue();
                getLogger().debug("Registered bundle " + val);
                bundleName[i] = val;
            }
            initBundleNames(bundleName);
        }
    }
    
    /**
     * Called the first time the Service is used.
     */
    public void initialize() throws Exception
    {
        // initBundleNames(null);
        defaultLocale = new Locale(defaultLanguage, defaultCountry);
        if (getLogger().isInfoEnabled())
        {
            getLogger().info("Localization Service is Initialized now..");
        }
    }
    
    /**
     * Initialize list of default bundle names.
     *
     * @param ignored names Ignored.
     */
    protected void initBundleNames(String[] intBundleNames)
    {
        //System.err.println("cfg=" + getConfiguration());
        if (defaultBundleName != null && defaultBundleName.length() > 0)
        {
            // Using old-style single bundle name property.
            if (intBundleNames == null || intBundleNames.length <= 0)
            {
                bundleNames = new String[] { defaultBundleName };
            }
            else
            {
                // Prepend "default" bundle name.
                String[] array = new String[intBundleNames.length + 1];
                array[0] = defaultBundleName;
                System.arraycopy(
                    intBundleNames,
                    0,
                    array,
                    1,
                    intBundleNames.length);
                bundleNames = array;
            }
        }
        if (intBundleNames == null)
        {
            bundleNames = new String[0];
        }
        bundleNames = intBundleNames;
    }
    
    /**
     * Retrieves the default language (specified in the config file).
     */
    public String getDefaultLanguage()
    {
        return defaultLanguage;
    }
    
    /**
     * Retrieves the default country (specified in the config file).
     */
    public String getDefaultCountry()
    {
        return defaultCountry;
    }
    
    /**
     * Retrieves the default Locale (as created from default
     * language and default country).
     */
    public Locale getDefaultLocale()
    {
        return defaultLocale;
    }

    /**
     * @see org.apache.fulcrum.localization.SimpleLocalizationService#getDefaultBundleName()
     */
    public String getDefaultBundleName()
    {
        return (bundleNames.length > 0 ? bundleNames[0] : "");
    }
    
    /**
     * @see org.apache.fulcrum.localization.SimpleLocalizationService#getBundleNames()
     */
    public String[] getBundleNames()
    {
        return (String[]) bundleNames.clone();
    }
    
    /**
     * @see org.apache.fulcrum.localization.SimpleLocalizationService#getBundle()
     */
    public ResourceBundle getBundle()
    {
        return getBundle(getDefaultBundleName(), (Locale) null);
    }
    
    /**
     * @see org.apache.fulcrum.localization.SimpleLocalizationService#getBundle(String)
     */
    public ResourceBundle getBundle(String bundleName)
    {
        return getBundle(bundleName, (Locale) null);
    }
    
    /**
     * This method returns a ResourceBundle for the given bundle name
     * and the given Locale.
     *
     * @param bundleName Name of bundle (or <code>null</code> for the
     * default bundle).
     * @param locale The locale (or <code>null</code> for the locale
     * indicated by the default language and country).
     * @return A localized ResourceBundle.
     */
    public ResourceBundle getBundle(String bundleName, Locale locale)
    {
        // Assure usable inputs.
        bundleName =
            (bundleName == null ? getDefaultBundleName() : bundleName.trim());
        if (locale == null)
        {
            locale = getDefaultLocale();
        }
        // Find/retrieve/cache bundle.
        ResourceBundle rb = null;
        HashMap bundlesByLocale = (HashMap) bundles.get(bundleName);
        if (bundlesByLocale != null)
        {
            // Cache of bundles by locale for the named bundle exists.
            // Check the cache for a bundle corresponding to locale.
            rb = (ResourceBundle) bundlesByLocale.get(locale);
            if (rb == null)
            {
                // Not yet cached.
                rb = cacheBundle(bundleName, locale);
            }
        }
        else
        {
            rb = cacheBundle(bundleName, locale);
        }
        return rb;
    }
    
    /**
     * Caches the named bundle for fast lookups.  This operation is
     * relatively expensive in terms of memory use, but is optimized
     * for run-time speed in the usual case.
     *
     * @exception MissingResourceException Bundle not found.
     */
    private synchronized ResourceBundle cacheBundle(
        String bundleName,
        Locale locale)
        throws MissingResourceException
    {
        HashMap bundlesByLocale = (HashMap) bundles.get(bundleName);
        ResourceBundle rb =
            (bundlesByLocale == null
                ? null
                : (ResourceBundle) bundlesByLocale.get(locale));
        if (rb == null)
        {
            bundlesByLocale =
                (bundlesByLocale == null
                    ? new HashMap(3)
                    : new HashMap(bundlesByLocale));
            try
            {
                rb = ResourceBundle.getBundle(bundleName, locale);
            }
            catch (MissingResourceException e)
            {
                rb = findBundleByLocale(bundleName, locale, bundlesByLocale);
                if (rb == null)
                {
                    throw (MissingResourceException) e.fillInStackTrace();
                }
            }
            if (rb != null)
            {
                // Cache bundle.
                bundlesByLocale.put(rb.getLocale(), rb);
                HashMap bundlesByName = new HashMap(bundles);
                bundlesByName.put(bundleName, bundlesByLocale);
                this.bundles = bundlesByName;
            }
        }
        return rb;
    }
    
    /**
     * <p>Retrieves the bundle most closely matching first against the
     * supplied inputs, then against the defaults.</p>
     *
     * <p>Use case: some clients send a HTTP Accept-Language header
     * with a value of only the language to use
     * (i.e. "Accept-Language: en"), and neglect to include a country.
     * When there is no bundle for the requested language, this method
     * can be called to try the default country (checking internally
     * to assure the requested criteria matches the default to avoid
     * disconnects between language and country).</p>
     *
     * <p>Since we're really just guessing at possible bundles to use,
     * we don't ever throw <code>MissingResourceException</code>.</p>
     */
    private ResourceBundle findBundleByLocale(
        String bundleName,
        Locale locale,
        Map bundlesByLocale)
    {
        ResourceBundle rb = null;
        if (!StringUtils.isNotEmpty(locale.getCountry())
            && defaultLanguage.equals(locale.getLanguage()))
        {
            /*
             *            category.debug("Requested language '" + locale.getLanguage() +
             *                           "' matches default: Attempting to guess bundle " +
             *                           "using default country '" + defaultCountry + '\'');
             */
            Locale withDefaultCountry =
                new Locale(locale.getLanguage(), defaultCountry);
            rb = (ResourceBundle) bundlesByLocale.get(withDefaultCountry);
            if (rb == null)
            {
                rb = getBundleIgnoreException(bundleName, withDefaultCountry);
            }
        }
        else if (
            !StringUtils.isNotEmpty(locale.getLanguage())
                && defaultCountry.equals(locale.getCountry()))
        {
            Locale withDefaultLanguage =
                new Locale(defaultLanguage, locale.getCountry());
            rb = (ResourceBundle) bundlesByLocale.get(withDefaultLanguage);
            if (rb == null)
            {
                rb = getBundleIgnoreException(bundleName, withDefaultLanguage);
            }
        }
        if (rb == null && !defaultLocale.equals(locale))
        {
            rb = getBundleIgnoreException(bundleName, defaultLocale);
        }
        return rb;
    }
    
    /**
     * Retrieves the bundle using the
     * <code>ResourceBundle.getBundle(String, Locale)</code> method,
     * returning <code>null</code> instead of throwing
     * <code>MissingResourceException</code>.
     */
    private final ResourceBundle getBundleIgnoreException(
        String bundleName,
        Locale locale)
    {
        try
        {
            return ResourceBundle.getBundle(bundleName, locale);
        }
        catch (MissingResourceException ignored)
        {
            return null;
        }
    }
    
    /**
     * This method sets the name of the first bundle in the search
     * list (the "default" bundle).
     *
     * @param defaultBundle Name of default bundle.
     */
    public void setBundle(String defaultBundle)
    {
        if (bundleNames.length > 0)
        {
            bundleNames[0] = defaultBundle;
        }
        else
        {
            synchronized (this)
            {
                if (bundleNames.length <= 0)
                {
                    bundleNames = new String[] { defaultBundle };
                }
            }
        }
    }
    
    /**
     * @exception MissingResourceException Specified key cannot be matched.
     * @see org.apache.fulcrum.localization.SimpleLocalizationService#getString(String, Locale, String)
     */
    public String getString(String bundleName, Locale locale, String key)
      throws MissingResourceException
    {
        String value = null;
        if (locale == null)
        {
            locale = getDefaultLocale();
        }
        // Look for text in requested bundle.
        ResourceBundle rb = getBundle(bundleName, locale);
        value = getStringOrNull(rb, key);
        // Look for text in list of default bundles.
        if (value == null && bundleNames.length > 0)
        {
            String name;
            for (int i = 0; i < bundleNames.length; i++)
            {
                name = bundleNames[i];
                //System.out.println("getString(): name=" + name +
                //                   ", locale=" + locale + ", i=" + i);
                if (!name.equals(bundleName))
                {
                    rb = getBundle(name, locale);
                    value = getStringOrNull(rb, key);
                    if (value != null)
                    {
                        locale = rb.getLocale();
                        break;
                    }
                }
            }
        }
        if (value == null)
        {
            String loc = locale.toString();
            String mesg =
                LocalizationService.SERVICE_NAME
                    + " noticed missing resource: "
                    + "bundleName="
                    + bundleName
                    + ", locale="
                    + loc
                    + ", key="
                    + key;
            getLogger().debug(mesg);
            // Text not found in requested or default bundles.
            throw new MissingResourceException(mesg, bundleName, key);
        }
        return value;
    }
    
    /**
     * Returns the value for the key in the default bundle and the default locale.
     * 
     * @param key The key to retrieve the value for.
     * @return The value mapped to the key.
     */
    public String getString(String key) {
    	return getString(getDefaultBundleName(), getDefaultLocale(), key);
    }
    
    
    /**
     * Gets localized text from a bundle if it's there.  Otherwise,
     * returns <code>null</code> (ignoring a possible
     * <code>MissingResourceException</code>).
     */
    protected final String getStringOrNull(ResourceBundle rb, String key)
    {
        if (rb != null)
        {
            try
            {
                return rb.getString(key);
            }
            catch (MissingResourceException ignored)
            {
                // ignore
            }
        }
        return null;
    }
    
    /**
     * @see org.apache.fulcrum.localization.SimpleLocalizationService#format(String, Locale, String, Object)
     */
    public String format(
        String bundleName,
        Locale locale,
        String key,
        Object arg1)
    {
        return format(bundleName, locale, key, new Object[] { arg1 });
    }
    
    /**
     * @see org.apache.fulcrum.localization.SimpleLocalizationService#format(String, Locale, String, Object, Object)
     */
    public String format(
        String bundleName,
        Locale locale,
        String key,
        Object arg1,
        Object arg2)
    {
        return format(bundleName, locale, key, new Object[] { arg1, arg2 });
    }
    
    /**
     * Looks up the value for <code>key</code> in the
     * <code>ResourceBundle</code> referenced by
     * <code>bundleName</code>, then formats that value for the
     * specified <code>Locale</code> using <code>args</code>.
     *
     * @return Localized, formatted text identified by
     * <code>key</code>.
     */
    public String format(
        String bundleName,
        Locale locale,
        String key,
        Object[] args)
    {
        // When formatting Date objects and such, MessageFormat
        // cannot have a null Locale.
        Locale formatLocale = (locale == null) ? getDefaultLocale() : locale; 
        String value = getString(bundleName, locale, key);
        
        Object[] formatArgs = (args == null) ? NO_ARGS : args;
        
        MessageFormat messageFormat = new MessageFormat(value, formatLocale);
        return messageFormat.format(formatArgs);
    }
}
