/**
 *                                                                            
 *  Copyright (c) 2011, 2016 - Loetz GmbH&Co.KG (69115 Heidelberg, Germany) 
 *                                                                            
 *  All rights reserved. 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:                                                      
 * 	   Christophe Loetz (Loetz GmbH&Co.KG) - initial implementation
 * 
 */
package org.eclipse.osbp.xtext.functionlibrarydsl.provider;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.MethodDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashSet;
import java.util.Locale;
import java.util.Map;
import java.util.Set;

import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.osbp.runtime.common.validation.IStatus;
import org.eclipse.osbp.ui.api.functionlibrary.IFunctionLibraryGroup;
import org.eclipse.osbp.ui.api.functionlibrary.IFunctionLibraryPackage;
import org.eclipse.osbp.ui.api.functionlibrary.IFunctionLibraryService;
import org.eclipse.osbp.ui.api.statemachine.IStateMachine;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This service provides access to the function library.
 */
@Component(immediate = true)
public class FunctionLibraryService implements IFunctionLibraryService {

	private final Logger log = LoggerFactory
			.getLogger(FunctionLibraryService.class);
	private Set<ServiceReference<IFunctionLibraryPackage>> functionLibraryPackages = new HashSet<>();
	private Set<Bundle> bundles = new HashSet<>();
	@SuppressWarnings("unused")
	private ComponentContext context;

	@Activate
	protected void activate(ComponentContext context) {
		this.context = context;
	}

	@Deactivate
	protected void deactivate(ComponentContext context) {
		this.context = null;
		functionLibraryPackages.clear();
		bundles.clear();
	}

	@Reference(cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC, unbind = "removeFunctionLibraryPackage")
	public synchronized void addFunctionLibraryPackage(
			final ServiceReference<IFunctionLibraryPackage> ref) {

		functionLibraryPackages.add(ref);

		createBundleList();

		log.debug("IFunctionLibraryPackage " + ref.getProperty("component.name")
				+ " bound");
	}

	public synchronized void removeFunctionLibraryPackage(
			final ServiceReference<IFunctionLibraryPackage> ref) {
		functionLibraryPackages.remove(ref);

		createBundleList();

		log.debug("IFunctionLibraryPackage " + ref.getProperty("component.name")
				+ " unbound");
	}

	private void createBundleList() {
		if (log.isDebugEnabled())
			log.debug("creating class loader list");
		bundles.clear();
		for (ServiceReference<IFunctionLibraryPackage> ref : functionLibraryPackages) {
			try {
				bundles.add(ref.getBundle());
			} catch (Exception e) {
				log.error("{}", e);
			}
		}
	}

	@SuppressWarnings("unchecked")
	public Class<IFunctionLibraryGroup> getFunctionLibraryClass(String className) {
		for (Bundle bundle : bundles) {
			try {
				return (Class<IFunctionLibraryGroup>) bundle.loadClass(className);
			} catch (ClassNotFoundException e) {
				log.error("{}", e);
			}
		}
		return null;
	}
	
	private Class<?> getClassFromSimpleName(String simpleName)  {
		for(ServiceReference<IFunctionLibraryPackage> ref : functionLibraryPackages) {
			String pkgName = (String) ref.getProperty("component.name");
			String className = pkgName.replace("FunctionLibraryPackage", simpleName);
			try {
				return ref.getBundle().loadClass(className);
			} catch (ClassNotFoundException e) {
				// NOSONAR
			}
		}
		return null;
	}

	private Object callFunctionLibrary(
			Class<IFunctionLibraryGroup> functionLibGroupClass,
			String methodName, Object fieldValue, Locale locale,
			Object... params) {
		if (functionLibGroupClass != null) {
			try {
				IFunctionLibraryGroup functionLibGroup = functionLibGroupClass
						.newInstance();
				for (Method method : functionLibGroupClass.getDeclaredMethods()) {
					if (method.getName().equals(methodName)) {
						try {
							// both locale and fieldValue are set
							if (locale != null && fieldValue != null) {
								if (params.length > 0) {
									return method.invoke(functionLibGroup,
											fieldValue, locale, params);
								}
								return method.invoke(functionLibGroup,
										fieldValue, locale);
							}
							// both locale and fieldValue are UNSET
							else if (locale == null && fieldValue == null) {
								return method.invoke(functionLibGroup);
							}
							// either locale or fieldValue is set, the other is
							// unset
							// only fieldValue is set
							else if (fieldValue != null) {
								return method.invoke(functionLibGroup,
										fieldValue);
							}
							// only locale is set (last possible condition)
							else {
								return method.invoke(functionLibGroup, locale);
							}
						} catch (IllegalArgumentException|InvocationTargetException e) {
							log.error("{}", e);
						}
					}
				}
			} catch (InstantiationException|IllegalAccessException e) {
				log.error("{}", e);
			}
		}
		return null;
	}

