/*******************************************************************************
 * Copyright (c) 2020, 2021 Obeo.
 * 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
 *******************************************************************************/
package org.eclipse.acceleo.aql.ls.services.textdocument;

import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.Objects;
import java.util.stream.Collectors;

import org.eclipse.acceleo.ASTNode;
import org.eclipse.acceleo.Module;
import org.eclipse.acceleo.aql.location.AcceleoLocationLinkToAcceleo;
import org.eclipse.acceleo.aql.location.aql.AqlLocationLinkToAny;
import org.eclipse.acceleo.aql.location.aql.AqlLocationLinkToAql;
import org.eclipse.acceleo.aql.location.common.AbstractLocationLink;
import org.eclipse.acceleo.aql.ls.common.AcceleoLanguageServerPositionUtils;
import org.eclipse.acceleo.aql.parser.AcceleoAstResult;
import org.eclipse.acceleo.aql.parser.AcceleoAstUtils;
import org.eclipse.acceleo.aql.parser.AcceleoParser;
import org.eclipse.acceleo.query.ast.VariableDeclaration;
import org.eclipse.acceleo.query.runtime.IService;
import org.eclipse.acceleo.query.runtime.namespace.IQualifiedNameResolver;
import org.eclipse.acceleo.query.runtime.namespace.ISourceLocation;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EOperation;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.lsp4j.LocationLink;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;

/**
 * The part of the {@link AcceleoTextDocumentService} APIs that makes the link between
 * {@link AbstractLocationLink} provided by the Acceleo API, and the {@link LocationLink} required by the
 * LSP4J API.
 * 
 * @author Florent Latombe
 */
public class AcceleoLocationLinkResolver {

	/**
	 * The owning {@link AcceleoTextDocumentService}.
	 */
	private final AcceleoTextDocumentService owner;

	/**
	 * Constructor.
	 * 
	 * @param acceleoTextDocumentService
	 *            the (non-{@code null}) owning {@link AcceleoTextDocumentService}.
	 */
	public AcceleoLocationLinkResolver(AcceleoTextDocumentService acceleoTextDocumentService) {
		this.owner = Objects.requireNonNull(acceleoTextDocumentService);
	}

	/**
	 * Transforms an {@link AbstractLocationLink} from Acceleo into a corresponding {@link LocationLink} for
	 * LSP4J.
	 * 
	 * @param locationLinkToTransform
	 *            the (non-{@code null}) {@link AbstractLocationLink} to transform.
	 * @return the {@link LocationLink} corresponding to {@code locationLink}.
	 */
	public LocationLink transform(AbstractLocationLink<?, ?> locationLinkToTransform) {
		Objects.requireNonNull(locationLinkToTransform);

		final LocationLink locationLink;
		// Dispatch depending on the concrete type of link.
		if (locationLinkToTransform instanceof AcceleoLocationLinkToAcceleo) {
			locationLink = this.transform((AcceleoLocationLinkToAcceleo)locationLinkToTransform);
		} else if (locationLinkToTransform instanceof AqlLocationLinkToAql) {
			locationLink = this.transform((AqlLocationLinkToAql)locationLinkToTransform);
		} else if (locationLinkToTransform instanceof AqlLocationLinkToAny) {
			locationLink = this.transform((AqlLocationLinkToAny)locationLinkToTransform);
		} else {
			throw new UnsupportedOperationException("Unsupported " + AbstractLocationLink.class
					.getCanonicalName() + " implementation: " + locationLinkToTransform.toString());
		}
		return locationLink;
	}

	/**
	 * Transforms an {@link AcceleoLocationLinkToAcceleo} from Acceleo into a corresponding
	 * {@link LocationLink} for LSP4J.
	 * 
	 * @param acceleoLocationLinkToAcceleo
	 *            the (non-{@code null}) {@link AcceleoLocationLinkToAcceleo} to transform.
	 * @return the {@link LocationLink} corresponding to {@code acceleoLocationLinkToAcceleo}.
	 */
	private LocationLink transform(AcceleoLocationLinkToAcceleo acceleoLocationLinkToAcceleo) {
		ASTNode linkOrigin = acceleoLocationLinkToAcceleo.getOrigin();
		AcceleoTextDocument originTextDocument = getAcceleoTextDocumentContaining(linkOrigin);
		ASTNode linkOriginEquivalent = AcceleoAstUtils.getSelfOrEquivalentOf(linkOrigin, originTextDocument
				.getAcceleoAstResult());

		Range originSelectionRange = AcceleoLanguageServerPositionUtils.getRangeOf(linkOriginEquivalent,
				originTextDocument.getAcceleoAstResult());

		ASTNode destinationAcceleoNode = acceleoLocationLinkToAcceleo.getDestination();
		return this.createLocationLinkFromRangeToAcceleoDestination(originSelectionRange,
				destinationAcceleoNode);
	}

