/*******************************************************************************
* Copyright (c) 2010 Composent, Inc. and others. All rights reserved. This
* program and the accompanying materials are made available under the terms of
* the Eclipse Public License v1.0 which accompanies this distribution, and is
* available at http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*   Composent, Inc. - initial API and implementation
******************************************************************************/
package org.eclipse.ecf.remoteservice;

import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.*;
import org.eclipse.core.runtime.*;
import org.eclipse.ecf.core.jobs.JobsExecutor;
import org.eclipse.ecf.core.util.ECFException;
import org.eclipse.ecf.internal.remoteservice.Activator;
import org.eclipse.equinox.concurrent.future.*;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceException;
import org.osgi.util.tracker.ServiceTracker;

/**
 * Abstract remote service implementation.  Clients may subclass to avoid re-implementing 
 * methods from IRemoteService.
 * 
 * @since 4.1
 */
//@ProviderType
public abstract class AbstractRemoteService implements IRemoteService, InvocationHandler {

	protected static final Object[] EMPTY_ARGS = new Object[0];

	/**
	 * @since 8.2
	 */
	protected int futureExecutorServiceMaxThreads = Integer.parseInt(System.getProperty("ecf.remoteservice.futureExecutorServiceMaxThreads", "10")); //$NON-NLS-1$ //$NON-NLS-2$

	/**
	 * @since 8.2
	 */
	protected ExecutorService futureExecutorService;

	/**
	 * @since 8.2
	 */
	protected ExecutorService getFutureExecutorService(IRemoteCall call) {
		synchronized (this) {
			if (futureExecutorService == null)
				futureExecutorService = Executors.newFixedThreadPool(futureExecutorServiceMaxThreads);
		}
		return futureExecutorService;
	}

	/**
	 * @since 8.2
	 */
	protected void setFutureExecutorService(ExecutorService executorService) {
		this.futureExecutorService = executorService;
	}

	/**
	 * @since 8.2
	 */
	protected IExecutor iFutureExecutor;

	/**
	 * @since 8.2
	 */
	protected IExecutor getIFutureExecutor(IRemoteCall call) {
		synchronized (this) {
			if (iFutureExecutor == null)
				iFutureExecutor = new JobsExecutor("RSJobs[rsID=" + getRemoteServiceID() + "]"); //$NON-NLS-1$ //$NON-NLS-2$
		}
		return iFutureExecutor;
	}

	/**
	 * @since 8.2
	 */
	protected void setIFutureExecutor(IExecutor executor) {
		this.iFutureExecutor = executor;
	}

	protected abstract String[] getInterfaceClassNames();

	protected abstract IRemoteServiceID getRemoteServiceID();

	protected abstract IRemoteServiceReference getRemoteServiceReference();

	protected Class loadInterfaceClass(String className) throws ClassNotFoundException {
		return loadInterfaceClass(this.getClass().getClassLoader(), className);
	}

	/**
	 * @since 6.0
	 */
	protected Class loadInterfaceClass(ClassLoader cl, String className) throws ClassNotFoundException {
		return Class.forName(className, true, cl);
	}

	protected IRemoteService getRemoteService() {
		return this;
	}

	protected long getDefaultTimeout() {
		return IRemoteCall.DEFAULT_TIMEOUT;
	}

	public IFuture callAsync(final IRemoteCall call) {
		IExecutor executor = getIFutureExecutor(call);
		if (executor == null)
			throw new ServiceException("iFuture executor is null.  Cannot callAsync remote method=" + call.getMethod()); //$NON-NLS-1$
		return executor.execute(new IProgressRunnable() {
			public Object run(IProgressMonitor monitor) throws Exception {
				return callSync(call);
			}
		}, null);
	}

	@SuppressWarnings("unchecked")
	public Object getProxy() throws ECFException {
		List classes = new ArrayList();
		ClassLoader cl = this.getClass().getClassLoader();
		try {
			// Get clazz from reference
			final String[] clazzes = getInterfaceClassNames();
			for (int i = 0; i < clazzes.length; i++)
				classes.add(loadInterfaceClass(cl, clazzes[i]));
		} catch (final Exception e) {
			ECFException except = new ECFException("Failed to create proxy", e); //$NON-NLS-1$
			logWarning("Exception in remote service getProxy", except); //$NON-NLS-1$
			throw except;
		} catch (final NoClassDefFoundError e) {
			ECFException except = new ECFException("Failed to load proxy interface class", e); //$NON-NLS-1$
			logWarning("Could not load class for getProxy", except); //$NON-NLS-1$
			throw except;
		}
		return getProxy(cl, (Class[]) classes.toArray(new Class[classes.size()]));
	}

