/*******************************************************************************
 * Copyright (c) 2016, 2017 EclipseSource Services GmbH 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:
 *     Martin Fleck - initial API and implementation
 *     Christian W. Damus - bug 526932
 *     Christian W. Damus - bug 512529
 *******************************************************************************/
package org.eclipse.papyrus.compare.uml2.internal.hook.migration;

import com.google.common.collect.Iterables;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;

import org.eclipse.emf.common.notify.Adapter;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.notify.Notifier;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EPackage.Registry;
import org.eclipse.emf.ecore.resource.ContentHandler;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.edit.provider.ComposedAdapterFactory;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.impl.TransactionalEditingDomainImpl;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
import org.eclipse.papyrus.uml.tools.model.UmlModel;

/**
 * This class wraps a resource set into a ModelSet with minimal changes to be compliant to the expected
 * Profile Migration mechanism of Eclipse Luna.
 * 
 * @author Martin Fleck <mfleck@eclipsesource.com>
 */
public class ModelSetWrapper extends ModelSet {

	/**
	 * Mapping of resources to their read-only setting. Needed when a new editing domain is created.
	 */
	private Map<Resource, Boolean> resourceToReadOnlyMap = new HashMap<Resource, Boolean>();

	/**
	 * The resource set being wrapped.
	 */
	private ResourceSet resourceSet;

	/**
	 * Constructor.
	 * 
	 * @param resourceSet
	 *            resource set to be wrapped.
	 */
	public ModelSetWrapper(ResourceSet resourceSet) {
		super();

		this.resourceSet = resourceSet;

		// We need to ensure that UML profiles are shared by myself and the
		// resource set that I wrap, because a profile must be loaded exactly once
		// to avoid confusing the identity of stereotypes. Otherwise, stereotype
		// applications repaired in this model-set context would be deemed invalid
		// in the wrapped resource-set context because there the UML API
		// is seeing the wrong copy of the Stereotype as their definition
		// cf. http://eclip.se/526932
		this.resources = new ProxyingResourceList();
	}

	@Override
	protected Resource demandCreateResource(URI uri) {
		if (shouldProxy(uri)) {
			// Create the real resource in the wrapped resource set and proxy it here
			Resource delegate = resourceSet.createResource(uri, ContentHandler.UNSPECIFIED_CONTENT_TYPE);
			if (delegate != null) {
				// Get the proxy
				return getResource(uri, false);
			}
		}

		return super.demandCreateResource(uri);
	}

	/**
	 * Ensure that the given resource has the specified readOnly setting in the
	 * {@link #getTransactionalEditingDomain() editing domain} of this model set.
	 * 
	 * @param resource
	 *            resource within this resource set
	 * @param readOnly
	 *            true if resource should be readOnly, false otherwise
	 */
	public void setReadOnly(Resource resource, Boolean readOnly) {
		resourceToReadOnlyMap.put(resource, readOnly);
	}

	@Override
	public synchronized TransactionalEditingDomain getTransactionalEditingDomain() {
		final TransactionalEditingDomainImpl domain = new TransactionalEditingDomainImpl(
				new ComposedAdapterFactory(ComposedAdapterFactory.Descriptor.Registry.INSTANCE));
		domain.setResourceToReadOnlyMap(resourceToReadOnlyMap);
		return domain;
	}

	@Override
	public Registry getPackageRegistry() {
		return resourceSet.getPackageRegistry(); // delegate to wrapped resourceSet
	}

	/**
	 * Queries whether a code resource should be proxied in the model set. This is usually required for UML
	 * library resources (profiles, metamodels, and such deployed in plug-ins) and not for other resources.
	 * 
	 * @param resourceURI
	 *            a resource URI
	 * @return whether it should be proxied
	 */
	protected boolean shouldProxy(URI resourceURI) {
		return resourceSet.getURIConverter().normalize(resourceURI).isPlatformPlugin()
				&& UmlModel.UML_FILE_EXTENSION.equals(resourceURI.fileExtension());
	}

	/**
	 * Detaches me from the resource-set that I wrap.
	 */
	public void detach() {
		((ProxyingResourceList)resources).detach();
	}

	/**
	 * Directly set the model-set's URI without initializing the entire pluggable models and snippets
	 * infrastructure.
	 * 
	 * @param uriWithoutExtension
	 *            the URI without the file extension
	 */
	@Override
	public void setURIWithoutExtension(URI uriWithoutExtension) {
		super.setURIWithoutExtension(uriWithoutExtension);
	}

