/*******************************************************************************
 * Copyright (c) 2008-2011 Chair for Applied Software Engineering,
 * Technische Universitaet Muenchen.
 * 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:
 * Otto von Wesendonk - initial API and implementation
 ******************************************************************************/
package org.eclipse.emf.emfstore.internal.client.model.connectionmanager.xmlrpc;

import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.apache.commons.lang.StringUtils;
import org.apache.xmlrpc.XmlRpcException;
import org.apache.xmlrpc.client.XmlRpcClient;
import org.apache.xmlrpc.client.XmlRpcClientConfigImpl;
import org.apache.xmlrpc.client.XmlRpcSun15HttpTransportFactory;
import org.eclipse.emf.emfstore.client.exceptions.ESCertificateException;
import org.eclipse.emf.emfstore.common.extensionpoint.ESExtensionElement;
import org.eclipse.emf.emfstore.common.extensionpoint.ESExtensionPoint;
import org.eclipse.emf.emfstore.internal.client.model.Configuration;
import org.eclipse.emf.emfstore.internal.client.model.ServerInfo;
import org.eclipse.emf.emfstore.internal.client.model.connectionmanager.ConnectionManager;
import org.eclipse.emf.emfstore.internal.client.model.connectionmanager.KeyStoreManager;
import org.eclipse.emf.emfstore.internal.common.ESCollections;
import org.eclipse.emf.emfstore.internal.common.model.util.FileUtil;
import org.eclipse.emf.emfstore.internal.common.model.util.ModelUtil;
import org.eclipse.emf.emfstore.internal.common.model.util.SerializationException;
import org.eclipse.emf.emfstore.internal.server.connection.xmlrpc.util.EObjectTypeFactory;
import org.eclipse.emf.emfstore.internal.server.exceptions.ConnectionException;
import org.eclipse.emf.emfstore.internal.server.model.ProjectId;
import org.eclipse.emf.emfstore.internal.server.model.SessionId;
import org.eclipse.emf.emfstore.internal.server.model.versioning.AbstractChangePackage;
import org.eclipse.emf.emfstore.internal.server.model.versioning.ChangePackageEnvelope;
import org.eclipse.emf.emfstore.internal.server.model.versioning.ChangePackageProxy;
import org.eclipse.emf.emfstore.internal.server.model.versioning.FileBasedChangePackage;
import org.eclipse.emf.emfstore.internal.server.model.versioning.VersioningFactory;
import org.eclipse.emf.emfstore.internal.server.model.versioning.operations.util.ChangePackageUtil;
import org.eclipse.emf.emfstore.server.exceptions.ESException;
import org.xml.sax.SAXException;

import com.google.common.base.Optional;

/**
 * Manager for XML RPC server calls.
 *
 * @author wesendon
 */
public class XmlRpcClientManager {

	private final String serverInterface;
	private XmlRpcClient client;
	private static boolean serializationOptionsInitialized;
	private static boolean gzipCompressionEnabled;
	private static boolean gzipRequestingEnabled;

	/**
	 * Default constructor.
	 *
	 * @param serverInterface name of interface
	 */
	public XmlRpcClientManager(String serverInterface) {
		this.serverInterface = serverInterface;
	}

	/**
	 * Initializes the connection.
	 *
	 * @param serverInfo server info
	 * @throws ConnectionException in case of failure
	 */
	public void initConnection(ServerInfo serverInfo) throws ConnectionException {
		try {
			initSerializationOptions();
			final XmlRpcClientConfigImpl config = new XmlRpcClientConfigImpl();
			config.setServerURL(createURL(serverInfo));
			config.setEnabledForExceptions(true);
			config.setEnabledForExtensions(true);
			config.setConnectionTimeout(Configuration.getXMLRPC().getXMLRPCConnectionTimeout());
			config.setReplyTimeout(Configuration.getXMLRPC().getXMLRPCReplyTimeout());
			config.setContentLengthOptional(true);
			config.setGzipCompressing(gzipCompressionEnabled);
			config.setGzipRequesting(gzipRequestingEnabled);

			client = new XmlRpcClient();
			client.setTypeFactory(new EObjectTypeFactory(client));

			final XmlRpcSun15HttpTransportFactory factory = new XmlRpcSun15HttpTransportFactory(client);

			try {
				factory.setSSLSocketFactory(KeyStoreManager.getInstance().getSSLContext().getSocketFactory());
			} catch (final ESCertificateException e) {
				throw new ConnectionException(Messages.XmlRpcClientManager_Could_Not_Load_Certificate, e);
			}
			client.setTransportFactory(factory);
			client.setConfig(config);
		} catch (final MalformedURLException e) {
			throw new ConnectionException(Messages.XmlRpcClientManager_Malformed_URL_Or_Port, e);
		}
	}