	/**
	 * @since 6.0
	 */
	protected void addRemoteServiceProxyToProxy(List classes) {
		IRemoteServiceReference rsReference = getRemoteServiceReference();
		// add IRemoteServiceProxy interface to set of interfaces supported by this proxy
		if (rsReference != null && rsReference.getProperty(Constants.SERVICE_PREVENT_RSPROXY) == null)
			classes.add(IRemoteServiceProxy.class);
	}

	/**
	 * @since 6.0
	 */
	@SuppressWarnings("unchecked")
	public Object getProxy(ClassLoader cl, Class[] interfaces) throws ECFException {
		// Add async classes
		// for all interfaces, add async classes
		List classes = new ArrayList();
		for (int i = 0; i < interfaces.length; i++) {
			// add interface to classes
			classes.add(interfaces[i]);
			Class asyncClass = findAsyncRemoteServiceProxyClass(cl, interfaces[i]);
			if (asyncClass != null)
				classes.add(asyncClass);
		}
		// Add IRemoteServiceProxy to classes, if not restricted via service properties
		addRemoteServiceProxyToProxy(classes);
		// create and return proxy
		try {
			return createProxy(cl, (Class[]) classes.toArray(new Class[classes.size()]));
		} catch (final Exception e) {
			ECFException except = new ECFException("Failed to create proxy", e); //$NON-NLS-1$
			logWarning("Exception in remote service getProxy", except); //$NON-NLS-1$
			throw except;
		} catch (final NoClassDefFoundError e) {
			ECFException except = new ECFException("Failed to load proxy interface class", e); //$NON-NLS-1$
			logWarning("Could not load class for getProxy", except); //$NON-NLS-1$
			throw except;
		}
	}

	/**
	 * @since 8.0
	 */
	public class ProxyClassLoader extends ClassLoader {

		private ClassLoader cl;

		public ProxyClassLoader(ClassLoader cl) {
			this.cl = cl;
		}

		public Class loadClass(String name) throws ClassNotFoundException {
			try {
				return cl.loadClass(name);
			} catch (ClassNotFoundException e) {
				// If the classloader passed in upon construction cannot 
				// find the class, then use this bundle's classloader to
				// try to load the class
				Activator a = Activator.getDefault();
				if (a == null)
					throw e;
				BundleContext context = a.getContext();
				if (context == null)
					throw e;
				return context.getBundle().loadClass(name);
			}
		}
	}

	/**
	 * @since 8.0
	 */
	protected IRemoteServiceProxyCreator getRemoteServiceProxyCreator() {
		ServiceTracker st = new ServiceTracker(Activator.getDefault().getContext(), IRemoteServiceProxyCreator.class, null);
		st.open();
		IRemoteServiceProxyCreator result = (IRemoteServiceProxyCreator) st.getService();
		st.close();
		return result;
	}

	/**
	 * @since 6.0
	 */
	protected Object createProxy(ClassLoader cl, Class[] classes) {
		IRemoteServiceProxyCreator proxyCreator = getRemoteServiceProxyCreator();
		if (proxyCreator != null)
			return proxyCreator.createProxy(new ProxyClassLoader(cl), classes, this);
		return Proxy.newProxyInstance(new ProxyClassLoader(cl), classes, this);
	}

	protected Object createProxy(Class[] classes) {
		return createProxy(this.getClass().getClassLoader(), classes);
	}

	/**
	 * @since 3.3
	 */
	protected Class findAsyncRemoteServiceProxyClass(Class c) {
		String proxyClassName = convertInterfaceNameToAsyncInterfaceName(c.getName());
		try {
			return Class.forName(proxyClassName);
		} catch (ClassNotFoundException e) {
			logInfo("No async remote service interface found with name=" + proxyClassName + " for proxy service class=" + c.getName(), e); //$NON-NLS-1$ //$NON-NLS-2$
			return null;
		} catch (NoClassDefFoundError e) {
			logWarning("Async remote service interface with name=" + proxyClassName + " could not be loaded for proxy service class=" + c.getName(), e); //$NON-NLS-1$ //$NON-NLS-2$
			return null;
		}
	}

