/*******************************************************************************
 * Copyright (c) 2015 Obeo 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:
 *     Obeo - initial API and implementation
 *     Philip Langer - extract interface
 *******************************************************************************/
package org.eclipse.emf.compare.ide.ui.internal.logical.resolver;

import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.eventbus.EventBus;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.Set;

import org.apache.log4j.Logger;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.emf.common.util.BasicDiagnostic;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.compare.ide.ui.internal.util.ThreadSafeProgressMonitor;
import org.eclipse.emf.compare.ide.utils.ResourceUtil;
import org.eclipse.emf.compare.internal.utils.Graph;

/**
 * The default implementation of the {@link IResourceDependencyProvider}.
 * 
 * @author <a href="mailto:laurent.delaigue@obeo.fr">Laurent Delaigue</a>
 */
public class ResourceDependencyLocalResolver implements IResourceDependencyLocalResolver {
	/** The logger. */
	private static final Logger LOGGER = Logger.getLogger(ResourceDependencyLocalResolver.class);

	/** The scheduler. */
	private final ResourceComputationScheduler<URI> scheduler;

	/** The event bus */
	private final EventBus eventBus;

	/** The dependency graph. */
	private final Graph<URI> dependencyGraph;

	/** The resource listener. */
	private final ModelResourceListener resourceListener;

	/** The implicit dependencies */
	private final IImplicitDependencies implicitDependencies;

	/**
	 * Constructor.
	 * 
	 * @param context
	 *            The resolution context, must not be {@code null}
	 */
	public ResourceDependencyLocalResolver(IResolutionContext context) {
		this.implicitDependencies = context.getImplicitDependencies();
		this.scheduler = context.getScheduler();
		this.eventBus = context.getEventBus();
		this.dependencyGraph = context.getGraph();
		this.resourceListener = context.getModelResourceListener();
	}

	public Iterable<URI> getDependenciesOf(IFile file) {
		return getDependenciesOf(file, Collections.<URI> emptySet());
	}

	public Iterable<URI> getDependenciesOf(IFile file, Set<URI> bounds) {
		final URI expectedURI = ResourceUtil.createURIFor(file);

		final Iterable<URI> dependencies;
		switch (ResolutionUtil.getResolutionScope()) {
			case WORKSPACE:
				dependencies = dependencyGraph.getSubgraphContaining(expectedURI, bounds);
				break;
			case PROJECT:
				final Set<URI> allDependencies = dependencyGraph.getSubgraphContaining(expectedURI, bounds);
				final IResource project = file.getProject();
				dependencies = Iterables.filter(allDependencies, isInContainer(project));
				break;
			case CONTAINER:
				final Set<URI> allDependencies1 = dependencyGraph.getSubgraphContaining(expectedURI, bounds);
				final IResource container = file.getParent();
				dependencies = Iterables.filter(allDependencies1, isInContainer(container));
				break;
			case OUTGOING:
				dependencies = dependencyGraph.getTreeFrom(expectedURI, bounds);
				break;
			case SELF:
				// fall through
			default:
				dependencies = Collections.singleton(expectedURI);
				break;
		}
		return dependencies;
	}

	/**
	 * Checks the current state of our {@link #resourceListener} and updates the dependency graph for all
	 * resources that have been changed since we last checked.
	 * 
	 * @param resourceSet
	 *            The resource set in which to load our temporary resources.
	 * @param diagnostic
	 *            The diagnostic.
	 * @param tspm
	 *            Monitor on which to report progress to the user.
	 */
	protected void updateChangedResources(SynchronizedResourceSet resourceSet, DiagnosticSupport diagnostic,
			ThreadSafeProgressMonitor tspm) {
		// this.diagnostic = createDiagnostic();
		final Set<URI> removedURIs = Sets.difference(resourceListener.popRemovedURIs(), scheduler
				.getComputedElements());
		final Set<URI> changedURIs = Sets.difference(resourceListener.popChangedURIs(), scheduler
				.getComputedElements());

		eventBus.post(new ResourceRemovedEvent<URI>(removedURIs));

		// We need to re-resolve the changed resources, along with their direct parents
		final Set<URI> recompute = new LinkedHashSet<URI>(changedURIs);
		final Multimap<URI, URI> parentToGrandParents = ArrayListMultimap.create();
		for (URI changed : changedURIs) {
			if (dependencyGraph.contains(changed)) {
				Set<URI> directParents = dependencyGraph.getDirectParents(changed);
				recompute.addAll(directParents);
				for (URI uri : directParents) {
					Set<URI> grandParents = dependencyGraph.getDirectParents(uri);
					parentToGrandParents.putAll(uri, grandParents);
				}
			}
		}

		eventBus.post(new ResourceRemovedEvent<URI>(recompute));

		demandResolveAll(recompute, diagnostic, resourceSet, tspm);

		// Re-connect changed resources parents' with their parents
		demandResolveAll(Iterables.concat(Iterables.transform(Iterables.filter(parentToGrandParents.keySet(),
				new Predicate<URI>() {
					public boolean apply(URI uri) {
						return dependencyGraph.contains(uri);
					}
				}), new Function<URI, Collection<URI>>() {
			public Collection<URI> apply(URI input) {
				return parentToGrandParents.get(input);
			}
		})), diagnostic, resourceSet, tspm);
	}

