/*
 * 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.
 */
package org.apache.click.util;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.ServletContext;

import org.apache.click.Context;
import org.apache.click.service.ConfigService;
import org.apache.commons.lang.Validate;

/**
 * Provides a localized read only messages Map for Page and Control classes.
 * <p/>
 * A MessagesMap instance is available in each Velocity page using the name
 * "<span class="blue">messages</span>".
 * <p/>
 * For example suppose you have a localized page title, which is stored in the
 * Page's properties file. You can access page "title" message in your page
 * template via:
 *
 * <pre class="codeHtml">
 * <span class="blue">$messages.title</span> </pre>
 *
 * This is roughly equivalent to making the call:
 *
 * <pre class="codeJava">
 * <span class="kw">public void</span> onInit() {
 *    ..
 *    addModel(<span class="st">"title"</span>, getMessage(<span class="st">"title"</span>);
 * } </pre>
 *
 * Please note if the specified message does not exist in your Page's
 * properties file, or if the Page does not have a properties file, then
 * a <tt>MissingResourceException</tt> will be thrown.
 * <p/>
 * The ClickServlet adds a MessagesMap instance to the Velocity Context before
 * it is merged with the page template.
 */
public class MessagesMap implements Map<String, String> {

    /** Cache of resource bundle and locales which were not found, with support for multiple class loaders. */
    private static final ClassLoaderCache<Set<String>> NOT_FOUND_CLASSLOADER_CACHE
        = new ClassLoaderCache<Set<String>>();

    /** Provides a synchronized cache of get value reflection methods, with support for multiple class loaders. */
    protected static final ClassLoaderCache<Map<CacheKey, Map<String, String>>> MESSAGES_CLASSLOADER_CACHE
        = new ClassLoaderCache<Map<CacheKey, Map<String, String>>>();

    /** The cache key set load lock. */
    protected static final Object CACHE_LOAD_LOCK = new Object();

    // ----------------------------------------------------- Instance Variables

    /** The base class. */
    protected final Class<?> baseClass;

    /** The class global resource bundle base name. */
    protected final String globalBaseName;

    /** The map of localized messages. */
    protected Map<String, String> messages;

    /** The resource bundle locale. */
    protected final Locale locale;

    // ----------------------------------------------------------- Constructors

    /**
     * Create a resource bundle messages <tt>Map</tt> adaptor for the given
     * object's class resource bundle, the global resource bundle and
     * <tt>Context</tt>.
     * <p/>
     * Messages located in the object's resource bundle will override any
     * messages defined in the global resource bundle.
     *
     * @param baseClass the target class
     * @param globalResource the global resource bundle name
     */
    public MessagesMap(Class<?> baseClass, String globalResource) {
        this(baseClass, globalResource, Context.getThreadLocalContext().getLocale());
    }

    /**
     * Create a resource bundle messages <tt>Map</tt> adaptor for the given
     * object's class resource bundle, the global resource bundle and
     * <tt>Context</tt>.
     * <p/>
     * Messages located in the object's resource bundle will override any
     * messages defined in the global resource bundle.
     *
     * @param baseClass the target class
     * @param globalResource the global resource bundle name
     * @param locale the resource bundle locale.
     */
    public MessagesMap(Class<?> baseClass, String globalResource, Locale locale) {
        Validate.notNull(baseClass, "Null object parameter");

        this.baseClass = baseClass;
        this.globalBaseName = globalResource;
        this.locale = locale;
    }

    // --------------------------------------------------------- Public Methods

    /**
     * @see java.util.Map#size()
     */
    public int size() {
        ensureInitialized();
        return messages.size();
    }

    /**
     * @see java.util.Map#isEmpty()
     */
    public boolean isEmpty() {
        ensureInitialized();
        return messages.isEmpty();
    }

    /**
     * @see java.util.Map#containsKey(Object)
     */
    public boolean containsKey(Object key) {
        if (key != null) {
            ensureInitialized();
            return messages.containsKey(key.toString());
        }
        return false;
    }

    /**
     * @see java.util.Map#containsValue(Object)
     */
    public boolean containsValue(Object value) {
        ensureInitialized();
        return messages.containsValue(value);
    }