	private URL createURL(ServerInfo serverInfo) throws MalformedURLException {
		checkUrl(serverInfo.getUrl());
		return new URL("https", serverInfo.getUrl(), serverInfo.getPort(), "/xmlrpc"); //$NON-NLS-1$ //$NON-NLS-2$
	}

	private void checkUrl(String url) throws MalformedURLException {
		if (url != null && !url.equals(StringUtils.EMPTY)) {
			if (!(url.contains(":") || url.contains("/"))) { //$NON-NLS-1$ //$NON-NLS-2$
				return;
			}
		}
		throw new MalformedURLException();
	}

	/**
	 * Executes a server call with return value.
	 *
	 * @param <T> return type
	 * @param methodName method name
	 * @param returnType return type
	 * @param parameters parameters
	 * @return returned object from server
	 * @throws ESException in case of failure
	 */
	public <T> T callWithResult(String methodName, Class<T> returnType, Object... parameters) throws ESException {
		return executeCall(methodName, returnType, parameters);
	}

	/**
	 * Executes a server call with list return value.
	 *
	 * @param <T> return type
	 * @param methodName method name
	 * @param returnType list return type
	 * @param parameters parameters
	 * @return list return type
	 * @throws ESException in case of failure
	 */
	@SuppressWarnings("unchecked")
	public <T> List<T> callWithListResult(String methodName, Class<T> returnType, Object... parameters)
		throws ESException {
		final List<T> result = new ArrayList<T>();
		final Object[] callResult = executeCall(methodName, Object[].class, parameters);
		if (callResult == null) {
			return result;
		}
		for (final Object obj : callResult) {
			result.add((T) obj);
		}
		return result;
	}

	/**
	 * Executes a server call without return value.
	 *
	 * @param methodName method name
	 * @param parameters parameters
	 * @throws ESException in case of failure
	 */
	public void call(String methodName, Object... parameters) throws ESException {
		executeCall(methodName, null, parameters);
	}

	@SuppressWarnings("unchecked")
	private <T> T executeCall(String methodName, Class<T> returnType, Object[] params) throws ESException {
		if (client == null) {
			throw new ConnectionException(ConnectionManager.REMOTE);
		}

		final Object[] adjustedParams = adjustParameters(params);

		try {
			final T result = (T) client.execute(serverInterface + "." + methodName, adjustedParams); //$NON-NLS-1$
			return adjustResult(ESCollections.find(params, SessionId.class), result);

		} catch (final XmlRpcException e) {
			if (e.getCause() instanceof ESException) {
				throw (ESException) e.getCause();
			} else if (e.linkedException instanceof SAXException
				&& ((SAXException) e.linkedException).getException() instanceof SerializationException) {
				final SerializationException serialE = (SerializationException) ((SAXException) e.linkedException)
					.getException();
				throw new org.eclipse.emf.emfstore.internal.server.exceptions.SerializationException(serialE);
			} else {
				throw new ConnectionException(ConnectionManager.REMOTE + e.getMessage(), e);
			}
		}
	}