	/**
	 * Provides the {@link AcceleoTextDocument} containing the given Acceleo {@link ASTNode}.
	 * 
	 * @param astNode
	 *            the (non-{@code null}) {@link ASTNode}.
	 * @return the {@link AcceleoTextDocument} whose contents define the {@link Module} defining
	 *         {@code astNode}. {@code null} if it could not be determined.
	 */
	private AcceleoTextDocument getAcceleoTextDocumentContaining(ASTNode astNode) {
		Module containingModule = AcceleoAstUtils.getContainerModule(astNode);
		AcceleoTextDocument containingTextDocument = this.getTextDocumentDefining(containingModule);
		return containingTextDocument;
	}

	/**
	 * Provides the {@link AcceleoTextDocument} that defines the given Acceleo {@link Module}.
	 * 
	 * @param acceleoModule
	 *            the (non-{@code null}) {@link Module} we want to find the defining document of.
	 * @return the {@link AcceleoTextDocument} that defines {@code acceleoModule}. {@code null} if it could
	 *         not be determined.
	 */
	private AcceleoTextDocument getTextDocumentDefining(Module acceleoModule) {
		return this.owner.findTextDocumentDefining(acceleoModule);
	}

	/**
	 * Transforms an {@link AqlLocationLinkToAql} from AQL into a corresponding {@link LocationLink} for
	 * LSP4J.
	 * 
	 * @param aqlLocationLinkToAql
	 *            the (non-{@code null}) {@link AqlLocationLinkToAql} to transform.
	 * @return the {@link LocationLink} corresponding to {@code aqlLocationLinkToAql}.
	 */
	private LocationLink transform(AqlLocationLinkToAql aqlLocationLinkToAql) {
		EObject linkOrigin = aqlLocationLinkToAql.getOrigin();
		Range originSelectionRange = getRangeForAqlAstElement(linkOrigin);

		EObject linkDestination = aqlLocationLinkToAql.getDestination();
		return createLocationLinkFromRangeToAqlDestination(originSelectionRange, linkDestination);
	}

	/**
	 * Provides the "selection range" of an {@link EObject AQL AST element}
	 * ({@link org.eclipse.acceleo.query.ast.Expression} or {@link VariableDeclaration}).
	 * 
	 * @param aqlAstElement
	 *            the (non-{@code null}) AQL {@link org.eclipse.acceleo.query.ast.Expression} or
	 *            {@link VariableDeclaration}.
	 * @return the {@link Range} corresponding to {@code aqlAstElement}.
	 */
	private Range getRangeForAqlAstElement(EObject aqlAstElement) {
		final ASTNode acceleoNodeContainingLinkOrigin = getAcceleoAstNodeContainingAqlElement(aqlAstElement);
		AcceleoTextDocument originTextDocument = getAcceleoTextDocumentContaining(
				acceleoNodeContainingLinkOrigin);

		Range originSelectionRange;
		if (aqlAstElement instanceof org.eclipse.acceleo.query.ast.Expression) {
			org.eclipse.acceleo.query.ast.Expression originAqlExpression = (org.eclipse.acceleo.query.ast.Expression)aqlAstElement;
			org.eclipse.acceleo.query.ast.Expression originAqlExpressionEquivalent = AcceleoAstUtils
					.getSelfOrEquivalentOf(originAqlExpression, originTextDocument.getAcceleoAstResult());
			originSelectionRange = AcceleoLanguageServerPositionUtils.getRangeOf(
					originAqlExpressionEquivalent, originTextDocument.getAcceleoAstResult());
		} else if (aqlAstElement instanceof org.eclipse.acceleo.query.ast.VariableDeclaration) {
			org.eclipse.acceleo.query.ast.VariableDeclaration originAqlVariableDeclaration = (org.eclipse.acceleo.query.ast.VariableDeclaration)aqlAstElement;
			org.eclipse.acceleo.query.ast.VariableDeclaration originAqlVariableDeclarationEquivalent = AcceleoAstUtils
					.getSelfOrEquivalentOf(originAqlVariableDeclaration, originTextDocument
							.getAcceleoAstResult());
			originSelectionRange = AcceleoLanguageServerPositionUtils.getRangeOf(
					originAqlVariableDeclarationEquivalent, originTextDocument.getAcceleoAstResult());
		} else {
			// This should never happen.
			throw new IllegalStateException(
					"Expected link origin to be either an AQL Expression or an AQL Variable Declaration but it was: "
							+ aqlAstElement.toString() + ".");
		}
		return originSelectionRange;
	}