    /**
     * Return localized resource message for the given key. If the message is
     * not found a <tt>MissingResourceException</tt> will be thrown.
     *
     * @see java.util.Map#get(Object)
     * @throws MissingResourceException if the given key was not found
     */
    public String get(Object key) {
        String value = null;
        if (key != null) {
            ensureInitialized();
            value = messages.get(key.toString());
        }

        if (value == null) {
            String msg = "Message \"{0}\" not found in bundle \"{1}\" for locale \"{2}\"";
            String keyStr = (key != null) ? key.toString() : null;
            Object[] args = { keyStr, baseClass.getName(), locale };
            msg = MessageFormat.format(msg, args);
            throw new MissingResourceException(msg, baseClass.getName(), keyStr);
        }
        return value;
    }

    /**
     * This method is not supported and will throw
     * <tt>UnsupportedOperationException</tt> if invoked.
     *
     * @see java.util.Map#put(Object, Object)
     */
    public String put(String key, String value) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not supported and will throw
     * <tt>UnsupportedOperationException</tt> if invoked.
     *
     * @see java.util.Map#remove(Object)
     */
    public String remove(Object key) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not supported and will throw
     * <tt>UnsupportedOperationException</tt> if invoked.
     *
     * @see java.util.Map#putAll(Map)
     */
    public void putAll(Map<? extends String, ? extends String> map) {
        throw new UnsupportedOperationException();
    }

    /**
     * This method is not supported and will throw
     * <tt>UnsupportedOperationException</tt> if invoked.
     *
     * @see java.util.Map#clear()
     */
    public void clear() {
        throw new UnsupportedOperationException();
    }

    /**
     * @see java.util.Map#keySet()
     */
    public Set<String> keySet() {
        ensureInitialized();
        return messages.keySet();
    }

    /**
     * @see java.util.Map#values()
     */
    public Collection<String> values() {
        ensureInitialized();
        return messages.values();
    }

    /**
     * @see java.util.Map#entrySet()
     */
    public Set<Map.Entry<String, String>> entrySet() {
        ensureInitialized();
        return messages.entrySet();
    }

    /**
     * @see #toString()
     */
    @Override
    public String toString() {
        ensureInitialized();
        return messages.toString();
    }

    // ------------------------------------------------------ Protected Methods

    /**
     * Return the ResourceBundle for the given resource name and locale. By
     * default this method will create a ResourceBundle using the standard JDK
     * method: {@link java.util.ResourceBundle#getBundle(java.lang.String, java.util.Locale, java.lang.ClassLoader)}.
     * <p/>
     * You can create your own custom ResourceBundle by overriding this method.
     * <p/>
     * In order for Click to use your custom MessagesMap implementation, you
     * need to provide your own {@link org.apache.click.service.MessagesMapService}
     * or extend {@link org.apache.click.service.DefaultMessagesMapService}.
     * <p/>
     * The method {@link org.apache.click.service.MessagesMapService#createMessagesMap(java.lang.Class, java.lang.String, java.util.Locale)  createMessagesMap},
     * can be implemented to return your custom MessagesMap instances.
     *
     * @param resourceName the resource bundle name
     * @param locale the resource bundle locale.
     *
     * @return the ResourceBundle for the given resource name and locale
     */
    protected ResourceBundle createResourceBundle(String resourceName, Locale locale) {
        return ClickUtils.getBundle(resourceName, locale);
    }

    /**
     * This method initializes and populates the internal{@link #messages} map
     * and {@link #MESSAGES_CACHE} if it is not already initialized.
     * <p/>
     * <b>Please Note:</b> populating {@link #MESSAGES_CACHE} is not thread safe
     * and access to the cache must be properly synchronized.
     */
    protected void ensureInitialized() {
        if (messages == null) {

            CacheKey resourceKey = new CacheKey(globalBaseName,
                baseClass.getName(), locale.toString());

            messages = getMessagesCache().get(resourceKey);

            if (messages != null) {
                return;
            }

            messages = new HashMap<String, String>();

            synchronized (CACHE_LOAD_LOCK) {

                loadResourceValuesIntoMap(globalBaseName, messages);

                List<String> classnameList = new ArrayList<String>();

                // Build class list
                Class<?> aClass = baseClass;
                while (!aClass.getName().equals("java.lang.Object")) {
                    classnameList.add(aClass.getName());
                    aClass = aClass.getSuperclass();
                }

                // Load messages from parent to child order, so that child
                // class messages override parent messages.
                for (int i = classnameList.size() - 1; i >= 0; i--) {
                    String className = classnameList.get(i);
                    loadResourceValuesIntoMap(className, messages);
                }

                messages = Collections.unmodifiableMap(messages);

                ServletContext servletContext = Context.getThreadLocalContext().getServletContext();
                ConfigService configService = ClickUtils.getConfigService(servletContext);
                if (configService.isProductionMode() || configService.isProfileMode()) {
                    getMessagesCache().put(resourceKey, messages);
                }
            }
        }
    }

