/*******************************************************************************
 * Copyright (c) 2011, 2018 BestSolution.at and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
 *     Dirk Fauth <dirk.fauth@googlemail.com> - modifications to instance creation
 *     Dirk Fauth <dirk.fauth@googlemail.com> - Bug 460308
 ******************************************************************************/
package org.eclipse.e4.core.internal.services;

import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.ResourceBundle;
import javax.annotation.PostConstruct;
import org.eclipse.e4.core.services.nls.IMessageFactoryService;
import org.eclipse.e4.core.services.nls.Message;
import org.eclipse.e4.core.services.nls.Message.ReferenceType;
import org.eclipse.e4.core.services.translation.ResourceBundleProvider;
import org.osgi.framework.Bundle;
import org.osgi.framework.FrameworkUtil;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.log.Logger;
import org.osgi.service.log.LoggerFactory;

@Component
public class MessageFactoryServiceImpl implements IMessageFactoryService {

	private LoggerFactory factory;
	private Logger logger;

	// Cache so when multiple instance use the same message class
	private Map<Object, Reference<Object>> SOFT_CACHE = Collections
			.synchronizedMap(new HashMap<Object, Reference<Object>>());

	private Map<Object, Reference<Object>> WEAK_CACHE = Collections
			.synchronizedMap(new HashMap<Object, Reference<Object>>());

	private int CLEANUPCOUNT = 0;

	@Override
	public <M> M getMessageInstance(final Locale locale, final Class<M> messages,
			final ResourceBundleProvider provider) {
		String key = messages.getName() + "_" + locale; //$NON-NLS-1$

		final Message annotation = messages.getAnnotation(Message.class);
		Map<Object, Reference<Object>> cache = null;
		ReferenceType type = ReferenceType.NONE;

		if (++CLEANUPCOUNT > 1000) {
			Iterator<Entry<Object, Reference<Object>>> it = WEAK_CACHE.entrySet().iterator();
			while (it.hasNext()) {
				if (it.next().getValue().get() == null) {
					it.remove();
				}
			}

			it = SOFT_CACHE.entrySet().iterator();
			while (it.hasNext()) {
				if (it.next().getValue().get() == null) {
					it.remove();
				}
			}
			CLEANUPCOUNT = 0;
		}

		if (annotation == null || annotation.referenceType() == ReferenceType.SOFT) {
			cache = SOFT_CACHE;
			type = ReferenceType.SOFT;
		} else if (annotation.referenceType() == ReferenceType.WEAK) {
			cache = WEAK_CACHE;
			type = ReferenceType.WEAK;
		}

		if (cache != null && cache.containsKey(key)) {
			@SuppressWarnings("unchecked")
			Reference<M> ref = (Reference<M>) cache.get(key);
			M o = ref.get();
			if (o != null) {
				return o;
			}
			cache.remove(key);
		}

		M instance;

		if (System.getSecurityManager() == null) {
			instance = createInstance(locale, messages, annotation, provider);
		} else {
			instance = AccessController.doPrivileged(new PrivilegedAction<M>() {

				@Override
				public M run() {
					return createInstance(locale, messages, annotation, provider);
				}

			});
		}

		if (cache != null) {
			if (type == ReferenceType.SOFT) {
				cache.put(key, new SoftReference<Object>(instance));
			} else if (type == ReferenceType.WEAK) {
				cache.put(key, new WeakReference<Object>(instance));
			}
		}

		return instance;
	}