	/**
	 * Provides the {@link ASTNode} containing the given node from an AQL AST.
	 * 
	 * @param aqlElement
	 *            the (non-{@code null}) AQL element ({@link org.eclipse.acceleo.query.ast.Expression} or
	 *            {@link org.eclipse.acceleo.query.ast.VariableDeclaration}).
	 * @return the {@link ASTNode} containing {@code aqlElement}.
	 */
	private static ASTNode getAcceleoAstNodeContainingAqlElement(EObject aqlElement) {
		final ASTNode acceleoNodeContainingAqlElement;
		if (aqlElement instanceof org.eclipse.acceleo.query.ast.Expression) {
			org.eclipse.acceleo.query.ast.Expression originAqlExpression = (org.eclipse.acceleo.query.ast.Expression)aqlElement;
			acceleoNodeContainingAqlElement = AcceleoAstUtils.getContainerOfAqlAstElement(
					originAqlExpression);
		} else if (aqlElement instanceof org.eclipse.acceleo.query.ast.VariableDeclaration) {
			org.eclipse.acceleo.query.ast.VariableDeclaration originAqlVariableDeclaration = (org.eclipse.acceleo.query.ast.VariableDeclaration)aqlElement;
			acceleoNodeContainingAqlElement = AcceleoAstUtils.getContainerOfAqlAstElement(
					originAqlVariableDeclaration);
		} else {
			// This should never happen.
			throw new IllegalStateException(
					"Expected AQL element to be either an AQL Expression or an AQL Variable Declaration but it was: "
							+ aqlElement.toString() + ".");
		}
		return acceleoNodeContainingAqlElement;
	}

	/**
	 * Transforms an {@link AqlLocationLinkToAny} from AQL into a corresponding {@link LocationLink} for
	 * LSP4J.
	 * 
	 * @param aqlLocationLinkToAny
	 *            the (non-{@code null}) {@link AqlLocationLinkToAny} to transform.
	 * @return the {@link LocationLink} corresponding to {@code aqlLocationLinkToAny}.
	 */
	private LocationLink transform(AqlLocationLinkToAny aqlLocationLinkToAny) {
		EObject aqlOrigin = aqlLocationLinkToAny.getOrigin();
		Range originSelectionRange = getRangeForAqlAstElement(aqlOrigin);
		Object destination = aqlLocationLinkToAny.getDestination();
		return createLocationLinkFromRangeToAnyDestination(aqlOrigin, originSelectionRange, destination);
	}

	/**
	 * Creates a {@link LocationLink} from the given {@link Range} to a destination of undetermined nature.
	 * 
	 * @param linkOrigin
	 *            the (non-{@code null}) origin {@link EObject} of the link to create.
	 * @param originSelectionRange
	 *            the (non-{@code null}) origin selection {@link Range} of the link.
	 * @param destination
	 *            the (non-{@code null}) destination of the link.
	 * @return the {@link LocationLink} from that points from {@code originSelectionRange} to
	 *         {@code destination}.
	 */
	private LocationLink createLocationLinkFromRangeToAnyDestination(EObject linkOrigin,
			Range originSelectionRange, Object destination) {
		LocationLink locationLink;
		if (destination instanceof ASTNode) {
			ASTNode destinationNode = (ASTNode)destination;
			locationLink = createLocationLinkFromRangeToAcceleoDestination(originSelectionRange,
					destinationNode);
		} else if (destination instanceof org.eclipse.acceleo.query.ast.Expression
				|| destination instanceof org.eclipse.acceleo.query.ast.VariableDeclaration) {
			// This should probably not happen due to how the relation between Acceleo and AQL is structured.
			// i.e. both Acceleo and AQL are aware of AQL so links with an AQL destination should not be
			// represented as links to "any" destination.
			// Still, support it just in case...
			locationLink = createLocationLinkFromRangeToAqlDestination(originSelectionRange,
					(EObject)destination);
		} else if (destination instanceof IService<?>) {
			locationLink = createLocationLinkFromRangeToServiceDestination(linkOrigin, originSelectionRange,
					(IService<?>)destination);
		} else if (destination instanceof java.lang.Class<?>) {
			locationLink = createLocationLinkFromRangeToJavaClassDestination(linkOrigin, originSelectionRange,
					(Class<?>)destination);
		} else if (destination instanceof Method) {
			locationLink = createLocationLinkFromRangeToJavaMethodDestination(linkOrigin,
					originSelectionRange, (Method)destination);
		} else if (destination instanceof EObject) {
			locationLink = createLocationLinkFromRangeToEObjectDestination(linkOrigin, originSelectionRange,
					(EObject)destination);
		} else {
			// Implement more cases if we have links that link to other types of destination: maybe Java?
			// This depends on how we have bound variables in the environment passed to the AQL evaluator.
			throw new IllegalStateException("Trying to create a link to destination: " + destination
					+ " but this type of destination is not supported.");
		}
		return locationLink;
	}