    /**
     * Load the values of the given resourceBundleName into the map.
     *
     * @param resourceBundleName the resource bundle name
     * @param map the map to load resource values into
     */
    protected void loadResourceValuesIntoMap(String resourceBundleName, Map<String, String> map) {
        if (resourceBundleName == null) {
            return;
        }

        String resourceKey = resourceBundleName + locale.toString();

        if (!getNotFoundCache().contains(resourceKey)) {
            try {
                ResourceBundle resources = createResourceBundle(resourceBundleName, locale);

                Enumeration<String> e = resources.getKeys();
                while (e.hasMoreElements()) {
                    String name = e.nextElement();
                    String value = resources.getString(name);
                    map.put(name, value);
                }

            } catch (MissingResourceException mre) {
                getNotFoundCache().add(resourceKey);
            }
        }
    }

    // Private Methods --------------------------------------------------------

    protected static Set<String> getNotFoundCache() {
        Set<String> notFoundCache = NOT_FOUND_CLASSLOADER_CACHE.get();
        if (notFoundCache == null) {
            notFoundCache = new HashSet<String>();
            NOT_FOUND_CLASSLOADER_CACHE.put(notFoundCache);
        }

        return notFoundCache;
    }

    protected static Map<CacheKey, Map<String, String>> getMessagesCache() {
        Map<CacheKey, Map<String, String>> messagesCache = MESSAGES_CLASSLOADER_CACHE.get();
        if (messagesCache == null) {
            messagesCache = new ConcurrentHashMap<CacheKey, Map<String, String>>();
            MESSAGES_CLASSLOADER_CACHE.put(messagesCache);
        }

        return messagesCache;
    }

    /**
     * See DRY Performance article by Kirk Pepperdine.
     * <p/>
     * http://www.javaspecialists.eu/archive/Issue134.html
     */
    private static class CacheKey {

        /** Global base name to encapsulate in cache key. */
        private final String globalBaseName;

        /** Base class name to encapsulate in cache key. */
        private final String baseClass;

        /** Locale to encapsulate in cache key. */
        private final String locale;

        /**
         * Constructs a new CacheKey for the given baseName, baseClass and
         * locale.
         *
         * @param globalBaseName the base name to build the cache key for
         * @param baseClass the base class name to build the cache key for
         * @param locale the request locale to build the cache key for
         */
        public CacheKey(String globalBaseName, String baseClass, String locale) {
            if (globalBaseName == null) {
                throw new IllegalArgumentException("Null globalBaseName parameter");
            }
            if (baseClass == null) {
                throw new IllegalArgumentException("Null baseClass parameter");
            }
            if (locale == null) {
                throw new IllegalArgumentException("Null locale parameter");
            }
            this.globalBaseName = globalBaseName;
            this.baseClass = baseClass;
            this.locale = locale;
        }

        /**
         * @see Object#equals(Object)
         *
         * @param o the object with which to compare this instance with
         * @return true if the specified object is the same as this object
         */
        @Override
        public final boolean equals(Object o) {
            if (this == o) {
                return true;
            }
            if (!(o instanceof CacheKey)) {
                return false;
            }

            CacheKey that = (CacheKey) o;

            if (!globalBaseName.equals(that.globalBaseName)) {
                return false;
            }

            if (!baseClass.equals(that.baseClass)) {
                return false;
            }

            if (!locale.equals(that.locale)) {
                return false;
            }

            return true;
        }

        /**
         * @see Object#hashCode()
         *
         * @return a hash code value for this object.
         */
        @Override
        public final int hashCode() {
            return globalBaseName.hashCode()
                * 31 + baseClass.hashCode()
                * 31 + locale.hashCode();
        }
    }
}
