// ***************************************************************************************************************************
// * 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.juneau.utils;

import static org.apache.juneau.internal.StringUtils.*;
import static org.apache.juneau.internal.ThrowableUtils.*;

import java.text.*;
import java.util.*;
import java.util.concurrent.*;

import org.apache.juneau.*;

/**
 * Wraps a {@link ResourceBundle} to provide some useful additional functionality.
 *
 * <ul class='spaced-list'>
 * 	<li>
 * 		Instead of throwing {@link MissingResourceException}, the {@link #getString(String)} method
 * 		will return <js>"{!!key}"</js> if the bundle was not found, and <js>"{!key}"</js> if bundle
 * 		was found but the key is not in the bundle.
 * 	<li>
 * 		A client locale can be set as a {@link ThreadLocal} object using the static {@link #setClientLocale(Locale)}
 * 		so that client localized messages can be retrieved using the {@link #getClientString(String, Object...)}
 * 		method on all instances of this class.
 * 	<li>
 * 		Resource bundles on parent classes can be added to the search path for this class by using the
 * 		{@link #addSearchPath(Class, String)} method.
 * 		This allows messages to be retrieved from the resource bundles of parent classes.
 * 	<li>
 * 		Locale-specific bundles can be retrieved by using the {@link #getBundle(Locale)} method.
 * 	<li>
 * 		The {@link #getString(Locale, String, Object...)} method can be used to retrieve locale-specific messages.
 * 	<li>
 * 		Messages in the resource bundle can optionally be prefixed with the simple class name.
 * 		For example, if the class is <c>MyClass</c> and the properties file contains <js>"MyClass.myMessage"</js>,
 * 		the message can be retrieved using <code>getString(<js>"myMessage"</js>)</code>.
 * </ul>
 *
 * <ul class='notes'>
 * 	<li>
 * 		This class is thread-safe.
 * </ul>
 */
public class MessageBundle extends ResourceBundle {

	private static final ThreadLocal<Locale> clientLocale = new ThreadLocal<>();

	private final ResourceBundle rb;
	private final String bundlePath, className;
	private final Class<?> forClass;
	private final long creationThreadId;

	// A map that contains all keys [shortKeyName->keyName] and [keyName->keyName], where shortKeyName
	// refers to keys prefixed and stripped of the class name (e.g. "foobar"->"MyClass.foobar")
	private final Map<String,String> keyMap = new ConcurrentHashMap<>();

	// Contains all keys present in all bundles in searchBundles.
	private final ConcurrentSkipListSet<String> allKeys = new ConcurrentSkipListSet<>();

	// Bundles to search through to find properties.
	// Typically this will be a list of resource bundles for each class up the class hierarchy chain.
	private final CopyOnWriteArrayList<MessageBundle> searchBundles = new CopyOnWriteArrayList<>();

	// Cache of message bundles per locale.
	private final ConcurrentHashMap<Locale,MessageBundle> localizedBundles = new ConcurrentHashMap<>();

	/**
	 * Sets the locale for this thread so that calls to {@link #getClientString(String, Object...)} return messages in
	 * that locale.
	 *
	 * @param locale The new client locale.
	 */
	public static void setClientLocale(Locale locale) {
		MessageBundle.clientLocale.set(locale);
	}

	/**
	 * Constructor.
	 *
	 * <p>
	 * When this method is used, the bundle path is determined by searching for the resource bundle
	 * in the following locations:
	 * <ul>
	 * 	<li><c>[package].ForClass.properties</c>
	 * 	<li><c>[package].nls.ForClass.properties</c>
	 * 	<li><c>[package].i18n.ForClass.properties</c>
	 * </ul>
	 *
	 * @param forClass The class
	 * @return A new message bundle belonging to the class.
	 */
	public static final MessageBundle create(Class<?> forClass) {
		return create(forClass, findBundlePath(forClass));
	}

	/**
	 * Constructor.
	 *
	 * <p>
	 * A shortcut for calling <c>new MessageBundle(forClass, bundlePath)</c>.
	 *
	 * @param forClass The class
	 * @param bundlePath The location of the resource bundle.
	 * @return A new message bundle belonging to the class.
	 */
	public static final MessageBundle create(Class<?> forClass, String bundlePath) {
		return new MessageBundle(forClass, bundlePath);
	}

	private static final String findBundlePath(Class<?> forClass) {
		String path = forClass.getName();
		if (tryBundlePath(forClass, path))
			return path;
		path = forClass.getPackage().getName() + ".nls." + forClass.getSimpleName();
		if (tryBundlePath(forClass, path))
			return path;
		path = forClass.getPackage().getName() + ".i18n." + forClass.getSimpleName();
		if (tryBundlePath(forClass, path))
			return path;
		return null;
	}