	/**
	 * Creates a {@link LocationLink} from the given {@link Range} that points to the given AQL element.
	 * 
	 * @param originSelectionRange
	 *            the (non-{@code null}) origin selection {@link Range} of the created link.
	 * @param aqlDestination
	 *            the (non-{@code null}) destination {@link EObject} that must be an AQL element
	 *            ({@link org.eclipse.acceleo.query.ast.Expression} or {@link VariableDeclaration}).
	 * @return the created {@link LocationLink}.
	 */
	private LocationLink createLocationLinkFromRangeToAqlDestination(Range originSelectionRange,
			EObject aqlDestination) {
		final ASTNode acceleoNodeContainingLinkDestination = getAcceleoAstNodeContainingAqlElement(
				aqlDestination);
		AcceleoTextDocument destinationTextDocument = getAcceleoTextDocumentContaining(
				acceleoNodeContainingLinkDestination);

		// Link target parameters.
		String targetDocumentUri = destinationTextDocument.getUri().toString();
		final Range targetRange = getRangeForAqlAstElement(aqlDestination);
		// FIXME: we probably only want to select part of the target.
		Range targetSelectionRange = targetRange;

		LocationLink locationLink = new LocationLink(targetDocumentUri, targetRange, targetSelectionRange,
				originSelectionRange);
		return locationLink;
	}

	/**
	 * Creates a {@link LocationLink} from the given {@link Range} to the given Acceleo {@link ASTNode}
	 * destination.
	 * 
	 * @param originSelectionRange
	 *            the (non-{@code null}) origin selection {@link Range}.
	 * @param destinationNode
	 *            the (non-{@code null}) destination {@link ASTNode}.
	 * @return the {@link LocationLink} from {@code originSelectionRange} to {@code destinationNode}.
	 */
	private LocationLink createLocationLinkFromRangeToAcceleoDestination(Range originSelectionRange,
			ASTNode destinationNode) {
		AcceleoTextDocument destinationTextDocument = this.getAcceleoTextDocumentContaining(destinationNode);
		if (destinationTextDocument == null) {
			// This should never happen because we a transforming a link that was provided by the
			// AcceleoLocator, so if a link destination could not be determined then the locator would not
			// have returned a link.
			throw new IllegalArgumentException("Could not find the Acceleo document that defines "
					+ destinationNode.toString());
		}
		AcceleoAstResult destinationAcceleoAstResult = destinationTextDocument.getAcceleoAstResult();

		// Note: the destination ASTNode comes from a parsing that is not necessarily the one known by the
		// destination text document, therefore we have to be able to locate the equivalent of an ASTNode in
		// another AcceleoAstResult of the same Acceleo file.
		ASTNode destinationNodeInDestinationTextDocument = AcceleoAstUtils.getSelfOrEquivalentOf(
				destinationNode, destinationAcceleoAstResult);
		Range targetRange = AcceleoLanguageServerPositionUtils.getRangeOf(
				destinationNodeInDestinationTextDocument, destinationAcceleoAstResult);
		// FIXME: we probably only want to select part of the target.
		Range targetSelectionRange = targetRange;

		// Link target parameters.
		Module destinationModule = destinationTextDocument.getAcceleoAstResult().getModule();
		String qualifiedName = URI.decode(destinationModule.eResource().getURI().toString().replaceFirst(
				AcceleoParser.ACCELEOENV_URI_PROTOCOL, ""));

		// TODO this is a more general matter, it should be performed in the AcceleoWorkspace
		// open source file whenever it's possible
		java.net.URI targetDocumentUri;
		try {
			final IQualifiedNameResolver resolver = destinationTextDocument.getQueryEnvironment()
					.getLookupEngine().getResolver();
			targetDocumentUri = resolver.getSourceURL(qualifiedName).toURI();
		} catch (

		URISyntaxException e) {
			targetDocumentUri = null;
		}
		if (targetDocumentUri == null) {
			targetDocumentUri = destinationTextDocument.getUri();
		}

		LocationLink locationLink = new LocationLink(targetDocumentUri.toString(), targetRange,
				targetSelectionRange, originSelectionRange);
		return locationLink;
	}

