/*****************************************************************************
 * Copyright (c) 2013, 2017 CEA LIST 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:
 *   CEA LIST - Initial API and implementation
 *   Christian W. Damus (CEA) - bug 429242
 *   Christian W. Damus (CEA) - bug 422257
 *
 *****************************************************************************/
package org.eclipse.papyrus.cdo.internal.core.importer;

import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.common.util.DiagnosticChain;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.osgi.util.NLS;
import org.eclipse.papyrus.cdo.core.importer.IModelDependentsProvider;
import org.eclipse.papyrus.cdo.core.importer.IModelTransferConfiguration;
import org.eclipse.papyrus.cdo.core.importer.IModelTransferListener;
import org.eclipse.papyrus.cdo.core.importer.IModelTransferNode;
import org.eclipse.papyrus.cdo.core.importer.IModelTransferOperation;
import org.eclipse.papyrus.cdo.core.importer.IModelTransferOperation.Context;
import org.eclipse.papyrus.cdo.internal.core.Activator;
import org.eclipse.papyrus.cdo.internal.core.l10n.Messages;
import org.eclipse.papyrus.infra.core.sashwindows.di.util.DiUtils;
import org.eclipse.papyrus.infra.emf.utils.EMFHelper;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * This is the ModelTransferConfiguration type. Enjoy.
 */
public class ModelTransferConfiguration implements IModelTransferConfiguration {

	private final Direction direction;

	private Map<URI, Resource> resources = Maps.newHashMap();

	private ResourceSet resourceSet;

	private boolean stripSashModelContent;

	private final boolean ownResourceSet;

	private final IModelTransferOperation.Context operationContext;

	private final Map<Resource, IModelTransferNode> importNodes = Maps.newHashMap();

	private final Set<IModelTransferNode> modelsToImport = Sets.newHashSet();

	private final Collection<IModelDependentsProvider> dependentsProviders = Lists.newArrayList();

	private final CopyOnWriteArrayList<IModelTransferListener> listeners = new CopyOnWriteArrayList<IModelTransferListener>();

	public ModelTransferConfiguration(IModelTransferOperation.Context operationContext, ResourceSet resourceSet) {
		this(operationContext, resourceSet, Direction.IMPORT);
	}

	public ModelTransferConfiguration(IModelTransferOperation.Context operationContext, ResourceSet resourceSet, Direction direction) {
		super();

		this.direction = direction;
		this.operationContext = new ReentrantOperationContext(operationContext);

		if (resourceSet != null) {
			this.resourceSet = resourceSet;
			this.ownResourceSet = false;
		} else {
			this.resourceSet = new ResourceSetImpl();
			((ResourceSetImpl) this.resourceSet).setURIResourceMap(resources);
			this.ownResourceSet = true;
		}
	}

	public final Direction getDirection() {
		return direction;
	}

	@Override
	public void dispose() {
		if (resourceSet != null) {
			if (ownResourceSet) {
				EMFHelper.unload(resourceSet);
				resourceSet = null;
			} else {
				// even if not owned, we should remove DependencyAdapters
				for (Resource next : resourceSet.getResources()) {
					DependencyAdapter adapter = DependencyAdapter.getExistingInstance(next);
					next.eAdapters().remove(adapter);
				}
			}

			resources.clear();
			resources = null;
		}

		listeners.clear();
	}

	@Override
	public ResourceSet getResourceSet() {
		return resourceSet;
	}

	@Override
	public Context getOperationContext() {
		return operationContext;
	}

	@Override
	public Collection<IModelTransferNode> getModelsToTransfer() {
		return Collections.unmodifiableSet(modelsToImport);
	}

	@Override
	public IModelTransferNode addModelToTransfer(URI resourceURI) {
		IModelTransferNode result = getNode(resourceURI);

		if (modelsToImport.add(result)) {
			fireModelsToImportChanged();
		}

		return result;
	}