	public Object invoke(String className, String methodName,
			Object fieldValue, Locale locale, Object... params) {
		return callFunctionLibrary(getFunctionLibraryClass(className),
				methodName, fieldValue, locale, params);
	}

	public Object invoke(String className, String methodName,
			Object fieldValue) {
		return callFunctionLibrary(getFunctionLibraryClass(className),
				methodName, fieldValue, null);
	}

	public Object invoke(String className, String methodName,
			Locale locale) {
		return callFunctionLibrary(getFunctionLibraryClass(className),
				methodName, null, locale);
	}

	public Object invoke(String className, String methodName) {
		return invoke(className, methodName, null);
	}

	public boolean guard(IStateMachine statemachine, String className,
			String methodName) {
		Class<?> clz = getFunctionLibraryClass(className);
		try {
			BeanInfo info = Introspector.getBeanInfo(clz);
			for (MethodDescriptor methodDesc : info.getMethodDescriptors()) {
				Method method = methodDesc.getMethod();
				Class<?>[] parameterTypes = method.getParameterTypes();
				if (methodName.equals(method.getName())) {
					if(parameterTypes.length == 1) {
						if(IStateMachine.class.isAssignableFrom(parameterTypes[0])) {
							if(boolean.class.isAssignableFrom(method.getReturnType())) {
								return (Boolean) method.invoke(clz, statemachine);
							} else {
								log.error("method "+methodName+" in class "+className+" must have a return type Boolean. Found "+method.getReturnType().getCanonicalName()+" instead.");
							}
						} else {
							log.error("method "+methodName+" in class "+className+" must have a parameter of type IStateMachine. Found "+parameterTypes[0].getCanonicalName()+" instead.");
						}
					} else {
						log.error("method "+methodName+" in class "+className+" must have exactly 1 parameter. Found "+parameterTypes.length+" parameters instead.");
					}
				}
			}
			log.error("method "+methodName+" was not found in class "+className);
		} catch (IntrospectionException | IllegalAccessException
				| IllegalArgumentException | InvocationTargetException e) {
			log.error("{}", e);
		}
		return false;
	}

	public boolean operation(IStateMachine statemachine, String className,
			String methodName, Object... params) {
		Class<?> clz = getFunctionLibraryClass(className);
		try {
			BeanInfo info = Introspector.getBeanInfo(clz);
			for (MethodDescriptor methodDesc : info.getMethodDescriptors()) {
				Method method = methodDesc.getMethod();
				Class<?>[] parameterTypes = method.getParameterTypes();
				if (methodName.equals(method.getName())) {
					if(parameterTypes.length >= 1) {
						if(IStateMachine.class.isAssignableFrom(parameterTypes[0])) {
							if(boolean.class.isAssignableFrom(method.getReturnType())) {
								if(parameterTypes.length == 1) {
									return (Boolean) method.invoke(clz, statemachine);
								} else {
									return (Boolean) method.invoke(clz, statemachine, params);
								}
							} else {
								log.error("method "+methodName+" in class "+className+" must have a return type Boolean. Found "+method.getReturnType().getCanonicalName()+" instead.");
							}
						} else {
							log.error("method "+methodName+" in class "+className+" must have as first parameter type IStateMachine. Found "+parameterTypes[0].getCanonicalName()+" instead.");
						}
					} else {
						log.error("method "+methodName+" in class "+className+" must have at least one parameter. Found "+parameterTypes.length+" parameters instead.");
					}
				}
			}
			log.error("method "+methodName+" was not found in class "+className);
		} catch (IntrospectionException | IllegalAccessException
				| IllegalArgumentException | InvocationTargetException e) {
			log.error("{}", e);
		}
		return false;
	}

	@Override
	public Object function(IStateMachine statemachine, String className,
			String methodName, Object... params) {
		Class<?> clz = getFunctionLibraryClass(className);
		try {
			BeanInfo info = Introspector.getBeanInfo(clz);
			for (MethodDescriptor methodDesc : info.getMethodDescriptors()) {
				Method method = methodDesc.getMethod();
				Class<?>[] parameterTypes = method.getParameterTypes();
				if (methodName.equals(method.getName())) {
					if(parameterTypes.length >= 1) {
						if(IStateMachine.class.isAssignableFrom(parameterTypes[0])) {
							if(parameterTypes.length == 1) {
								return method.invoke(clz, statemachine);
							} else {
								return method.invoke(clz, statemachine, params);
							}
						} else {
							log.error("method "+methodName+" in class "+className+" must have as first parameter type IStateMachine. Found "+parameterTypes[0].getCanonicalName()+" instead.");
						}
					} else {
						log.error("method "+methodName+" in class "+className+" must have at least one parameter. Found "+parameterTypes.length+" parameters instead.");
					}
				}
			}
			log.error("method "+methodName+" was not found in class "+className);
		} catch (IntrospectionException | IllegalAccessException
				| IllegalArgumentException | InvocationTargetException e) {
			log.error("{}", e);
		}
		return null;
	}