	//
	// Nested types
	//

	/**
	 * A specialized resource list that shares the underlying resources (and hence their contents) of UML
	 * Profiles with the wrapped resource, to ensure a single in-memory copy of each profile definition for
	 * consistent identification of stereotype applications. Nonetheless, each resource set has to see these
	 * shared resources as "owned by" it, so in the {@code ModelSetWrapper} context this is achieved by
	 * dynamic proxies that pass through to the real resources for everything but the relationship to the
	 * owning resource-set.
	 *
	 * @author Christian W. Damus
	 */
	protected class ProxyingResourceList extends ResourcesEList<Resource> implements Adapter {

		private static final long serialVersionUID = 1L;

		private final Map<Resource, Resource> proxies = new HashMap<>();

		/**
		 * Initializes me.
		 */
		protected ProxyingResourceList() {
			super();

			for (Resource next : resourceSet.getResources()) {
				addProxy(next);
			}

			resourceSet.eAdapters().add(this);
		}

		/**
		 * Detaches me from my delegate list, removes all of my proxy resources, and forgets all of my proxy
		 * mappings.
		 */
		void detach() {
			// Stop listening to my delegate for changes in its resources
			resourceSet.eAdapters().remove(this);

			// Remove all of my proxy resources that I don't own
			removeAll(proxies.values());
			proxies.clear();
		}

		//
		// Proxy management
		//

		/**
		 * Queries whether a {@code resource} should be proxied in the model set. This is usually required for
		 * UML library resources (profiles, metamodels, and such deployed in plug-ins) and not for other
		 * resources.
		 * 
		 * @param resource
		 *            a resource
		 * @return whether it should be proxied
		 */
		protected boolean shouldProxy(Resource resource) {
			return ModelSetWrapper.this.shouldProxy(resource.getURI());
		}

		/**
		 * Obtains the existing proxy, if any, that represents my share of a {@code resource}.
		 * 
		 * @param resource
		 *            a resource
		 * @return the existing proxy, or {@code null} if it has not been proxied
		 */
		Resource getProxy(Resource resource) {
			return proxies.get(resource);
		}

		/**
		 * Creates the canonical proxy wrapper for a {@code resource} that represents my share of it.
		 * 
		 * @param resource
		 *            a resource to proxy
		 * @return the proxied resource
		 */
		Resource createProxy(Resource resource) {
			Collection<Class<?>> interfaces = getResourceInterfaces(resource.getClass());
			Resource result = (Resource)Proxy.newProxyInstance(getClass().getClassLoader(),
					Iterables.toArray(interfaces, Class.class), new ResourceProxy(resource));
			proxies.put(resource, result);
			return result;
		}

		/**
		 * Computes the {@link Resource} interfaces that a proxy needs to implement to expose the full API of
		 * an instance of the given resource implementation class.
		 * 
		 * @param resourceImpl
		 *            the implementation class of a resource
		 * @return its interfaces
		 */
		private Collection<Class<?>> getResourceInterfaces(Class<?> resourceImpl) {
			Collection<Class<?>> result = new LinkedHashSet<>();

			for (Class<?> class_ = resourceImpl; class_ != null; class_ = class_.getSuperclass()) {
				interfaces: for (Class<?> next : class_.getInterfaces()) {
					if (Resource.class.isAssignableFrom(next)) {
						for (Class<?> found : result) {
							if (next.isAssignableFrom(found)) {
								// Don't bother if it's a redundant superinterface
								continue interfaces;
							}
						}
						result.add(next);
					}
				}
			}

			// Remove redundant superinterfaces

			return result;
		}

		/**
		 * Queries whether a {@code resource} is a proxy that represents my co-ownership of it.
		 * 
		 * @param resource
		 *            a resource
		 * @return whether it is a proxy of mine
		 */
		boolean isProxy(Resource resource) {
			return resource != null && Proxy.isProxyClass(resource.getClass())
					&& Proxy.getInvocationHandler(resource) instanceof ResourceProxy;
		}

		/**
		 * Obtains a proxy for the given {@code resource}, creating that proxy if necessary, to represent my
		 * share of it.
		 * 
		 * @param resource
		 *            a resource
		 * @return the {@code resource} itself if it already {@linkplain #isProxy(Resource) is a proxy} or a
		 *         proxy wrapping it
		 */
		Resource proxy(Resource resource) {
			if (isProxy(resource)) {
				return resource;
			}

			Resource result = getProxy(resource);
			if (result == null) {
				result = createProxy(resource);
			}
			return result;
		}