	protected IModelTransferNode getNode(URI resourceURI) {
		IModelTransferNode result = null;

		final Resource resource = resourceSet.getResource(resourceURI, true);
		if (resource != null) {
			result = importNodes.get(resource);
			if (result == null) {
				final ModelTransferNode newNode = new ModelTransferNode(this, resource);
				importNodes.put(resource, newNode);

				newNode.initialize(getOperationContext());

				Diagnostic problems = getOperationContext().run(new IModelTransferOperation() {

					@Override
					public Diagnostic run(IProgressMonitor monitor) {
						SubMonitor sub = SubMonitor.convert(monitor, Messages.ModelTransferConfiguration_0, dependentsProviders.size());

						for (IModelDependentsProvider next : dependentsProviders) {
							// first, if it's a DI resource, ensure that it gets its components
							if (DependencyAdapter.isDIResource(resource)) {
								DependencyAdapter adapter = DependencyAdapter.getInstance(resource);
								final int oldCount = adapter.getDependencies().size();

								for (URI uri : next.getComponents(resource, monitor)) {
									// this is an implicit dependency, even if there are no references
									// to it (which occurs, e.g., in model sub-units that have no diagrams)
									Resource implicitDependency = resource.getResourceSet().getResource(uri, true);
									if (implicitDependency != null) {
										adapter.addDependency(implicitDependency);
									}
								}

								if (adapter.getDependencies().size() > oldCount) {
									// scan for components and dependencies again
									newNode.scanForComponents();
									newNode.scanForDependencies();
								}
							}

							for (URI uri : next.getDependents(newNode.getPrimaryResource(), monitor)) {
								newNode.addDependent(getNode(uri));
							}

							sub.worked(1);
						}

						sub.done();
						return Diagnostic.OK_INSTANCE;
					}
				});

				fireModelDependentsChanged(newNode);
				fireProblemsEvent(problems);

				result = newNode;
			}
		}

		return result;
	}

	@Override
	public void removeModelToTransfer(IModelTransferNode node) {
		if (modelsToImport.remove(node)) {
			fireModelsToImportChanged();
		}
	}

	@Override
	public void addModelDependentsProvider(IModelDependentsProvider provider) {
		if (!dependentsProviders.contains(provider)) {
			dependentsProviders.add(provider);
		}
	}

	@Override
	public Diagnostic validate() {
		BasicDiagnostic result = new BasicDiagnostic();

		Set<IModelTransferNode> toImport = ImmutableSet.copyOf(getModelsToTransfer());
		for (IModelTransferNode node : toImport) {
			checkDependents(node, toImport, result);
			checkDependencies(node, toImport, result);
		}

		fireProblemsEvent(result);

		return result;
	}

	protected void checkDependents(IModelTransferNode node, Set<IModelTransferNode> toImport, DiagnosticChain diagnostics) {
		Set<IModelTransferNode> dependents = ImmutableSet.copyOf(node.getDependents());
		Set<IModelTransferNode> leftOut = Sets.difference(dependents, toImport);
		if (!leftOut.isEmpty()) {
			IModelTransferNode parentUnit = findParentUnit(node, leftOut);
			if (parentUnit != null) {
				diagnostics.add(new BasicDiagnostic(Diagnostic.ERROR, Activator.PLUGIN_ID, 0, NLS.bind(Messages.ModelTransferConfiguration_3, new Object[] { node.getName(), direction, parentUnit.getName() }), new Object[] { node, parentUnit }));
			} else {
				int severity = direction.isImport() ? Diagnostic.WARNING : Diagnostic.INFO;
				diagnostics.add(new BasicDiagnostic(severity, Activator.PLUGIN_ID, 0, NLS.bind(Messages.ModelTransferConfiguration_1, node.getName(), direction), new Object[] { node, leftOut }));
			}
		}
	}

