/******************************************************************************
 * Copyright (c) 2016-2018 TypeFox and others.
 * 
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 * 
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 ******************************************************************************/
package org.eclipse.lsp4j.jsonrpc;

import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.function.Consumer;
import java.util.function.Function;

import org.eclipse.lsp4j.jsonrpc.json.ConcurrentMessageProcessor;
import org.eclipse.lsp4j.jsonrpc.json.JsonRpcMethod;
import org.eclipse.lsp4j.jsonrpc.json.JsonRpcMethodProvider;
import org.eclipse.lsp4j.jsonrpc.json.MessageJsonHandler;
import org.eclipse.lsp4j.jsonrpc.json.StreamMessageConsumer;
import org.eclipse.lsp4j.jsonrpc.json.StreamMessageProducer;
import org.eclipse.lsp4j.jsonrpc.messages.ResponseError;
import org.eclipse.lsp4j.jsonrpc.services.ServiceEndpoints;
import org.eclipse.lsp4j.jsonrpc.validation.ReflectiveMessageValidator;

import com.google.gson.GsonBuilder;

/**
 * This is the entry point for applications that use LSP4J. A Launcher does all the wiring that is necessary to connect
 * your endpoint via an input stream and an output stream.
 * 
 * @param <T> remote service interface type
 */
public interface Launcher<T> {
	
	/**
	 * Create a new Launcher for a given local service object, a given remote interface and an input and output stream.
	 * 
	 * @param localService - the object that receives method calls from the remote service
	 * @param remoteInterface - an interface on which RPC methods are looked up
	 * @param in - input stream to listen for incoming messages
	 * @param out - output stream to send outgoing messages
	 */
	static <T> Launcher<T> createLauncher(Object localService, Class<T> remoteInterface, InputStream in, OutputStream out) {
		return new Builder<T>()
				.setLocalService(localService)
				.setRemoteInterface(remoteInterface)
				.setInput(in)
				.setOutput(out)
				.create();
	}
	
	/**
	 * Create a new Launcher for a given local service object, a given remote interface and an input and output stream,
	 * and set up message validation and tracing.
	 * 
	 * @param localService - the object that receives method calls from the remote service
	 * @param remoteInterface - an interface on which RPC methods are looked up
	 * @param in - input stream to listen for incoming messages
	 * @param out - output stream to send outgoing messages
	 * @param validate - whether messages should be validated with the {@link ReflectiveMessageValidator}
	 * @param trace - a writer to which incoming and outgoing messages are traced, or {@code null} to disable tracing
	 */
	static <T> Launcher<T> createLauncher(Object localService, Class<T> remoteInterface, InputStream in, OutputStream out,
			boolean validate, PrintWriter trace) {
		return new Builder<T>()
				.setLocalService(localService)
				.setRemoteInterface(remoteInterface)
				.setInput(in)
				.setOutput(out)
				.validateMessages(validate)
				.traceMessages(trace)
				.create();
	}
	
	/**
	 * Create a new Launcher for a given local service object, a given remote interface and an input and output stream.
	 * Threads are started with the given executor service. The wrapper function is applied to the incoming and
	 * outgoing message streams so additional message handling such as validation and tracing can be included.
	 * 
	 * @param localService - the object that receives method calls from the remote service
	 * @param remoteInterface - an interface on which RPC methods are looked up
	 * @param in - input stream to listen for incoming messages
	 * @param out - output stream to send outgoing messages
	 * @param executorService - the executor service used to start threads
	 * @param wrapper - a function for plugging in additional message consumers
	 */
	static <T> Launcher<T> createLauncher(Object localService, Class<T> remoteInterface, InputStream in, OutputStream out,
			ExecutorService executorService, Function<MessageConsumer, MessageConsumer> wrapper) {
		return createIoLauncher(localService, remoteInterface, in, out, executorService, wrapper);
	}
	
	/**
	 * Create a new Launcher for a given local service object, a given remote interface and an input and output stream.
	 * Threads are started with the given executor service. The wrapper function is applied to the incoming and
	 * outgoing message streams so additional message handling such as validation and tracing can be included.
	 * 
	 * @param localService - the object that receives method calls from the remote service
	 * @param remoteInterface - an interface on which RPC methods are looked up
	 * @param in - input stream to listen for incoming messages
	 * @param out - output stream to send outgoing messages
	 * @param executorService - the executor service used to start threads
	 * @param wrapper - a function for plugging in additional message consumers
	 */
	static <T> Launcher<T> createIoLauncher(Object localService, Class<T> remoteInterface, InputStream in, OutputStream out,
			ExecutorService executorService, Function<MessageConsumer, MessageConsumer> wrapper) {
		return new Builder<T>()
				.setLocalService(localService)
				.setRemoteInterface(remoteInterface)
				.setInput(in)
				.setOutput(out)
				.setExecutorService(executorService)
				.wrapMessages(wrapper)
				.create();
	}
	
