/*******************************************************************************
 * Copyright (c) 2013, 2017 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
 *     Martin Fleck - bug 507177
 *******************************************************************************/
package org.eclipse.emf.compare.uml2.internal.postprocessor;

import static com.google.common.base.Predicates.instanceOf;

import com.google.common.base.Predicate;
import com.google.common.collect.Collections2;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.SetMultimap;

import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.emf.compare.Comparison;
import org.eclipse.emf.compare.Diff;
import org.eclipse.emf.compare.DifferenceKind;
import org.eclipse.emf.compare.Match;
import org.eclipse.emf.compare.ReferenceChange;
import org.eclipse.emf.compare.ResourceAttachmentChange;
import org.eclipse.emf.compare.internal.postprocessor.factories.AbstractChangeFactory;
import org.eclipse.emf.compare.internal.utils.ComparisonUtil;
import org.eclipse.emf.compare.internal.utils.DiffUtil;
import org.eclipse.emf.compare.uml2.internal.StereotypeApplicationChange;
import org.eclipse.emf.compare.uml2.internal.UMLDiff;
import org.eclipse.emf.compare.utils.EMFComparePredicates;
import org.eclipse.emf.compare.utils.MatchUtil;
import org.eclipse.emf.compare.utils.ReferenceUtil;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EStructuralFeature.Setting;
import org.eclipse.emf.ecore.util.Switch;
import org.eclipse.uml2.common.util.UML2Util;
import org.eclipse.uml2.uml.util.UMLSwitch;

/**
 * Factory of UML difference extensions.
 * 
 * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
 */
public abstract class AbstractUMLChangeFactory extends AbstractChangeFactory {

	/**
	 * UML Switch to get the discriminants (if they exist) related to the given business object.
	 * 
	 * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
	 */
	protected class DiscriminantsGetter extends UMLSwitch<Set<EObject>> {

		@Override
		public Set<EObject> defaultCase(EObject object) {
			return defaultCaseForDiscriminantsGetter(this, object);
		}
	}

	/**
	 * Setting to define a candidate to the seeking of refining differences.
	 * 
	 * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
	 */
	private class RefiningCandidate implements Setting {

		/** The business object containing the structural feature. */
		private EObject holdingObject;

		/** The structural feature. */
		private EStructuralFeature eStructuralFeature;

		/**
		 * Constructor to use if the origin of the target value is unknown (neither holding object nor
		 * structural feature). This candidate will be considered as a containment reference to the target
		 * value.
		 */
		RefiningCandidate() {
		}