	protected void checkDependencies(IModelTransferNode node, Set<IModelTransferNode> toImport, DiagnosticChain diagnostics) {
		Set<IModelTransferNode> dependencies = ImmutableSet.copyOf(node.getDependencies());
		Set<IModelTransferNode> leftOut = Sets.difference(dependencies, toImport);
		if (!leftOut.isEmpty()) {
			Set<IModelTransferNode> subUnits = findSubUnits(node, leftOut);
			if (!subUnits.isEmpty()) {
				diagnostics.add(new BasicDiagnostic(Diagnostic.ERROR, Activator.PLUGIN_ID, 0, NLS.bind(Messages.ModelTransferConfiguration_4, new Object[] { node.getName(), direction }), new Object[] { node, subUnits }));
			} else {
				int severity = direction.isImport() ? Diagnostic.INFO : Diagnostic.WARNING;
				diagnostics.add(new BasicDiagnostic(severity, Activator.PLUGIN_ID, 0, NLS.bind(Messages.ModelTransferConfiguration_2, node.getName(), direction), new Object[] { node, leftOut }));
			}
		}
	}

	private IModelTransferNode findParentUnit(IModelTransferNode node, Collection<? extends IModelTransferNode> possibleParents) {
		IModelTransferNode result = null;

		for (IModelTransferNode next : possibleParents) {
			if (node.isModelParentUnit(next)) {
				result = next;
				break;
			}
		}

		return result;
	}

	private Set<IModelTransferNode> findSubUnits(IModelTransferNode node, Collection<? extends IModelTransferNode> possibleChildren) {
		ImmutableSet.Builder<IModelTransferNode> result = ImmutableSet.builder();

		for (IModelTransferNode next : possibleChildren) {
			if (node.isModelSubUnit(next)) {
				result.add(next);
			}
		}

		return result.build();
	}

	@Override
	public void addModelTransferListener(IModelTransferListener listener) {
		listeners.addIfAbsent(listener);
	}

	@Override
	public void removeModelTransferListener(IModelTransferListener listener) {
		listeners.remove(listener);
	}

	void fireProblemsEvent(Diagnostic problems) {
		if (problems.getSeverity() > Diagnostic.OK) {
			for (IModelTransferListener next : listeners) {
				try {
					next.modelTransferProblemsOccurred(problems);
				} catch (Exception e) {
					Activator.log.error(NLS.bind("Uncaught exception in model {0} listener.", direction.name()), e); //$NON-NLS-1$
				}
			}
		}
	}

	void fireModelsToImportChanged() {
		for (IModelTransferListener next : listeners) {
			try {
				next.modelsToTransferChanged(this);
			} catch (Exception e) {
				Activator.log.error(NLS.bind("Uncaught exception in model {0} listener.", direction.name()), e); //$NON-NLS-1$
			}
		}
	}

	void fireModelDependentsChanged(IModelTransferNode node) {
		for (IModelTransferListener next : listeners) {
			try {
				next.modelDependentsChanged(node);
			} catch (Exception e) {
				Activator.log.error(NLS.bind("Uncaught exception in model {0} listener.", direction.name()), e); //$NON-NLS-1$
			}
		}
	}

	boolean hasResource(URI uri) {
		return resources.containsKey(uri);
	}

	@Override
	public boolean hasSashModelContent() {
		boolean result = false;

		ResourceSet rset = getResourceSet();
		if (rset != null) {
			for (IModelTransferNode next : importNodes.values()) {
				Resource primary = rset.getResource(next.getPrimaryResourceURI(), false);
				if ((primary != null) && (DiUtils.lookupSashWindowsMngr(primary) != null)) {
					result = true;
					break;
				}
			}
		}

		return result;
	}

	@Override
	public boolean isStripSashModelContent() {
		return stripSashModelContent;
	}

	@Override
	public void setStripSashModelContent(boolean stripSashModelContent) {
		this.stripSashModelContent = stripSashModelContent;
	}

	//
	// Nested types
	//

	public static enum Direction {
		IMPORT(Messages.ModelTransferConfiguration_6), EXPORT(Messages.ModelTransferConfiguration_7);

		private final String label;

		private Direction(String label) {
			this.label = label;
		}

		public boolean isImport() {
			return this == IMPORT;
		}

		@Override
		public String toString() {
			return label;
		}
	}
}