	/**
	 * @since 6.0
	 */
	protected Class findAsyncRemoteServiceProxyClass(ClassLoader cl, Class c) {
		String proxyClassName = convertInterfaceNameToAsyncInterfaceName(c.getName());
		try {
			return Class.forName(proxyClassName, true, cl);
		} catch (ClassNotFoundException e) {
			//logInfo("No async remote service interface found with name=" + proxyClassName + " for remote service class=" + c.getName(), e); //$NON-NLS-1$ //$NON-NLS-2$
			return null;
		} catch (NoClassDefFoundError e) {
			logWarning("Async remote service interface with name=" + proxyClassName + " could not be loaded for proxy service class=" + c.getName(), e); //$NON-NLS-1$ //$NON-NLS-2$
			return null;
		}
	}

	protected String convertInterfaceNameToAsyncInterfaceName(String interfaceName) {
		if (interfaceName == null)
			return null;
		String asyncProxyName = (String) getRemoteServiceReference().getProperty(Constants.SERVICE_ASYNC_RSPROXY_CLASS_ + interfaceName);
		if (asyncProxyName != null)
			return asyncProxyName;
		// If a value has been specified by the ServiceProperty
		return interfaceName + IAsyncRemoteServiceProxy.ASYNC_INTERFACE_SUFFIX;
	}

	protected Object[] getCallParametersForProxyInvoke(String callMethod, Method proxyMethod, Object[] args) {
		return args == null ? EMPTY_ARGS : args;
	}

	protected long getCallTimeoutForProxyInvoke(String callMethod, Method proxyMethod, Object[] args) {
		return IRemoteCall.DEFAULT_TIMEOUT;
	}

	protected String getCallMethodNameForProxyInvoke(Method method, Object[] args) {
		return method.getName();
	}

	protected Object invokeObject(Object proxy, final Method method, final Object[] args) throws Throwable {
		if (method.getName().equals("toString")) { //$NON-NLS-1$
			final String[] clazzes = getInterfaceClassNames();
			String proxyClass = (clazzes.length == 1) ? clazzes[0] : Arrays.asList(clazzes).toString();
			return proxyClass + ".proxy@" + getRemoteServiceID(); //$NON-NLS-1$
		} else if (method.getName().equals("hashCode")) { //$NON-NLS-1$
			return new Integer(hashCode());
		} else if (method.getName().equals("equals")) { //$NON-NLS-1$
			if (args == null || args.length == 0)
				return Boolean.FALSE;
			try {
				return new Boolean(Proxy.getInvocationHandler(args[0]).equals(this));
			} catch (IllegalArgumentException e) {
				return Boolean.FALSE;
			}
			// This handles the use of IRemoteServiceProxy.getRemoteService method
		} else if (method.getName().equals("getRemoteService")) { //$NON-NLS-1$
			return getRemoteService();
		} else if (method.getName().equals("getRemoteServiceReference")) { //$NON-NLS-1$
			return getRemoteServiceReference();
		}
		return null;
	}

	protected Object invokeSync(IRemoteCall call) throws ECFException {
		return callSync(call);
	}

	public Object invoke(Object proxy, final Method method, final Object[] args) throws Throwable {
		// methods declared by Object
		try {
			// If the method is from Class Object, or from IRemoteServiceProxy
			// then return result
			Object resultObject = invokeObject(proxy, method, args);
			if (resultObject != null)
				return resultObject;
			// If the method's class is a subclass of IAsyncRemoteServiceProxy, then we assume
			// that the methods are intended to be invoked asynchronously
			if (Arrays.asList(method.getDeclaringClass().getInterfaces()).contains(IAsyncRemoteServiceProxy.class))
				return invokeAsync(method, args);
			// else call synchronously/block and return result
			final String callMethod = getCallMethodNameForProxyInvoke(method, args);
			final Object[] callParameters = getCallParametersForProxyInvoke(callMethod, method, args);
			final long callTimeout = getCallTimeoutForProxyInvoke(callMethod, method, args);
			final IRemoteCall remoteCall = new IRemoteCall() {
				public String getMethod() {
					return callMethod;
				}

				public Object[] getParameters() {
					return callParameters;
				}

				public long getTimeout() {
					return callTimeout;
				}
			};
			return invokeSync(remoteCall);
		} catch (Throwable t) {
			if (t instanceof ServiceException)
				throw t;
			// rethrow as service exception
			throw new ServiceException("Service exception on remote service proxy rsid=" + getRemoteServiceID(), ServiceException.REMOTE, t); //$NON-NLS-1$
		}
	}

	/**
	 * @since 3.3
	 */
	protected class AsyncArgs {
		private IRemoteCallListener listener;
		private Object[] args;
		private boolean isIFuture;

		public AsyncArgs(Object[] originalArgs, boolean isIFuture) {
			this.listener = null;
			this.args = originalArgs;
			this.isIFuture = isIFuture;
		}