	/**
	 * Creates and returns an instance of the of a given messages class for the given {@link Locale}
	 * . The message class gets instantiated and the fields are initialized with values out of a
	 * {@link ResourceBundle}. As there are several options to specify the location of the
	 * {@link ResourceBundle} to load, the following search order is used:
	 * <ol>
	 * <li>URI location<br/>
	 * If the message class is annotated with <code>@Message</code> and the <i>contributorURI</i>
	 * attribute is set, the {@link ResourceBundle} is searched at the specified location</li>
	 * <li>Relative location<br/>
	 * If the message class is not annotated with <code>@Message</code> and a contributorURI
	 * attribute value or there is no {@link ResourceBundle} found at the specified location, a
	 * {@link ResourceBundle} with the same name in the same package as the message class is
	 * searched.</li>
	 * <li>Bundle localization<br/>
	 * If there is no {@link ResourceBundle} found by URI or relative location, the OSGi
	 * {@link ResourceBundle} configured in the MANIFEST.MF is tried to load.</li>
	 * </ol>
	 * Note: Even if there is no {@link ResourceBundle} found in any of the mentioned locations,
	 * this method will not break. In this case the fields of the message class will get initialized
	 * with values that look like <code>!key!</code> to indicate that there is no translation value
	 * found for that key.
	 *
	 * @param locale
	 *            The {@link Locale} for which the message class instance is requested.
	 * @param messages
	 *            The type of the message class whose instance is requested.
	 * @param annotation
	 *            The annotation that is used in the message class. If specified it is needed to
	 *            retrieve the URI of the location to search for the {@link ResourceBundle}.
	 * @param rbProvider
	 *            The service that is needed to retrieve {@link ResourceBundle} objects from a
	 *            bundle with a given locale.
	 *
	 * @return The created instance of the given messages class and {@link Locale} or
	 *         <code>null</code> if an error occured on creating the instance.
	 */
	@SuppressWarnings("deprecation")
	private <M> M createInstance(Locale locale, Class<M> messages, Message annotation,
			ResourceBundleProvider rbProvider) {

		ResourceBundle resourceBundle = null;
		if (annotation != null) {
			if (annotation.contributionURI().length() > 0) {
				resourceBundle = ResourceBundleHelper.getResourceBundleForUri(
						annotation.contributionURI(), locale, rbProvider);
			} else if (annotation.contributorURI().length() > 0) {
				Logger log = this.logger;
				if (log != null) {
					log.warn(
							"Usage of @Message#contributorURI detected! Please use @Message#contributionURI instead!"); //$NON-NLS-1$
				}
				resourceBundle = ResourceBundleHelper.getResourceBundleForUri(
					annotation.contributorURI(), locale, rbProvider);
			}
		}

		if (resourceBundle == null) {
			// check for the resource bundle relative to the messages class
			String baseName = messages.getName().replace('.', '/');

			resourceBundle = ResourceBundleHelper.getEquinoxResourceBundle(baseName, locale,
					messages.getClassLoader());

			if (resourceBundle == null) {
				// check for the resource bundle relative to the messages class by searching
				// the properties file lower case
				// this is a fix for Linux environments
				resourceBundle = ResourceBundleHelper.getEquinoxResourceBundle(
						baseName.toLowerCase(), locale, messages.getClassLoader());
			}
		}

		if (resourceBundle == null) {
			// retrieve the OSGi resource bundle
			Bundle bundle = FrameworkUtil.getBundle(messages);
			resourceBundle = rbProvider.getResourceBundle(bundle, locale.toString());
		}

		// always create a provider, if there is no resource bundle found, simply the modified keys
		// will be returned by this provider to show that there is something
		// wrong on loading it
		ResourceBundleTranslationProvider provider = new ResourceBundleTranslationProvider(
				resourceBundle);

		M instance = null;
		try {
			instance = messages.newInstance();
			Field[] fields = messages.getDeclaredFields();

			for (int i = 0; i < fields.length; i++) {
				if (!fields[i].isAccessible()) {
					fields[i].setAccessible(true);
				}

				if (fields[i].getType().isAssignableFrom(String.class)) {
					fields[i].set(instance,
							provider.translate(fields[i].getName()));
				}
			}
		} catch (InstantiationException e) {
			Logger log = this.logger;
			if (log != null) {
				log.error("Instantiation of messages class failed", e); //$NON-NLS-1$
			}
		} catch (IllegalAccessException e) {
			Logger log = this.logger;
			if (log != null) {
				log.error("Failed to access messages class", e); //$NON-NLS-1$
			}
		}

		// invoke the method annotated with @PostConstruct
		processPostConstruct(instance, messages);

		return instance;
	}

	/**
	 * Searches for the method annotated {@link PostConstruct} in the messages class. If there is
	 * one found it will be executed.
	 * <p>
	 * Note: The method annotated with {@link PostConstruct} does not support method injection
	 * because we are not using the injection mechanism to call.
	 *
	 * @param messageObject
	 *            The message instance of the given class where the method annotated with
	 *            {@link PostConstruct} should be called
	 * @param messageClass
	 *            The type of the message class whose instance is requested.
	 */
	private void processPostConstruct(Object messageObject, Class<?> messageClass) {
		if (messageObject != null) {
			Method[] methods = messageClass.getDeclaredMethods();
			for (Method method : methods) {
				if (!method.isAnnotationPresent(PostConstruct.class)) {
					continue;
				} else {
					try {
						method.invoke(messageObject);
					} catch (Exception e) {
						Logger log = this.logger;
						if (log != null) {
							log.error(
									"Exception on trying to execute the @PostConstruct annotated method in {}", //$NON-NLS-1$
									messageClass, e);
						}
					}
				}
			}
		}
	}

	@org.osgi.service.component.annotations.Reference(cardinality = ReferenceCardinality.OPTIONAL, policy = ReferencePolicy.DYNAMIC)
	void setLogger(LoggerFactory factory) {
		this.factory = factory;
		this.logger = factory.getLogger(getClass());
	}

	void unsetLogger(LoggerFactory loggerFactory) {
		if (this.factory == loggerFactory) {
			// if the factory we referenced locally is unset, we set the logger reference to
			// null
			this.factory = null;
			this.logger = null;
		}
	}

}