	public void demandResolve(final SynchronizedResourceSet resourceSet, final URI uri,
			final DiagnosticSupport diagnostic, final ThreadSafeProgressMonitor tspm) {
		if (ResolutionUtil.isInterruptedOrCanceled(tspm)) {
			scheduler.demandShutdown();
			return;
		}
		for (URI currentUri : implicitDependencies.of(uri, resourceSet.getURIConverter())) {
			scheduler.scheduleComputation(new LocalResolveComputation(scheduler, eventBus, diagnostic,
					resourceSet, currentUri, new MonitorCallback(diagnostic, tspm), tspm));
		}
	}

	/**
	 * Allows callers to launch the loading and resolution of the model pointed at by the given URI.
	 * <p>
	 * This will check whether the given storage isn't already being resolved, then submit a job to the
	 * {@link #resolvingPool} to load and resolve the model in a separate thread.
	 * </p>
	 * 
	 * @param resourceSet
	 *            The resource set in which to load the resource.
	 * @param uris
	 *            The uris we are to try and load as models.
	 * @param diagnostic
	 *            The diagnostic
	 * @param tspm
	 *            Monitor on which to report progress to the user.
	 * @see LocalResolveComputation
	 */
	private void demandResolveAll(Iterable<URI> uris, final DiagnosticSupport diagnostic,
			final SynchronizedResourceSet resourceSet, final ThreadSafeProgressMonitor tspm) {
		scheduler.computeAll(Iterables.transform(uris, new Function<URI, IComputation<URI>>() {
			public IComputation<URI> apply(final URI uri) {
				// In this case, we don't want to call the implicit dependencies extension point
				return new LocalResolveComputation(scheduler, eventBus, diagnostic, resourceSet, uri,
						new MonitorCallback(diagnostic, tspm), tspm);
			}
		}));
	}

	/**
	 * This predicate can be used to check wether a given URI points to a workspace resource contained in the
	 * given container.
	 * 
	 * @param container
	 *            The container in which we need the resources to be contained.
	 * @return A ready to use predicate.
	 */
	protected Predicate<URI> isInContainer(final IResource container) {
		return new Predicate<URI>() {
			public boolean apply(URI input) {
				if (input != null) {
					final IFile pointedFile = ResolutionUtil.getFileAt(input);
					if (pointedFile != null) {
						return container.getLocation().isPrefixOf(pointedFile.getLocation());
					}
				}
				return false;
			}
		};
	}

	/**
	 * Update the dependency graph to make sure that it contains the given file.
	 * <p>
	 * If the graph does not yet contain this file, we'll try and find cross-references outgoing from and/or
	 * incoming to the given file, depending on the current {@link #getResolutionScope() resolution scope}.
	 * </p>
	 * 
	 * @param monitor
	 *            The progress monitor.
	 * @param diagnostic
	 *            The diagnostic
	 * @param files
	 *            The files which we need to be present in the dependency graph.
	 * @throws InterruptedException
	 *             if the computation of dependencies is interrupted.
	 */
	public void updateDependencies(IProgressMonitor monitor, final DiagnosticSupport diagnostic,
			IFile... files) throws InterruptedException {
		final ThreadSafeProgressMonitor tspm = new ThreadSafeProgressMonitor(monitor);
		if (LOGGER.isDebugEnabled()) {
			LOGGER.debug("INSTANTIATING SynchronizedResourceSet to update dependencies with " //$NON-NLS-1$
					+ files.length + " files"); //$NON-NLS-1$
		}
		final SynchronizedResourceSet resourceSet = new SynchronizedResourceSet(
				new LocalMonitoredProxyCreationListener(tspm, eventBus, this, diagnostic));
		Iterable<IFile> filesToResolve = Iterables.filter(Arrays.asList(files), new Predicate<IFile>() {
			public boolean apply(IFile file) {
				return !dependencyGraph.contains(ResourceUtil.asURI().apply(file));
			}
		});
		scheduler.runAll(Iterables.transform(filesToResolve, new Function<IFile, Runnable>() {
			public Runnable apply(final IFile file) {
				return new Runnable() {
					public void run() {
						final IResource startingPoint = getResolutionStartingPoint(file);
						final ModelResourceVisitor modelVisitor = new ModelResourceVisitor(scheduler,
								resourceSet, ResourceDependencyLocalResolver.this, diagnostic, tspm);
						try {
							startingPoint.accept(modelVisitor);
						} catch (CoreException e) {
							diagnostic.merge(BasicDiagnostic.toDiagnostic(e));
						}
					}
				};
			}
		}));
		updateChangedResources(resourceSet, diagnostic, tspm);

		resourceSet.dispose();
	}

	/**
	 * Returns the starting point for the resolution of the given file's logical model according to
	 * {@link #getResolutionScope()}.
	 * 
	 * @param file
	 *            The file which logical model we need to add to the current {@link #dependencyGraph}.
	 * @return Starting point for this file's logical model resolution.
	 * @see CrossReferenceResolutionScope
	 */
	protected IResource getResolutionStartingPoint(IFile file) {
		final IResource startingPoint;
		switch (ResolutionUtil.getResolutionScope()) {
			case WORKSPACE:
				startingPoint = ResourcesPlugin.getWorkspace().getRoot();
				break;
			case PROJECT:
				startingPoint = file.getProject();
				break;
			case CONTAINER:
				startingPoint = file.getParent();
				break;
			case OUTGOING:
				// fall through, the difference between SELF and OUTGOING will only come later on
			case SELF:
				// fall through
			default:
				startingPoint = file;
				break;
		}
		return startingPoint;
	}

	public boolean hasChild(URI parent, URI candidate) {
		return dependencyGraph.hasChild(parent, candidate);
	}
}