	/**
	 * Create a new Launcher for a given local service object, a given remote interface and an input and output stream.
	 * Threads are started with the given executor service. The wrapper function is applied to the incoming and
	 * outgoing message streams so additional message handling such as validation and tracing can be included.
	 * The {@code configureGson} function can be used to register additional type adapters in the {@link GsonBuilder}
	 * in order to support protocol classes that cannot be handled by Gson's reflective capabilities.
	 * 
	 * @param localService - the object that receives method calls from the remote service
	 * @param remoteInterface - an interface on which RPC methods are looked up
	 * @param in - input stream to listen for incoming messages
	 * @param out - output stream to send outgoing messages
	 * @param executorService - the executor service used to start threads
	 * @param wrapper - a function for plugging in additional message consumers
	 * @param configureGson - a function for Gson configuration
	 */
	static <T> Launcher<T> createIoLauncher(Object localService, Class<T> remoteInterface, InputStream in, OutputStream out,
			ExecutorService executorService, Function<MessageConsumer, MessageConsumer> wrapper, Consumer<GsonBuilder> configureGson) {
		return new Builder<T>()
				.setLocalService(localService)
				.setRemoteInterface(remoteInterface)
				.setInput(in)
				.setOutput(out)
				.setExecutorService(executorService)
				.wrapMessages(wrapper)
				.configureGson(configureGson)
				.create();
	}
	
	/**
	 * Create a new Launcher for a given local service object, a given remote interface and an input and output stream.
	 * Threads are started with the given executor service. The wrapper function is applied to the incoming and
	 * outgoing message streams so additional message handling such as validation and tracing can be included.
	 * The {@code configureGson} function can be used to register additional type adapters in the {@link GsonBuilder}
	 * in order to support protocol classes that cannot be handled by Gson's reflective capabilities.
	 * 
	 * @param localService - the object that receives method calls from the remote service
	 * @param remoteInterface - an interface on which RPC methods are looked up
	 * @param in - input stream to listen for incoming messages
	 * @param out - output stream to send outgoing messages
	 * @param validate - whether messages should be validated with the {@link ReflectiveMessageValidator}
	 * @param executorService - the executor service used to start threads
	 * @param wrapper - a function for plugging in additional message consumers
	 * @param configureGson - a function for Gson configuration
	 */
	static <T> Launcher<T> createIoLauncher(Object localService, Class<T> remoteInterface, InputStream in, OutputStream out, boolean validate,
			ExecutorService executorService, Function<MessageConsumer, MessageConsumer> wrapper, Consumer<GsonBuilder> configureGson) {
		return new Builder<T>()
				.setLocalService(localService)
				.setRemoteInterface(remoteInterface)
				.setInput(in)
				.setOutput(out)
				.validateMessages(validate)
				.setExecutorService(executorService)
				.wrapMessages(wrapper)
				.configureGson(configureGson)
				.create();
	}
	
	/**
	 * Create a new Launcher for a collection of local service objects, a collection of remote interfaces and an
	 * input and output stream. Threads are started with the given executor service. The wrapper function is applied
	 * to the incoming and outgoing message streams so additional message handling such as validation and tracing
	 * can be included. The {@code configureGson} function can be used to register additional type adapters in
	 * the {@link GsonBuilder} in order to support protocol classes that cannot be handled by Gson's reflective
	 * capabilities.
	 * 
	 * @param localServices - the objects that receive method calls from the remote services
	 * @param remoteInterfaces - interfaces on which RPC methods are looked up
	 * @param classLoader - a class loader that is able to resolve all given interfaces
	 * @param in - input stream to listen for incoming messages
	 * @param out - output stream to send outgoing messages
	 * @param executorService - the executor service used to start threads
	 * @param wrapper - a function for plugging in additional message consumers
	 * @param configureGson - a function for Gson configuration
	 */
	static Launcher<Object> createIoLauncher(Collection<Object> localServices, Collection<Class<?>> remoteInterfaces, ClassLoader classLoader,
			InputStream in, OutputStream out, ExecutorService executorService, Function<MessageConsumer, MessageConsumer> wrapper,
			Consumer<GsonBuilder> configureGson) {
		return new Builder<Object>()
				.setLocalServices(localServices)
				.setRemoteInterfaces(remoteInterfaces)
				.setClassLoader(classLoader)
				.setInput(in)
				.setOutput(out)
				.setExecutorService(executorService)
				.wrapMessages(wrapper)
				.configureGson(configureGson)
				.create();
	}
	
	
	//------------------------------ Builder Class ------------------------------//
	