	private static final boolean tryBundlePath(Class<?> c, String path) {
		try {
			path = c.getName();
			ResourceBundle.getBundle(path, Locale.getDefault(), c.getClassLoader());
			return true;
		} catch (MissingResourceException e) {
			return false;
		}
	}

	/**
	 * Constructor.
	 *
	 * @param forClass The class using this resource bundle.
	 * @param bundlePath
	 * 	The path of the resource bundle to wrap.
	 * 	This can be an absolute path (e.g. <js>"com.foo.MyMessages"</js>) or a path relative to the package of the
	 * 	<l>forClass</l> (e.g. <js>"MyMessages"</js> if <l>forClass</l> is <js>"com.foo.MyClass"</js>).
	 */
	public MessageBundle(Class<?> forClass, String bundlePath) {
		this(forClass, bundlePath, Locale.getDefault());
	}

	private MessageBundle(Class<?> forClass, String bundlePath, Locale locale) {
		this.forClass = forClass;
		this.className = forClass.getSimpleName();
		if (bundlePath == null)
			throw new RuntimeException("Bundle path was null.");
		if (bundlePath.endsWith(".properties"))
			throw new RuntimeException("Bundle path should not end with '.properties'");
		this.bundlePath = bundlePath;
		this.creationThreadId = Thread.currentThread().getId();
		ClassLoader cl = forClass.getClassLoader();
		ResourceBundle trb = null;
		try {
			trb = ResourceBundle.getBundle(bundlePath, locale, cl);
		} catch (MissingResourceException e) {
			try {
				trb = ResourceBundle.getBundle(forClass.getPackage().getName() + '.' + bundlePath, locale, cl);
			} catch (MissingResourceException e2) {
			}
		}
		this.rb = trb;
		if (rb != null) {

			// Populate keyMap with original mappings.
			for (Enumeration<String> e = getKeys(); e.hasMoreElements();) {
				String key = e.nextElement();
				keyMap.put(key, key);
			}

			// Override/augment with shortname mappings (e.g. "foobar"->"MyClass.foobar")
			String c = className + '.';
			for (Enumeration<String> e = getKeys(); e.hasMoreElements();) {
				String key = e.nextElement();
				if (key.startsWith(c)) {
					String shortKey = key.substring(className.length() + 1);
					keyMap.put(shortKey, key);
				}
			}

			allKeys.addAll(keyMap.keySet());
		}
		searchBundles.add(this);
	}


	/**
	 * Add another bundle path to this resource bundle.
	 *
	 * <p>
	 * Order of property lookup is first-to-last.
	 *
	 * <p>
	 * This method must be called from the same thread as the call to the constructor.
	 * This eliminates the need for synchronization.
	 *
	 * @param forClass The class using this resource bundle.
	 * @param bundlePath The bundle path.
	 * @return This object (for method chaining).
	 */
	public MessageBundle addSearchPath(Class<?> forClass, String bundlePath) {
		assertSameThread(creationThreadId, "This method can only be called from the same thread that created the object.");
		MessageBundle srb = new MessageBundle(forClass, bundlePath);
		if (srb.rb != null) {
			allKeys.addAll(srb.keySet());
			searchBundles.add(srb);
		}
		return this;
	}

	@Override /* ResourceBundle */
	public boolean containsKey(String key) {
		return allKeys.contains(key);
	}

	/**
	 * Similar to {@link ResourceBundle#getString(String)} except allows you to pass in {@link MessageFormat} objects.
	 *
	 * @param key The resource bundle key.
	 * @param args Optional {@link MessageFormat}-style arguments.
	 * @return
	 * 	The resolved value.  Never <jk>null</jk>.
	 * 	<js>"{!!key}"</js> if the bundle is missing.
	 * 	<js>"{!key}"</js> if the key is missing.
	 */
	public String getString(String key, Object...args) {
		String s = getString(key);
		if (s.length() > 0 && s.charAt(0) == '{')
			return s;
		return format(s, args);
	}

	/**
	 * Same as {@link #getString(String, Object...)} but allows you to specify the locale.
	 *
	 * @param locale The locale of the resource bundle to retrieve message from.
	 * @param key The resource bundle key.
	 * @param args Optional {@link MessageFormat}-style arguments.
	 * @return
	 * 	The resolved value.  Never <jk>null</jk>.
	 * 	<js>"{!!key}"</js> if the bundle is missing.
	 * 	<js>"{!key}"</js> if the key is missing.
	 */
	public String getString(Locale locale, String key, Object...args) {
		if (locale == null)
			return getString(key, args);
		return getBundle(locale).getString(key, args);
	}