	@Override
	public boolean execute(IEclipseContext context, String className, String methodName, Object... params) {
		Class<?> clz = getFunctionLibraryClass(className);
		try {
			BeanInfo info = Introspector.getBeanInfo(clz);
			for (MethodDescriptor methodDesc : info.getMethodDescriptors()) {
				Method method = methodDesc.getMethod();
				Class<?>[] parameterTypes = method.getParameterTypes();
				if (methodName.equals(method.getName())) {
					if(parameterTypes.length >= 1) {
						if(IEclipseContext.class.isAssignableFrom(parameterTypes[0])) {
							if(boolean.class.isAssignableFrom(method.getReturnType())) {
								if(parameterTypes.length == 1) {
									return (Boolean) method.invoke(clz, context);
								} else {
									return (Boolean) method.invoke(clz, context, params);
								}
							} else {
								log.error("method "+methodName+" in class "+className+" must have a return type Boolean. Found "+method.getReturnType().getCanonicalName()+" instead.");
							}
						} else {
							log.error("method "+methodName+" in class "+className+" must have as first parameter type IEclipseContext. Found "+parameterTypes[0].getCanonicalName()+" instead.");
						}
					} else {
						log.error("method "+methodName+" in class "+className+" must have at least one parameter. Found "+parameterTypes.length+" parameters instead.");
					}
				}
			}
			log.error("method "+methodName+" was not found in class "+className);
		} catch (IntrospectionException | IllegalAccessException
				| IllegalArgumentException | InvocationTargetException e) {
			log.error("{}", e);
		}
		return false;
	}

	@Override
	public boolean canExecute(IEclipseContext context, String className, String methodName, Object... params) {
		Class<?> clz = getFunctionLibraryClass(className);
		try {
			BeanInfo info = Introspector.getBeanInfo(clz);
			for (MethodDescriptor methodDesc : info.getMethodDescriptors()) {
				Method method = methodDesc.getMethod();
				Class<?>[] parameterTypes = method.getParameterTypes();
				if (methodName.equals(method.getName())) {
					if(parameterTypes.length >= 1) {
						if(IEclipseContext.class.isAssignableFrom(parameterTypes[0])) {
							if(boolean.class.isAssignableFrom(method.getReturnType())) {
								if(parameterTypes.length == 1) {
									return (Boolean) method.invoke(clz, context);
								} else {
									return (Boolean) method.invoke(clz, context, params);
								}
							} else {
								log.error("method "+methodName+" in class "+className+" must have a return type Boolean. Found "+method.getReturnType().getCanonicalName()+" instead.");
							}
						} else {
							log.error("method "+methodName+" in class "+className+" must have as first parameter type IEclipseContext. Found "+parameterTypes[0].getCanonicalName()+" instead.");
						}
					} else {
						log.error("method "+methodName+" in class "+className+" must have at least one parameter. Found "+parameterTypes.length+" parameters instead.");
					}
				}
			}
			log.error("method "+methodName+" was not found in class "+className);
		} catch (IntrospectionException | IllegalAccessException
				| IllegalArgumentException | InvocationTargetException e) {
			log.error("{}", e);
		}
		return false;
	}
	
	@Override
	public Set<IStatus> validation(String className, Object clazz, Map<String, Object> properties) {
		Class<?> clz = getClassFromSimpleName(className);
		HashSet<IStatus> statuus = new HashSet<>();
		if(clz != null) {
			try {
				BeanInfo info = Introspector.getBeanInfo(clz);
				for (MethodDescriptor methodDesc : info.getMethodDescriptors()) {
					Method method = methodDesc.getMethod();
					if(method.getReturnType().isAssignableFrom(IStatus.class)) {
						Object status = method.invoke(clz, clazz, properties);
						if(status != null) {
							statuus.add((IStatus)status);
						}
					}
				}
			} catch (IntrospectionException | IllegalAccessException
					| IllegalArgumentException | InvocationTargetException e) {
				log.error("{}", e);
			}
		}
		return statuus;
	}

	public Method getMethod(Class<?> clz, String methodName) {
		BeanInfo info;
		try {
			info = Introspector.getBeanInfo(clz);
			for (MethodDescriptor methodDesc : info.getMethodDescriptors()) {
				Method method = methodDesc.getMethod();
				Class<?>[] parameterTypes = method.getParameterTypes();
				if (methodName.equals(method.getName()) && boolean.class.isAssignableFrom(method.getReturnType()) && parameterTypes.length == 2) {
					return method;
				}
			}
		} catch (IntrospectionException e) {
			log.error("{}", e);
		}
		return null;
	}
}