	/**
	 * The launcher builder wires up all components for JSON-RPC communication.
	 * 
	 * @param <T> remote service interface type
	 */
	public static class Builder<T> {
		
		protected Collection<Object> localServices;
		protected Collection<Class<? extends T>> remoteInterfaces;
		protected InputStream input;
		protected OutputStream output;
		protected ExecutorService executorService;
		protected Function<MessageConsumer, MessageConsumer> messageWrapper;
		protected Function<Throwable, ResponseError> exceptionHandler;
		protected boolean validateMessages;
		protected Consumer<GsonBuilder> configureGson;
		protected ClassLoader classLoader;
		protected MessageTracer messageTracer;
		
		public Builder<T> setLocalService(Object localService) {
			this.localServices = Collections.singletonList(localService);
			return this;
		}

		public Builder<T> setLocalServices(Collection<Object> localServices) {
			this.localServices = localServices;
			return this;
		}

		public Builder<T> setRemoteInterface(Class<? extends T> remoteInterface) {
			this.remoteInterfaces = Collections.singletonList(remoteInterface);
			return this;
		}
		
		public Builder<T> setRemoteInterfaces(Collection<Class<? extends T>> remoteInterfaces) {
			this.remoteInterfaces = remoteInterfaces;
			return this;
		}

		public Builder<T> setInput(InputStream input) {
			this.input = input;
			return this;
		}

		public Builder<T> setOutput(OutputStream output) {
			this.output = output;
			return this;
		}

		public Builder<T> setExecutorService(ExecutorService executorService) {
			this.executorService = executorService;
			return this;
		}

		public Builder<T> setClassLoader(ClassLoader classLoader) {
			this.classLoader = classLoader;
			return this;
		}

		public Builder<T> wrapMessages(Function<MessageConsumer, MessageConsumer> wrapper) {
			this.messageWrapper = wrapper;
			return this;
		}
		
		public Builder<T> setExceptionHandler(Function<Throwable, ResponseError> exceptionHandler) {
			this.exceptionHandler = exceptionHandler;
			return this;
		}
		
		public Builder<T> validateMessages(boolean validate) {
			this.validateMessages = validate;
			return this;
		}
		
		public Builder<T> traceMessages(PrintWriter tracer) {
			if (tracer != null) {
				this.messageTracer = new MessageTracer(tracer);
			}
			return this;
		}

		public Builder<T> configureGson(Consumer<GsonBuilder> configureGson) {
			this.configureGson = configureGson;
			return this;
		}

		public Launcher<T> create() {
			// Validate input
			if (input == null)
				throw new IllegalStateException("Input stream must be configured.");
			if (output == null)
				throw new IllegalStateException("Output stream must be configured.");
			if (localServices == null)
				throw new IllegalStateException("Local service must be configured.");
			if (remoteInterfaces == null)
				throw new IllegalStateException("Remote interface must be configured.");
			
			// Create the JSON handler, remote endpoint and remote proxy
			MessageJsonHandler jsonHandler = createJsonHandler();
			RemoteEndpoint remoteEndpoint = createRemoteEndpoint(jsonHandler);
			T remoteProxy = createProxy(remoteEndpoint);
			
			// Create the message processor
			StreamMessageProducer reader = new StreamMessageProducer(input, jsonHandler, remoteEndpoint);
			MessageConsumer messageConsumer = wrapMessageConsumer(remoteEndpoint);
			ConcurrentMessageProcessor msgProcessor = createMessageProcessor(reader, messageConsumer, remoteProxy);
			ExecutorService execService = executorService != null ? executorService : Executors.newCachedThreadPool();
			return createLauncher(execService, remoteProxy, remoteEndpoint, msgProcessor);
		}
		