	/**
	 * Creates a {@link LocationLink} from the given {@link Range} to the given Java {@link Class}
	 * destination.
	 * 
	 * @param linkOrigin
	 *            the (non-{@code null}) origin {@link EObject} of the link.
	 * @param originSelectionRange
	 *            the (non-{@code null}) origin selection {@link Range}.
	 * @param destinationJavaClass
	 *            the (non-{@code null}) destination Java {@link Class}.
	 * @return the {@link LocationLink} from {@code originSelectionRange} to {@code destinationJavaClass}.
	 */
	private LocationLink createLocationLinkFromRangeToJavaClassDestination(EObject linkOrigin,
			Range originSelectionRange, Class<?> destinationJavaClass) {
		ASTNode acceleoAstNode = getAcceleoAstNodeContainingAqlElement(linkOrigin);
		AcceleoTextDocument acceleoTextDocument = this.getAcceleoTextDocumentContaining(acceleoAstNode);

		// TODO: implement link to Java sources.
		// We probably want to retrieve the Java context (classpath, etc.) of the AcceleoTextDocument, and use
		// it to retrieve the location of the Java class. Most of this mechanism should be implemented for the
		// resolution of modules anyway.

		// FIXME: temporary placeholder so it still sort of works
		String urlPrefix = "https://docs.oracle.com/javase/8/docs/api/";
		String urlPostfix = ".html";
		String classNameUrlPart = destinationJavaClass.getCanonicalName().replace('.', '/');
		String urlToJavadoc = urlPrefix + classNameUrlPart + urlPostfix;

		String targetUri = urlToJavadoc;
		Range targetRange = new Range(new Position(0, 0), new Position(0, 0));
		Range targetSelectionRange = targetRange;

		LocationLink locationLink = new LocationLink(targetUri, targetRange, targetSelectionRange,
				originSelectionRange);
		return locationLink;
	}

	/**
	 * Creates a {@link LocationLink} from the given {@link Range} to the given {@link IService} destination.
	 * 
	 * @param linkOrigin
	 *            the (non-{@code null}) origin {@link EObject} of the link.
	 * @param originSelectionRange
	 *            the (non-{@code null}) origin selection {@link Range}.
	 * @param destinationService
	 *            the (non-{@code null}) destination {@link IService}.
	 * @return the {@link LocationLink} from {@code originSelectionRange} to {@code destinationService}.
	 */
	private LocationLink createLocationLinkFromRangeToServiceDestination(EObject linkOrigin,
			Range originSelectionRange, IService<?> destinationService) {
		ASTNode acceleoAstNode = getAcceleoAstNodeContainingAqlElement(linkOrigin);
		AcceleoTextDocument acceleoTextDocument = this.getAcceleoTextDocumentContaining(acceleoAstNode);

		final IQualifiedNameResolver resolver = acceleoTextDocument.getQueryEnvironment().getLookupEngine()
				.getResolver();

		final ISourceLocation sourceLocation = resolver.getSourceLocation(destinationService);
		final LocationLink locationLink;
		if (sourceLocation != null) {
			Position targetRangeStart = new Position(sourceLocation.getRange().getStart().getLine(),
					sourceLocation.getRange().getStart().getColumn());
			Position targetRangeEnd = new Position(sourceLocation.getRange().getEnd().getLine(),
					sourceLocation.getRange().getEnd().getColumn());
			Range targetRange = new Range(targetRangeStart, targetRangeEnd);

			Position targetSelectionRangeStart = new Position(sourceLocation.getIdentifierRange().getStart()
					.getLine(), sourceLocation.getIdentifierRange().getStart().getColumn());
			Position targetSelectionRangeEnd = new Position(sourceLocation.getIdentifierRange().getEnd()
					.getLine(), sourceLocation.getIdentifierRange().getEnd().getColumn());
			Range targetSelectionRange = new Range(targetSelectionRangeStart, targetSelectionRangeEnd);

			locationLink = new LocationLink(sourceLocation.getSourceURL().toString(), targetRange,
					targetSelectionRange, originSelectionRange);
		} else {
			locationLink = createLocationLinkFromRangeToAnyDestination(linkOrigin, originSelectionRange,
					destinationService.getOrigin());
		}

		return locationLink;
	}