		/**
		 * Obtains the real resource represented by the given {@code resource}, in case it
		 * {@linkplain #isProxy(Resource) is a proxy}.
		 * 
		 * @param resource
		 *            a resource
		 * @return the real resource if a proxy, otherwise just the {@code resource}, itself
		 */
		Resource unproxy(Resource resource) {
			if (isProxy(resource)) {
				return ((ResourceProxy)Proxy.getInvocationHandler(resource)).resource;
			}
			return resource;
		}

		/**
		 * Adds a proxy for me to share ownership of the given {@code resource} if I
		 * {@linkplain #shouldProxy(Resource) should have a proxy} for it.
		 * 
		 * @param resource
		 *            a resource to conditionally add to me as a proxy
		 */
		void addProxy(Resource resource) {
			if (shouldProxy(resource)) {
				add(proxy(resource));
			}
		}

		/**
		 * Removes my proxy for the given {@code resource} if I have one
		 * 
		 * @param resource
		 *            a resource that I must no longer share
		 */
		void removeProxy(Resource resource) {
			// Don't implicitly create a proxy just to remove it
			remove(getProxy(resource));
		}

		/**
		 * Adds a proxy for me to share ownership of the given {@code newResource} in place of the old if I
		 * {@linkplain #shouldProxy(Resource) should have a proxy} for it. Otherwise, just ensures that I do
		 * not have a proxy for the {@code oldResource}.
		 * 
		 * @param oldResource
		 *            a resource for which I should not have a proxy
		 * @param newResource
		 *            a resource to conditionally replace the old one with
		 */
		void replaceProxy(Resource oldResource, Resource newResource) {
			// Don't implicitly create a proxy just to remove it
			int index = indexOf(getProxy(oldResource));
			if (index >= 0) {
				if (shouldProxy(newResource)) {
					set(index, proxy(newResource));
				} else {
					removeProxy(oldResource);
				}
			} else if (shouldProxy(newResource)) {
				add(proxy(newResource));
			}
		}

		//
		// Adapter protocol to pick up changes in the delegate list
		//

		public void notifyChanged(Notification msg) {
			if (msg.isTouch()) {
				return;
			}

			if (msg.getNotifier() == resourceSet
					&& msg.getFeatureID(ResourceSet.class) == RESOURCE_SET__RESOURCES) {
				switch (msg.getEventType()) {
					case Notification.ADD:
						addProxy((Resource)msg.getNewValue());
						break;
					case Notification.ADD_MANY:
						for (Object next : (Collection<?>)msg.getNewValue()) {
							addProxy((Resource)next);
						}
						break;
					case Notification.REMOVE:
						removeProxy((Resource)msg.getOldValue());
						break;
					case Notification.REMOVE_MANY:
						for (Object next : (Collection<?>)msg.getOldValue()) {
							removeProxy((Resource)next);
						}
						break;
					case Notification.SET:
						replaceProxy((Resource)msg.getOldValue(), (Resource)msg.getNewValue());
						break;
					default:
						// Pass. Not even move is interesting
						break;
				}
			}
		}

		public Notifier getTarget() {
			return null;
		}

		public void setTarget(Notifier newTarget) {
			// Pass
		}

		public boolean isAdapterForType(Object type) {
			return false;
		}

	}

	/**
	 * Invocation handler for my proxy resources. It passes through all API to the wrapped resource, properly
	 * owned by my wrapped resource set, except for the API dealing with the relationship to the resource set,
	 * which in that case is myself.
	 *
	 * @author Christian W. Damus
	 */
	private class ResourceProxy implements InvocationHandler {
		private final Resource resource;

		ResourceProxy(Resource resource) {
			super();

			this.resource = resource;
		}

		public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
			switch (method.getName()) {
				case "getResourceSet": //$NON-NLS-1$
					if (method.getDeclaringClass() == Resource.class) {
						return ModelSetWrapper.this;
					}
					break;
				case "basicSetResourceSet": //$NON-NLS-1$
					if (method.getDeclaringClass() == Resource.Internal.class) {
						// Don't try to tell the real resource that the wrapper
						// model-set is its owner
						return null;
					}
					break;
			}

			return method.invoke(resource, args);
		}

	}
}