	private Object[] adjustParameters(final Object[] params) throws ESException {
		if (!Configuration.getClientBehavior().getChangePackageFragmentSize().isPresent()) {
			return params;
		}

		final Optional<SessionId> maybeSessionId = ESCollections.find(params, SessionId.class);
		final Optional<ProjectId> maybeProjectId = ESCollections.find(params, ProjectId.class);

		if (!maybeSessionId.isPresent() || !maybeProjectId.isPresent()) {
			// do not attempt to split
			return params;
		}

		for (int i = 0; i < params.length; i++) {
			final Object param = params[i];
			if (AbstractChangePackage.class.isInstance(param) && !ChangePackageProxy.class.isInstance(param)) {
				params[i] = uploadInFragments(
					maybeSessionId.get(),
					maybeProjectId.get(),
					AbstractChangePackage.class.cast(param));
			}
		}

		return params;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	private <T> T adjustResult(final Optional<SessionId> maybeSessionId, final T result) throws ESException {
		if (result instanceof Object[]) {
			final Object[] objects = (Object[]) result;
			for (int i = 0; i < objects.length; i++) {
				final Object item = objects[i];
				objects[i] = adjustResult(maybeSessionId, item);
			}
			return (T) objects;
		} else if (result instanceof List) {
			final List l = (List) result;
			for (int i = 0; i < l.size(); i++) {
				l.set(i, adjustResult(maybeSessionId, result));
			}
		} else if (result instanceof ChangePackageProxy) {
			return (T) downloadAndResolveChangePackage((ChangePackageProxy) result, maybeSessionId);
		}

		return result;
	}

	private AbstractChangePackage downloadAndResolveChangePackage(final ChangePackageProxy proxy,
		final Optional<SessionId> maybeSession) throws ESException {

		if (!maybeSession.isPresent()) {
			throw new ESException(Messages.XmlRpcClientManager_NoValidSessionId);
		}

		int fragmentIndex = 0;
		final FileBasedChangePackage changePackage = VersioningFactory.eINSTANCE
			.createFileBasedChangePackage();
		changePackage.initialize(FileUtil.createLocationForTemporaryChangePackage());

		ChangePackageEnvelope envelope;
		do {
			envelope = executeCall("downloadChangePackageFragment", ChangePackageEnvelope.class, new Object[] { //$NON-NLS-1$
				maybeSession.get(),
					proxy.getId(),
					fragmentIndex
			});
			changePackage.addAll(envelope.getFragment());
			fragmentIndex += 1;
		} while (!envelope.isLast());

		try {
			changePackage.setLogMessage(
				ModelUtil.clone(proxy.getLogMessage()));
			changePackage.save();
		} catch (final IOException ex) {
			throw new ESException(Messages.XmlRpcClientManager_SaveChangePackageFailed, ex);
		}
		return changePackage;
	}

	private ChangePackageProxy uploadInFragments(SessionId sessionId,
		ProjectId projectId, AbstractChangePackage changePackage)
		throws ESException {

		// get() is guarded
		final Iterator<ChangePackageEnvelope> envelopes = ChangePackageUtil.splitChangePackage(
			changePackage,
			Configuration.getClientBehavior().getChangePackageFragmentSize().get());

		String proxyId = null;
		try {
			while (envelopes.hasNext()) {
				proxyId = uploadChangePackageFragment(
					sessionId,
					projectId,
					envelopes.next()
					);
			}
		} catch (final XmlRpcException ex) {
			throw new ESException(Messages.XmlRpcClientManager_UploadChangePackageFragmentCallFailed, ex);
		}

		final ChangePackageProxy proxy = VersioningFactory.eINSTANCE.createChangePackageProxy();
		proxy.setLogMessage(ModelUtil.clone(changePackage.getLogMessage()));
		proxy.setId(proxyId);
		return proxy;
	}

	private String uploadChangePackageFragment(final SessionId sessionId,
		final ProjectId projectId, final ChangePackageEnvelope envelope) throws XmlRpcException {
		return (String) client.execute(serverInterface + "." + "uploadChangePackageFragment", //$NON-NLS-1$ //$NON-NLS-2$
			new Object[] {
				sessionId,
				projectId,
				envelope
			});
	}

	/**
	 * Initializes the serialization options for compressed server communication.
	 */
	private static void initSerializationOptions() {

		if (serializationOptionsInitialized) {
			return;
		}
		// init compression with false if not configured
		gzipRequestingEnabled = false;
		gzipCompressionEnabled = false;
		final ESExtensionElement element = new ESExtensionPoint(
			"org.eclipse.emf.emfstore.common.model.serializationOptions") //$NON-NLS-1$
			.getFirst();

		if (element != null) {
			gzipCompressionEnabled = element.getBoolean("GzipCompression"); //$NON-NLS-1$
			gzipRequestingEnabled = element.getBoolean("GzipRequesting"); //$NON-NLS-1$
		}

		serializationOptionsInitialized = true;
	}

}
