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.lang3.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>
 *
 * <pre>
 * <code>
 * SimpleLocalizationService ls = (SimpleLocalizationService) TurbineServices
 *     .getInstance().getService(SimpleLocalizationService.SERVICE_NAME);
 * </code>
 * </pre>
 *
 * <p>
 * Then call {@link #getString(String, Locale, String)}, or one of
 * two methods to retrieve a ResourceBundle:
 * </p>
 *
 * <ul>
 * <li>getBundle("MyBundleName")</li>
 * <li>getBundle("MyBundleName", Locale)</li>
 * <li>etc.</li>
 * </ul>
 *
 * @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<String, HashMap<Locale, ResourceBundle>> bundles = null;
    
    /**
     * The list of default bundles to search.
     */
    private String[] bundleNames = 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 = null;
    
    /** The name of the default country to use. */
    private String defaultCountry = null;

    /**
     * Creates a new instance.
     */
    public SimpleLocalizationServiceImpl()
    {
        bundles = new HashMap<String, HashMap<Locale, ResourceBundle>>();
    }

    /**
     * Avalon lifecycle method
     * 
     * {@link org.apache.avalon.framework.configuration.Configurable}
     * 
     * @param conf the configuration
     * @throws ConfigurationException if failed to configure
     */
    @Override
	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.
     * 
     * @throws Exception generic exception
     */
    @Override
	public void initialize() throws Exception
    {
        defaultLocale = new Locale(defaultLanguage, defaultCountry);
        if (getLogger().isInfoEnabled())
        {
            getLogger().info("Localization Service is Initialized now..");
        }
    }
    
    /**
     * Initialize list of default bundle names.
     *
     * @param intBundleNames set bundle names
     */
    protected void initBundleNames(String[] intBundleNames)
    {
        if (intBundleNames == null)
            bundleNames = new String[0];
        else
        	bundleNames = intBundleNames;
    }
    
    /**
     * Retrieves the default language (specified in the config file).
     * 
     * @return the default language
     */
    @Override
	public String getDefaultLanguage()
    {
        return defaultLanguage;
    }
    
    /**
     * Retrieves the default country (specified in the config file).
     * 
     * @return the default country
     */
    @Override
	public String getDefaultCountry()
    {
        return defaultCountry;
    }
    
    /**
     * Retrieves the default Locale (as created from default
     * language and default country).
     * 
     * @return the default locale
     */
    @Override
	public Locale getDefaultLocale()
    {
        return defaultLocale;
    }

    /**
     * {@link org.apache.fulcrum.localization.SimpleLocalizationService#getDefaultBundleName()}
     * 
     * @return the default bundle name
     */
    @Override
	public String getDefaultBundleName()
    {
        return (bundleNames.length > 0 ? bundleNames[0] : "");
    }
    
    /**
     * {@link org.apache.fulcrum.localization.SimpleLocalizationService#getBundleNames()}
     * 
     * @return list of bundle names available
     */
    @Override
	public String[] getBundleNames()
    {
        return bundleNames.clone();
    }
    
    /**
     * @see org.apache.fulcrum.localization.SimpleLocalizationService#getBundle()
     * 
     * @return the default resource bundle
     */
    @Override
	public ResourceBundle getBundle()
    {
        return getBundle(getDefaultBundleName(), (Locale) null);
    }
    
    /**
     * @see org.apache.fulcrum.localization.SimpleLocalizationService#getBundle(java.lang.String)
     * 
     * @param bundleName the name of a bundle
     * @return the resource bundle
     */
    @Override
	public ResourceBundle getBundle(String bundleName)
    {
        return getBundle(bundleName, (Locale) null);
    }
    
    /**
     * @see org.apache.fulcrum.localization.SimpleLocalizationService#getBundle(java.lang.String, java.util.Locale)
     * 
     * 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.
     */
    @Override
	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.
     *
     * @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).
     * @throws MissingResourceException Bundle not found.
     * @return a localized resource bundle
     */
    private synchronized ResourceBundle cacheBundle(
        String bundleName,
        Locale locale)
        throws MissingResourceException
    {
        HashMap<Locale, ResourceBundle> bundlesByLocale = (HashMap<Locale, ResourceBundle>) bundles.get(bundleName);
        ResourceBundle rb =
            (bundlesByLocale == null
                ? null
                : (ResourceBundle) bundlesByLocale.get(locale));
        if (rb == null)
        {
            bundlesByLocale =
                (bundlesByLocale == null
                    ? new HashMap<Locale, ResourceBundle>(3)
                    : new HashMap<Locale, ResourceBundle>(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<String, HashMap<Locale, ResourceBundle>> bundlesByName 
                	= new HashMap<String, HashMap<Locale, ResourceBundle>>(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>
     * 
     * @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).
     * @param bundleByLocale map of locales and resource bundles
     * @return a localized resource bundle
     * 
     */
    private ResourceBundle findBundleByLocale(
        String bundleName,
        Locale locale,
        Map<Locale, ResourceBundle> bundlesByLocale)
    {
        ResourceBundle rb = null;
        if (StringUtils.isEmpty(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.isEmpty(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>.
     * 
     * @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).
     */
    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.
     */
    @Override
	public void setBundle(String defaultBundle)
    {
        if (bundleNames.length > 0)
        {
            bundleNames[0] = defaultBundle;
        }
        else
        {
            synchronized (this)
            {
                if (bundleNames.length <= 0)
                {
                    bundleNames = new String[] { defaultBundle };
                }
            }
        }
    }
    
    /**
     * 
     * {@link org.apache.fulcrum.localization.SimpleLocalizationService#getString(String, Locale, String)}
     * @throws MissingResourceException Specified key cannot be matched.
     */
    @Override
	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.
     */
    @Override
	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>).
     * 
     * @param rb resource bundle 
     * @param key The key to retrieve the value for.
     * @return name of resource
     */
    protected final String getStringOrNull(ResourceBundle rb, String key)
    {
        if (rb != null)
        {
            try
            {
                return rb.getString(key);
            }
            catch (MissingResourceException ignored)
            {
                // ignore
            }
        }
        return null;
    }
    
    /**
     * {@link org.apache.fulcrum.localization.SimpleLocalizationService#format(String, Locale, String, Object)}
     * @param bundleName the bundle name
     * @param locale locale
     * @param key key to lookup
     * @param arg1 bundle arguments
     */
    @Override
	public String format(
        String bundleName,
        Locale locale,
        String key,
        Object arg1)
    {
        return format(bundleName, locale, key, new Object[] { arg1 });
    }
    
    /* (non-Javadoc)
     * @see org.apache.fulcrum.localization.SimpleLocalizationService#format(java.lang.String, java.util.Locale, java.lang.String, java.lang.Object, java.lang.Object)
     */
    @Override
	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>.
     * 
     * If <code>locale</code> is <code>null</code>, {@link #getDefaultLocale()} will be checked.
     * If <code>bundleName</code> is <code>null</code>, {@link #getDefaultBundleName()} will be checked (cft. {@link #getBundle(String, Locale)}.
     *
     * @return Localized, formatted text identified by
     * <code>key</code>.
     */
    @Override
	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);
    }
}