	/**
	 * Creates a {@link LocationLink} from the given {@link Range} to the given Java {@link Method}
	 * destination.
	 * 
	 * @param linkOrigin
	 *            the (non-{@code null}) origin {@link EObject} of the link.
	 * @param originSelectionRange
	 *            the (non-{@code null}) origin selection {@link Range}.
	 * @param destinationJavaMethod
	 *            the (non-{@code null}) destination Java {@link Method}.
	 * @return the {@link LocationLink} from {@code originSelectionRange} to {@code destinationJavaMethod}.
	 */
	private LocationLink createLocationLinkFromRangeToJavaMethodDestination(EObject linkOrigin,
			Range originSelectionRange, Method destinationJavaMethod) {
		ASTNode acceleoAstNode = getAcceleoAstNodeContainingAqlElement(linkOrigin);
		AcceleoTextDocument acceleoTextDocument = this.getAcceleoTextDocumentContaining(acceleoAstNode);

		// TODO: implement link to Java sources.
		// We probably want to retrieve the Java context (classpath, etc.) of the AcceleoTextDocument, and use
		// it to retrieve the location of the Java method. Most of this mechanism should be implemented for
		// the
		// resolution of modules anyway.

		// FIXME: temporary placeholder so it still sort of works
		String urlPrefix = "https://docs.oracle.com/javase/8/docs/api/";
		String urlPostfix = ".html";
		String classNameUrlPart = destinationJavaMethod.getDeclaringClass().getCanonicalName().replace('.',
				'/');
		String methodNameUrlPart = destinationJavaMethod.getName();
		String methodParametersUrlPart = Arrays.asList(destinationJavaMethod.getParameterTypes()).stream()
				.map(parameterType -> parameterType.getSimpleName()).collect(Collectors.joining("-"));
		String urlToJavadoc = urlPrefix + classNameUrlPart + urlPostfix + "#" + methodNameUrlPart + "-"
				+ methodParametersUrlPart;

		String targetUri = urlToJavadoc;
		Range targetRange = new Range(new Position(0, 0), new Position(0, 0));
		Range targetSelectionRange = targetRange;

		LocationLink locationLink = new LocationLink(targetUri, targetRange, targetSelectionRange,
				originSelectionRange);
		return locationLink;
	}

	/**
	 * Creates a {@link LocationLink} from the given {@link Range} to the given EMF {@link EOperation}
	 * destination.
	 * 
	 * @param linkOrigin
	 *            the (non-{@code null}) origin {@link EObject} of the link.
	 * @param originSelectionRange
	 *            the (non-{@code null}) origin selection {@link Range}.
	 * @param destinationEObject
	 *            the (non-{@code null}) destination EMF {@link EObject}.
	 * @return the {@link LocationLink} from {@code originSelectionRange} to {@code destinationEObject}.
	 */
	private LocationLink createLocationLinkFromRangeToEObjectDestination(EObject linkOrigin,
			Range originSelectionRange, EObject destinationEObject) {
		ASTNode acceleoAstNode = getAcceleoAstNodeContainingAqlElement(linkOrigin);
		AcceleoTextDocument acceleoTextDocument = this.getAcceleoTextDocumentContaining(acceleoAstNode);

		// TODO: implement link to EMF metamodel elements.
		// We probably want to retrieve the Java/EMF context (classpath, etc.) of the AcceleoTextDocument, and
		// use
		// it to retrieve the location of the EMF operation. Most of this mechanism should be implemented for
		// the
		// resolution of modules anyway.

		// FIXME: temporary placeholder so it still sort of works
		String url = EcoreUtil.getURI(destinationEObject).toString();

		String targetUri = url;
		Range targetRange = new Range(new Position(0, 0), new Position(0, 0));
		Range targetSelectionRange = targetRange;

		LocationLink locationLink = new LocationLink(targetUri, targetRange, targetSelectionRange,
				originSelectionRange);
		return locationLink;
	}
}