		/**
		 * Constructor.
		 * 
		 * @param holdingObject
		 *            The business object containing the structural feature to the target value.
		 * @param feature
		 *            the structural feature to the target value.
		 */
		RefiningCandidate(EObject holdingObject, EStructuralFeature feature) {
			this.holdingObject = holdingObject;
			this.eStructuralFeature = feature;
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.ecore.EStructuralFeature.Setting#getEObject()
		 */
		public EObject getEObject() {
			return holdingObject;
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see org.eclipse.emf.ecore.EStructuralFeature.Setting#getEStructuralFeature()
		 */
		public EStructuralFeature getEStructuralFeature() {
			return eStructuralFeature;
		}

		/**
		 * {@inheritDoc}<br>
		 * No use. Return null.
		 * 
		 * @see org.eclipse.emf.ecore.EStructuralFeature.Setting#get(boolean)
		 */
		public Object get(boolean resolve) {
			return null;
		}

		/**
		 * {@inheritDoc}<br>
		 * No use. Do nothing.
		 * 
		 * @see org.eclipse.emf.ecore.EStructuralFeature.Setting#set(java.lang.Object)
		 */
		public void set(Object newValue) {
		}

		/**
		 * {@inheritDoc}<br>
		 * No use. Return false.
		 * 
		 * @see org.eclipse.emf.ecore.EStructuralFeature.Setting#isSet()
		 */
		public boolean isSet() {
			return false;
		}

		/**
		 * {@inheritDoc}<br>
		 * No use. Do nothing.
		 * 
		 * @see org.eclipse.emf.ecore.EStructuralFeature.Setting#unset()
		 */
		public void unset() {
		}

	}

	/**
	 * It defines the predicate to keep only the differences which match with the given settings (refining
	 * candidates).
	 * 
	 * @author <a href="mailto:cedric.notot@obeo.fr">Cedric Notot</a>
	 */
	private class DifferencesOnRefiningCandidates implements Predicate<Diff> {

		/** The comparison. */
		private final Comparison fComparison;

		/** The specified settings. */
		private final SetMultimap<Object, RefiningCandidate> fRefiningCandidates;

		/**
		 * Constructor.
		 * 
		 * @param comparison
		 *            The comparison.
		 * @param refiningCandidates
		 *            The specified settings.
		 */
		DifferencesOnRefiningCandidates(Comparison comparison,
				SetMultimap<Object, RefiningCandidate> refiningCandidates) {
			fComparison = comparison;
			fRefiningCandidates = refiningCandidates;
		}

		/**
		 * {@inheritDoc}
		 * 
		 * @see com.google.common.base.Predicate#apply(java.lang.Object)
		 */
		public boolean apply(final Diff input) {
			boolean result = false;
			Object value = MatchUtil.getValue(input);
			Set<RefiningCandidate> settings = fRefiningCandidates.get(value);
			if (settings.size() > 0) {
				// Keep the current difference if one specified candidate setting match with it at least.
				result = Iterables.any(settings, new Predicate<EStructuralFeature.Setting>() {
					public boolean apply(EStructuralFeature.Setting setting) {
						boolean res = true;
						if (setting.getEObject() != null) {
							// Keep if match of the current difference is the same as the match of the
							// specified
							// holding object in the setting...
							res = input.getMatch() == fComparison.getMatch(setting.getEObject());
						}
						if (setting.getEStructuralFeature() != null) {
							// ... and the structural feature is the same as the specified one in the
							// setting.
							res = res && MatchUtil.getStructuralFeature(input) == setting
									.getEStructuralFeature();
						} else {
							// If no structural feature specified, check that the reference of the
							// difference is containment.
							EStructuralFeature diffFeature = MatchUtil.getStructuralFeature(input);
							res = res && DiffUtil.isContainmentReference(diffFeature);
						}
						return res;
					}
				});
			}
			return result;
		}
	}

	/**
	 * {@inheritDoc}<br>
	 * It checks that the given difference concerns the creation of an UML macroscopic change. <br>
	 * It verifies this difference is not a part of a macroscopic ADD or DELETE not to have a macroscopic
	 * ADD/DELETE plus a macroscopic CHANGE.<br>
	 * At last, the first matching difference allows to create a complete macroscopic change (with all the
	 * refining differences. So, the next matching ones will not be held to avoid to create duplicated
	 * macroscopic changes.
	 * 
	 * @see org.eclipse.emf.compare.internal.postprocessor.factories.AbstractChangeFactory#handles(org.eclipse.emf.compare.Diff)
	 */
	@Override
	public boolean handles(Diff input) {
		return super.handles(input) && !isChangeOnAddOrDelete(input) && input.getRefines().isEmpty();
	}

	/**
	 * {@inheritDoc}<br>
	 * It creates the macroscopic change and builds it. It sets its discriminant (main business object to
	 * focus). <br>
	 * For a macroscopic ADD/DELETE, it sets its eReference (the reference of the main refining difference (on
	 * the discriminant)).
	 * 
	 * @see org.eclipse.emf.compare.internal.postprocessor.factories.IChangeFactory#create(org.eclipse.emf.compare.Diff)
	 */
	@Override
	public Diff create(Diff input) {
		Diff ret = super.create(input);
		if (ret instanceof UMLDiff) {
			((UMLDiff)ret).setDiscriminant(getDiscriminant(input));
			setEReference(input, (UMLDiff)ret);
		}
		return ret;
	}

	/**
	 * {@inheritDoc}<br>
	 * During the building process, it sets the differences refining the macroscopic one.
	 * 
	 * @see org.eclipse.emf.compare.internal.postprocessor.factories.AbstractChangeFactory#setRefiningChanges(org.eclipse.emf.compare.Diff,
	 *      org.eclipse.emf.compare.DifferenceKind, org.eclipse.emf.compare.Diff)
	 */
	@Override
	public void setRefiningChanges(Diff extension, DifferenceKind extensionKind, Diff refiningDiff) {
		SetMultimap<Object, RefiningCandidate> refiningCandidates = LinkedHashMultimap.create();

		Comparison comparison = ComparisonUtil.getComparison(refiningDiff);
		// From each discriminant business object, ...
		Set<EObject> discriminants = getDiscriminants(refiningDiff);
		for (EObject discriminant : discriminants) {
			// ... define all the business objects which may be impacted by refining differences specifying
			// the
			// settings (holding object and structural feature) which link them.
			defineRefiningCandidates(discriminant, refiningCandidates);
			// For each of these business objects, find the impacted differences, keeping only the ones
			// matching the defined settings.
			for (Object elt : refiningCandidates.keys()) {
				beRefinedByCrossReferences(comparison, elt, (UMLDiff)extension,
						new DifferencesOnRefiningCandidates(comparison, refiningCandidates));
			}
		}
	}

	/**
	 * {@inheritDoc}
	 * 
	 * @see org.eclipse.emf.compare.internal.postprocessor.factories.IChangeFactory#getParentMatch(org.eclipse.emf.compare.Diff)
	 */
	@Override
	public Match getParentMatch(Diff input) {
		return getParentMatch(ComparisonUtil.getComparison(input), input);
	}

	/**
	 * Get the discriminant business objects concerned by the given difference.<br>
	 * 
	 * @param input
	 *            The given difference.
	 * @return The set of discriminant business objects.
	 */
	protected Set<EObject> getDiscriminants(Diff input) {
		EObject value;
		// Get the business object to focus as starting point to find all the discriminant objects.
		if (input instanceof ReferenceChange && ((ReferenceChange)input).getReference().isContainment()) {
			value = ((ReferenceChange)input).getValue();
		} else {
			value = MatchUtil.getContainer(ComparisonUtil.getComparison(input), input);
		}
		return getDiscriminants(value);
	}

	/**
	 * Get the cross referenced object (setting) matching with given predicate, from the given business
	 * object.
	 * 
	 * @param object
	 *            The given object from which we seek a cross referenced object.
	 * @param predicate
	 *            The predicate.
	 * @return the setting containing the cross referenced object.
	 */
	protected Setting getInverseReferences(EObject object, Predicate<EStructuralFeature.Setting> predicate) {
		final Iterator<EStructuralFeature.Setting> crossReferences = UML2Util.getInverseReferences(object)
				.iterator();
		return Iterators.find(crossReferences, predicate, null);
	}

	/**
	 * {@inheritDoc}<br>
	 * The given reference change is related to a macroscopic ADD if... <br>
	 * - Its reference is a containment one<br>
	 * - Its value is the specified discriminant<br>
	 * - Its kind is ADD
	 * 
	 * @see org.eclipse.emf.compare.internal.postprocessor.factories.AbstractChangeFactory#isRelatedToAnExtensionAdd(org.eclipse.emf.compare.ReferenceChange)
	 */
	@Override
	protected boolean isRelatedToAnExtensionAdd(ReferenceChange input) {
		return input.getReference().isContainment() && input.getValue() == getDiscriminant(input)
				&& input.getKind() == DifferenceKind.ADD;
	}

	/**
	 * {@inheritDoc}<br>
	 * The given reference change is related to a macroscopic DELETE if... <br>
	 * - Its reference is a containment one<br>
	 * - Its value is the specified discriminant<br>
	 * - Its kind is DELETE
	 * 
	 * @see org.eclipse.emf.compare.internal.postprocessor.factories.AbstractChangeFactory#isRelatedToAnExtensionDelete(org.eclipse.emf.compare.ReferenceChange)
	 */
	@Override
	protected boolean isRelatedToAnExtensionDelete(ReferenceChange input) {
		return input.getReference().isContainment() && input.getValue() == getDiscriminant(input)
				&& input.getKind() == DifferenceKind.DELETE;
	}

	// No UML macroscopic change anymore for any changes on discriminants.
	// /**
	// * {@inheritDoc}<br>
	// * The given reference change is related to a macroscopic CHANGE if discriminants are found from the
	// * business impacted object.
	// *
	// * @see
	// org.eclipse.emf.compare.internal.postprocessor.factories.AbstractChangeFactory#isRelatedToAnExtensionChange(org.eclipse.emf.compare.ReferenceChange)
	// */
	// @Override
	// protected boolean isRelatedToAnExtensionChange(ReferenceChange input) {
	// return !getDiscriminants(MatchUtil.getContainer(input.getMatch().getComparison(), input)).isEmpty();
	// }

	// TODO: Add isRelatedToAnExtensionChange(AttributeChange input)

	/**
	 * Get the switch which allows to return the set of discriminants from any business object.<br>
	 * 
	 * @return The switch to get the discriminants.
	 */
	protected abstract Switch<Set<EObject>> getDiscriminantsGetter();

	/**
	 * Get the main discriminant business object concerned by the given difference. Usually, it will be one of
	 * the ones returned by {@link AbstractUMLChangeFactory#getDiscriminants(Diff)}
	 * 
	 * @param input
	 *            The difference.
	 * @return The discriminant.
	 */
	protected abstract EObject getDiscriminant(Diff input);

	/**
	 * Default method in discriminant getters ({@link DiscriminantsGetter}) to find discriminants.
	 * 
	 * @param discriminantsGetter
	 *            The specific discriminant getter.
	 * @param object
	 *            The current object as starting point to the seeking of discriminants.
	 * @return The set of discriminants.
	 */
	protected static Set<EObject> defaultCaseForDiscriminantsGetter(Switch<Set<EObject>> discriminantsGetter,
			EObject object) {
		Set<EObject> result = new LinkedHashSet<EObject>();
		EObject parent = object.eContainer();
		if (parent != null) {
			result.addAll(discriminantsGetter.doSwitch(parent));
		}
		return result;
	}

	/**
	 * Get the discriminant business objects from the given one.
	 * 
	 * @param value
	 *            The given business object.
	 * @return The set of discriminants.
	 */
	private Set<EObject> getDiscriminants(EObject value) {
		Switch<Set<EObject>> discriminantGetter = getDiscriminantsGetter();
		return discriminantGetter.doSwitch(value);
	}

	/**
	 * It defines the business objects to scan and their settings to find the matching refining differences,
	 * from the given discriminant business object.
	 * 
	 * @param discriminant
	 *            The given discriminant.
	 * @param refiningCandidates
	 *            Map business object to the list of settings to keep during the research of refining
	 *            differences. This map must not be null.
	 */
	private void defineRefiningCandidates(EObject discriminant,
			Multimap<Object, RefiningCandidate> refiningCandidates) {
		// The discriminant itself is a candidate, only on an incoming containment reference.
		refiningCandidates.put(discriminant, new RefiningCandidate());
		// Delegation to a recursive method to find the other candidates.
		defineRefiningCandidatesFrom(discriminant, refiningCandidates);
	}

	/**
	 * It defines the business objects to scan and their settings to find the matching refining differences,
	 * from the given discriminant business object. It ignores the given object and searches candidates in all
	 * the referenced objects from it and all the attributes. A recursion is made between containment
	 * references, to scan all the children. Opposite references are taken into account for the candidates.
	 * 
	 * @param discriminant
	 *            The given discriminant.
	 * @param refiningCandidates
	 *            Map business object to the list of settings to keep during the research of refining
	 *            differences. This map must not be null.
	 */
	private void defineRefiningCandidatesFrom(EObject discriminant,
			Multimap<Object, RefiningCandidate> refiningCandidates) {
		Iterator<EStructuralFeature> outgoingFeatures = discriminant.eClass().getEAllStructuralFeatures()
				.iterator();
		while (outgoingFeatures.hasNext()) {
			EStructuralFeature outgoingFeature = outgoingFeatures.next();
			// For each referenced objects and attributes...
			Iterator<Object> values = ReferenceUtil.getAsList(discriminant, outgoingFeature).iterator();
			while (values.hasNext()) {
				Object value = values.next();
				// ... register it with its setting.
				refiningCandidates.put(value, new RefiningCandidate(discriminant, outgoingFeature));
				if (outgoingFeature instanceof EReference && value instanceof EObject) {
					if (((EReference)outgoingFeature).isContainment()) {
						// Recursion on children
						defineRefiningCandidatesFrom((EObject)value, refiningCandidates);
					} else if (((EReference)outgoingFeature).getEOpposite() != null) {
						// Take opposite references
						refiningCandidates.put(discriminant, new RefiningCandidate((EObject)value,
								((EReference)outgoingFeature).getEOpposite()));
					}
				}
			}

		}
	}

	/**
	 * Get the match in which the macroscopic change should be added.<br>
	 * Take the same match of the given difference. If it is related to a macroscopic CHANGE, take the match
	 * of the discriminant.
	 * 
	 * @param comparison
	 *            The current comparison.
	 * @param input
	 *            The difference to locate.
	 * @return The containing match.
	 */
	private Match getParentMatch(Comparison comparison, Diff input) {
		if (getRelatedExtensionKind(input) == DifferenceKind.CHANGE) {
			return comparison.getMatch(getDiscriminant(input));
		} else {
			return input.getMatch();
		}
	}

	/**
	 * Fill the refining link of the given refined extension (macroscopic change) with the found differences
	 * on the given object (lookup), according to the given predicate.
	 * 
	 * @param comparison
	 *            The comparison.
	 * @param lookup
	 *            The object on which differences have to be found.
	 * @param refinedExtension
	 *            The macroscopic change to set (refinedBy link)
	 * @param p
	 *            The predicate.
	 */
	private void beRefinedByCrossReferences(Comparison comparison, Object lookup, UMLDiff refinedExtension,
			Predicate<Diff> p) {
		if (lookup instanceof EObject) {
			List<Diff> crossReferences = findCrossReferences(comparison, (EObject)lookup, p);
			refinedExtension.getRefinedBy().addAll(Collections2.filter(crossReferences,
					EMFComparePredicates.fromSide(refinedExtension.getSource())));
		}
	}

	/**
	 * Set the eReference link in the given UML difference, from the given unit difference.
	 * 
	 * @param input
	 *            The unit difference.
	 * @param umlDiff
	 *            The UML difference (macroscopic change).
	 */
	private void setEReference(Diff input, UMLDiff umlDiff) {
		if (getRelatedExtensionKind(input) == DifferenceKind.ADD
				|| getRelatedExtensionKind(input) == DifferenceKind.DELETE) {
			if (input instanceof ReferenceChange) {
				umlDiff.setEReference(((ReferenceChange)input).getReference());
			} else if (input instanceof ResourceAttachmentChange
					&& umlDiff instanceof StereotypeApplicationChange) {
				// the resource attachment concerns the stereotype application itself.
				// The reference is located "below" that.
				final List<Diff> candidates = input.getMatch().getDifferences();
				// Little chance that there is more is that the input ... and what we seek.
				for (Diff candidate : candidates) {
					if (candidate instanceof ReferenceChange) {
						umlDiff.setEReference(((ReferenceChange)candidate).getReference());
					}
				}
			}
		}
	}

	/**
	 * It checks if the given difference concerns is related to a macroscopic CHANGE within a macroscopic
	 * ADD/DELETE.
	 * 
	 * @param input
	 *            The difference.
	 * @return True if it is related to a CHANGE in an ADD/DELETE.
	 */
	protected boolean isChangeOnAddOrDelete(Diff input) {
		if (getRelatedExtensionKind(input) == DifferenceKind.CHANGE) {
			final Comparison comparison = ComparisonUtil.getComparison(input);
			final EObject discriminant = getDiscriminant(input);
			if (discriminant != null) {
				return isChangeOnAddOrDelete(input, comparison, discriminant);
			}
		}
		return false;
	}

	/**
	 * It checks if the given difference concerns is related to a macroscopic CHANGE within a macroscopic
	 * ADD/DELETE.
	 * 
	 * @param input
	 *            The given difference.
	 * @param comparison
	 *            the related comparison.
	 * @param discriminant
	 *            The discriminant found for the given difference.
	 * @return True if it is related to a CHANGE in an ADD/DELETE.
	 */
	private boolean isChangeOnAddOrDelete(Diff input, final Comparison comparison,
			final EObject discriminant) {
		boolean result = false;
		Match match = comparison.getMatch(discriminant);
		if (match != null
				&& Iterables.any(match.getDifferences(), instanceOf(ResourceAttachmentChange.class))) {
			result = true;
		}
		if (!result) {
			final List<Diff> candidates = comparison.getDifferences(discriminant);
			for (Diff diff : candidates) {
				if (diff == input) {
					// ignore this one
				} else {
					DifferenceKind relatedExtensionKind = getRelatedExtensionKind(diff);
					if ((relatedExtensionKind == DifferenceKind.ADD
							|| relatedExtensionKind == DifferenceKind.DELETE)
							&& getDiscriminant(diff) == discriminant) {
						result = true;
						break;
					}
				}
			}
		}
		return result;
	}

}