	/**
	 * Same as {@link #getString(String, Object...)} but uses the locale specified on the call to {@link #setClientLocale(Locale)}.
	 *
	 * @param key The resource bundle key.
	 * @param args Optional {@link MessageFormat}-style arguments.
	 * @return
	 * 	The resolved value.  Never <jk>null</jk>.
	 * 	<js>"{!!key}"</js> if the bundle is missing.
	 * 	<js>"{!key}"</js> if the key is missing.
	 */
	public String getClientString(String key, Object...args) {
		return getString(clientLocale.get(), key, args);
	}

	/**
	 * Looks for all the specified keys in the resource bundle and returns the first value that exists.
	 *
	 * @param keys The list of possible keys.
	 * @return The resolved value, or <jk>null</jk> if no value is found or the resource bundle is missing.
	 */
	public String findFirstString(String...keys) {
		if (rb == null)
			return null;
		for (String k : keys) {
			if (containsKey(k))
				return getString(k);
		}
		return null;
	}

	/**
	 * Same as {@link #findFirstString(String...)}, but uses the specified locale.
	 *
	 * @param locale The locale of the resource bundle to retrieve message from.
	 * @param keys The list of possible keys.
	 * @return The resolved value, or <jk>null</jk> if no value is found or the resource bundle is missing.
	 */
	public String findFirstString(Locale locale, String...keys) {
		MessageBundle srb = getBundle(locale);
		return srb.findFirstString(keys);
	}

	@Override /* ResourceBundle */
	public Set<String> keySet() {
		return Collections.unmodifiableSet(allKeys);
	}

	/**
	 * Returns all keys in this resource bundle with the specified prefix.
	 *
	 * @param prefix The prefix.
	 * @return The set of all keys in the resource bundle with the prefix.
	 */
	public Set<String> keySet(String prefix) {
		Set<String> set = new HashSet<>();
		for (String s : keySet()) {
			if (s.equals(prefix) || (s.startsWith(prefix) && s.charAt(prefix.length()) == '.'))
				set.add(s);
		}
		return set;
	}

	@Override /* ResourceBundle */
	public Enumeration<String> getKeys() {
		if (rb == null)
			return new Vector<String>(0).elements();
		return rb.getKeys();
	}

	@Override /* ResourceBundle */
	protected Object handleGetObject(String key) {
		for (MessageBundle srb : searchBundles) {
			if (srb.rb != null) {
				String key2 = srb.keyMap.get(key);
				if (key2 != null) {
					try {
						return srb.rb.getObject(key2);
					} catch (Exception e) {
						return "{!"+key+"}";
					}
				}
			}
		}
		if (rb == null)
			return "{!!"+key+"}";
		return "{!"+key+"}";
	}

	/**
	 * Returns this resource bundle as an {@link ObjectMap}.
	 *
	 * <p>
	 * Useful for debugging purposes.
	 * Note that any class that implements a <c>swap()</c> method will automatically be serialized by
	 * calling this method and serializing the result.
	 *
	 * <p>
	 * This method always constructs a new {@link ObjectMap} on each call.
	 *
	 * @return A new map containing all the keys and values in this bundle.
	 */
	public ObjectMap swap() {
		ObjectMap om = new ObjectMap();
		for (String k : allKeys)
			om.put(k, getString(k));
		return om;
	}

	/**
	 * Returns the resource bundle for the specified locale.
	 *
	 * @param locale The client locale.
	 * @return The resource bundle for the specified locale.  Never <jk>null</jk>.
	 */
	public MessageBundle getBundle(Locale locale) {
		MessageBundle mb = localizedBundles.get(locale);
		if (mb != null)
			return mb;
		mb = new MessageBundle(forClass, bundlePath, locale);
		List<MessageBundle> l = new ArrayList<>(searchBundles.size()-1);
		for (int i = 1; i < searchBundles.size(); i++) {
			MessageBundle srb = searchBundles.get(i);
			srb = new MessageBundle(srb.forClass, srb.bundlePath, locale);
			l.add(srb);
			mb.allKeys.addAll(srb.keySet());
		}
		mb.searchBundles.addAll(l);
		localizedBundles.putIfAbsent(locale, mb);
		return localizedBundles.get(locale);
	}
}