		/**
		 * Create the JSON handler for messages between the local and remote services.
		 */
		protected MessageJsonHandler createJsonHandler() {
			Map<String, JsonRpcMethod> supportedMethods = getSupportedMethods();
			if (configureGson != null)
				return new MessageJsonHandler(supportedMethods, configureGson);
			else
				return new MessageJsonHandler(supportedMethods);
		}
		
		/**
		 * Create the remote endpoint that communicates with the local services.
		 */
		protected RemoteEndpoint createRemoteEndpoint(MessageJsonHandler jsonHandler) {
			MessageConsumer outgoingMessageStream = new StreamMessageConsumer(output, jsonHandler);
			outgoingMessageStream = wrapMessageConsumer(outgoingMessageStream);
			Endpoint localEndpoint = ServiceEndpoints.toEndpoint(localServices);
			RemoteEndpoint remoteEndpoint;
			if (exceptionHandler == null)
				remoteEndpoint = new RemoteEndpoint(outgoingMessageStream, localEndpoint);
			else
				remoteEndpoint = new RemoteEndpoint(outgoingMessageStream, localEndpoint, exceptionHandler);
			jsonHandler.setMethodProvider(remoteEndpoint);
			return remoteEndpoint;
		}
		
		/**
		 * Create the proxy for calling methods on the remote service.
		 */
		@SuppressWarnings("unchecked")
		protected T createProxy(RemoteEndpoint remoteEndpoint) {
			if (localServices.size() == 1 && remoteInterfaces.size() == 1) {
				return ServiceEndpoints.toServiceObject(remoteEndpoint, remoteInterfaces.iterator().next());
			} else {
				return (T) ServiceEndpoints.toServiceObject(remoteEndpoint, (Collection<Class<?>>) (Object) remoteInterfaces, classLoader);
			}
		}
		
		/**
		 * Create the message processor that listens to the input stream. 
		 */
		protected ConcurrentMessageProcessor createMessageProcessor(MessageProducer reader, 
				MessageConsumer messageConsumer, T remoteProxy) {
			return new ConcurrentMessageProcessor(reader, messageConsumer);
		}
		
		protected Launcher<T> createLauncher(ExecutorService execService, T remoteProxy, RemoteEndpoint remoteEndpoint,
				ConcurrentMessageProcessor msgProcessor) {
			return new StandardLauncher<T>(execService, remoteProxy, remoteEndpoint, msgProcessor);
		}
		
		protected MessageConsumer wrapMessageConsumer(MessageConsumer consumer) {
			MessageConsumer result = consumer;
			if (messageTracer != null) {
				result = messageTracer.apply(consumer);
			}
			if (validateMessages) {
				result = new ReflectiveMessageValidator(result);
			}
			if (messageWrapper != null) {
				result = messageWrapper.apply(result);
			}
			return result;
		}
		
		/**
		 * Gather all JSON-RPC methods from the local and remote services.
		 */
		protected Map<String, JsonRpcMethod> getSupportedMethods() {
			Map<String, JsonRpcMethod> supportedMethods = new LinkedHashMap<>();
			// Gather the supported methods of remote interfaces
			for (Class<?> interface_ : remoteInterfaces) {
				supportedMethods.putAll(ServiceEndpoints.getSupportedMethods(interface_));
			}
			
			// Gather the supported methods of local services
			for (Object localService : localServices) {
				if (localService instanceof JsonRpcMethodProvider) {
					JsonRpcMethodProvider rpcMethodProvider = (JsonRpcMethodProvider) localService;
					supportedMethods.putAll(rpcMethodProvider.supportedMethods());
				} else {
					supportedMethods.putAll(ServiceEndpoints.getSupportedMethods(localService.getClass()));
				}
			}
			
			return supportedMethods;
		}
	}
	
	
	//---------------------------- Interface Methods ----------------------------//
	
	/**
	 * Start a thread that listens to the input stream. The thread terminates when the stream is closed.
	 * 
	 * @return a future that returns {@code null} when the listener thread is terminated
	 */
	Future<Void> startListening();
	
	/**
	 * Returns the proxy instance that implements the remote service interfaces.
	 */
	T getRemoteProxy();
	
	/**
	 * Returns the remote endpoint. Use this one to send generic {@code request} or {@code notify} methods
	 * to the remote services.
	 */
	RemoteEndpoint getRemoteEndpoint();
	
}