		public AsyncArgs(IRemoteCallListener listener, Object[] originalArgs) {
			this.listener = listener;
			if (this.listener != null) {
				int asynchArgsLength = originalArgs.length - 1;
				this.args = new Object[asynchArgsLength];
				System.arraycopy(originalArgs, 0, args, 0, asynchArgsLength);
			} else
				this.args = originalArgs;
		}

		public IRemoteCallListener getListener() {
			return listener;
		}

		public Object[] getArgs() {
			return args;
		}

		/**
		 * @since 8.2
		 */
		public boolean isIFuture() {
			return isIFuture;
		}
	}

	/**
	 * @since 3.3
	 */
	protected Object invokeAsync(final Method method, final Object[] args) throws Throwable {
		final String invokeMethodName = getAsyncInvokeMethodName(method);
		final AsyncArgs asyncArgs = getAsyncArgs(method, args);
		IRemoteCallListener listener = asyncArgs.getListener();
		IRemoteCall call = new IRemoteCall() {
			public String getMethod() {
				return invokeMethodName;
			}

			public Object[] getParameters() {
				return asyncArgs.getArgs();
			}

			public long getTimeout() {
				return DEFAULT_TIMEOUT;
			}
		};
		// IFuture or Future will have listener == null
		if (listener == null) {
			if (asyncArgs.isIFuture())
				return callAsync(call);
			return callFutureAsync(call);
		}
		return callAsyncWithResult(call, listener);
	}

	/**
	 * @since 8.2
	 */
	protected Object callAsyncWithResult(IRemoteCall call, IRemoteCallListener listener) {
		callAsync(call, listener);
		return null;
	}

	/**
	 * @since 8.2
	 */
	protected Future callFutureAsync(final IRemoteCall call) {
		ExecutorService executorService = getFutureExecutorService(call);
		if (executorService == null)
			throw new ServiceException("future executor service is null.  .  Cannot callAsync remote method=" + call.getMethod()); //$NON-NLS-1$
		return executorService.submit(new Callable() {
			public Object call() throws Exception {
				return callSync(call);
			}
		});
	}

	/**
	 * @since 3.3
	 */
	protected AsyncArgs getAsyncArgs(Method method, Object[] args) {
		IRemoteCallListener listener = null;
		Class returnType = method.getReturnType();
		// If the return type is of type java.util.concurrent.Future, then we return
		if (returnType.equals(Future.class)) {
			return new AsyncArgs(args, false);
		} else if (returnType.equals(IFuture.class)) {
			return new AsyncArgs(args, true);
		} else {
			// If the provided args do *not* include an IRemoteCallListener then we have a problem
			if (args == null || args.length == 0)
				throw new IllegalArgumentException("Async calls must include a IRemoteCallListener instance as the last argument"); //$NON-NLS-1$
			// Get the last arg
			Object lastArg = args[args.length - 1];
			// If it's an IRemoteCallListener implementer directly, then just cast and return
			if (lastArg instanceof IRemoteCallListener) {
				listener = (IRemoteCallListener) lastArg;
			}
			// If it's an implementation of IAsyncCallback, then create a new listener based upon 
			// callback and return
			if (lastArg instanceof IAsyncCallback) {
				listener = new CallbackRemoteCallListener((IAsyncCallback) lastArg);
			}
			// If the last are is not an instance of IRemoteCallListener then there is a problem
			if (listener == null)
				throw new IllegalArgumentException("Last argument must be an instance of IRemoteCallListener"); //$NON-NLS-1$
			return new AsyncArgs(listener, args);
		}
	}

	/**
	 * @since 3.3
	 */
	protected String getAsyncInvokeMethodName(Method method) {
		String methodName = method.getName();
		return methodName.endsWith(IAsyncRemoteServiceProxy.ASYNC_METHOD_SUFFIX) ? methodName.substring(0, methodName.length() - IAsyncRemoteServiceProxy.ASYNC_METHOD_SUFFIX.length()) : methodName;
	}

	private void logInfo(String message, Throwable e) {
		Activator a = Activator.getDefault();
		if (a != null)
			a.log(new Status(IStatus.INFO, Activator.PLUGIN_ID, message, e));
	}

	protected void logWarning(String string, Throwable e) {
		Activator a = Activator.getDefault();
		if (a != null)
			a.log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, string, e));
	}

	/**
	 * @since 8.2
	 */
	public void dispose() {
		synchronized (this) {
			if (futureExecutorService != null) {
				futureExecutorService.shutdownNow();
				futureExecutorService = null;
			}
			iFutureExecutor = null;
		}
	}
}
