/*******************************************************************************
 * Copyright (c) 2011, 2012 Oracle. All rights reserved.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
 * which accompanies this distribution.
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *     Oracle - initial API and implementation
 *
 ******************************************************************************/
package org.eclipse.jpt.jpa.ui.internal.jpql;

import java.util.Collections;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.core.CompletionContext;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.IExtendedModifier;
import org.eclipse.jdt.core.dom.MemberValuePair;
import org.eclipse.jdt.core.dom.NormalAnnotation;
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.ui.text.java.ContentAssistInvocationContext;
import org.eclipse.jdt.ui.text.java.IJavaCompletionProposalComputer;
import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jpt.common.core.internal.utility.jdt.ASTTools;
import org.eclipse.jpt.common.core.utility.TextRange;
import org.eclipse.jpt.common.utility.internal.StringTools;
import org.eclipse.jpt.jpa.core.JpaFile;
import org.eclipse.jpt.jpa.core.JpaStructureNode;
import org.eclipse.jpt.jpa.core.JptJpaCorePlugin;
import org.eclipse.jpt.jpa.core.context.NamedQuery;
import org.eclipse.jpt.jpa.core.context.Query;
import org.eclipse.jpt.jpa.core.context.java.JavaNamedQuery;
import org.eclipse.jpt.jpa.core.context.java.JavaPersistentType;
import org.eclipse.jpt.jpa.core.context.java.JavaTypeMapping;
import org.eclipse.jpt.jpa.ui.JptJpaUiPlugin;
import org.eclipse.jpt.jpa.ui.internal.JptUiMessages;
import org.eclipse.persistence.jpa.jpql.ExpressionTools;
import org.eclipse.swt.graphics.Image;

/**
 * This computer adds content assist support when it is invoked inside the query element of {@link
 * javax.persistence.NamedQuery &#64;NamedQuery}.
 *
 * @version 3.2
 * @since 3.0
 * @author Pascal Filion
 */
@SuppressWarnings("restriction")
public final class JpaJpqlJavaCompletionProposalComputer extends JpqlCompletionProposalComputer<ICompletionProposal>
                                                         implements IJavaCompletionProposalComputer {

	/**
	 * Creates a new <code>JpaJpqlJavaCompletionProposalComputer</code>.
	 */
	public JpaJpqlJavaCompletionProposalComputer() {
		super();
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	ICompletionProposal buildProposal(String proposal,
	                                  String displayString,
	                                  String additionalInfo,
	                                  Image image,
	                                  int cursorOffset) {

		return new JpqlCompletionProposal(
			contentAssistProposals,
			proposal,
			displayString,
			additionalInfo,
			image,
			namedQuery,
			actualQuery,
			jpqlQuery,
			offset + 1, // +1 is to skip the opening "
			position,
			cursorOffset,
			true
		);
	}

	/**
	 * {@inheritDoc}
	 */
	public List<ICompletionProposal> computeCompletionProposals(ContentAssistInvocationContext context,
	                                                            IProgressMonitor monitor) {

		if (context instanceof JavaContentAssistInvocationContext) {
			monitor.beginTask(null, 100);
			try {
				return computeCompletionProposals((JavaContentAssistInvocationContext) context, monitor);
			}
			catch (Exception e) {
				JptJpaUiPlugin.log(JptUiMessages.JpaJpqlJavaCompletionProposalComputer_Error, e);
			}
			finally {
				monitor.done();
			}
		}

		return Collections.emptyList();
	}

	private List<ICompletionProposal> computeCompletionProposals(JavaContentAssistInvocationContext context,
	                                                             IProgressMonitor monitor) throws Exception {

		CompletionContext completionContext = context.getCoreContext();
		if (completionContext == null) return Collections.emptyList();

		// The token "start" is the offset of the token's first character within the document.
		// A token start of -1 can means:
		// - It is inside the string representation of a unicode character, \\u0|0E9 where | is the
		//   cursor, then -1 is returned;
		// - The string is not valid (it has some invalid characters)
		int tokenStart = completionContext.getTokenStart();
		if (tokenStart == -1) return Collections.emptyList();

		int[] position = { completionContext.getOffset() - tokenStart - 1 };
		if (position[0] < 0) return Collections.emptyList();

		ICompilationUnit compilationUnit = context.getCompilationUnit();
		if (compilationUnit == null) return Collections.emptyList();
		CompilationUnit astRoot = ASTTools.buildASTRoot(compilationUnit);

		IFile file = getCorrespondingResource(compilationUnit);
		if (file == null) return Collections.emptyList();

		JpaFile jpaFile = (JpaFile) file.getAdapter(JpaFile.class);
		if (jpaFile == null) return Collections.emptyList();

		monitor.worked(80);
		checkCanceled(monitor);

		// Retrieve the JPA's model object
		NamedQuery namedQuery = namedQuery(jpaFile, tokenStart);
		if (namedQuery == null) return Collections.emptyList();

		// Retrieve the actual value of the element "query" since the content assist can be
		// invoked before the model received the new content
		String jpqlQuery = jpqlQuery(astRoot, tokenStart, completionContext.getTokenEnd(), position);

		// Now create the proposals
		return buildProposals(namedQuery, jpqlQuery, tokenStart, position[0]);
	}

	/**
	 * {@inheritDoc}
	 */
	public List<IContextInformation> computeContextInformation(ContentAssistInvocationContext context,
	                                                           IProgressMonitor monitor) {

		return Collections.emptyList();
	}

	private NamedQuery findNamedQuery(JpaStructureNode structureNode,
	                                  int tokenStart) {

		if (structureNode instanceof JavaPersistentType) {
			JavaPersistentType persistentType = (JavaPersistentType) structureNode;
			JavaTypeMapping typeMapping = persistentType.getMapping();

			for (Query query : typeMapping.getQueries()){
				if (query.getType().equals(NamedQuery.class)){
					JavaNamedQuery namedQuery = (JavaNamedQuery)query;
					TextRange textRange = namedQuery.getQueryAnnotation().getQueryTextRange();
					if ((textRange != null) && textRange.includes(tokenStart)) {
						return namedQuery;
					}
				}
			}
		}

		return null;
	}

	private IFile getCorrespondingResource(ICompilationUnit compilationUnit) {
		try {
			return (IFile) compilationUnit.getCorrespondingResource();
		}
		catch (JavaModelException ex) {
			JptJpaCorePlugin.log(ex);
			return null;
		}
	}

	private boolean isInsideNode(ASTNode node, int tokenStart, int tokenEnd) {
		int startPosition = node.getStartPosition();
		return startPosition <= tokenStart &&
		       startPosition + node.getLength() >= tokenEnd;
	}

	private String jpqlQuery(CompilationUnit astRoot, int tokenStart, int tokenEnd, int[] position) {

		String jpqlQuery = retrieveQuery(astRoot, tokenStart, tokenEnd);

		if (jpqlQuery == null) {
			jpqlQuery = StringTools.EMPTY_STRING;
		}
		else if (StringTools.stringIsQuoted(jpqlQuery)) {
			jpqlQuery = jpqlQuery.substring(1, jpqlQuery.length() - 1);
		}

		return jpqlQuery;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	String modifyJpqlQuery(String jpqlQuery, int[] position) {
		return ExpressionTools.unescape(jpqlQuery, position);
	}

	private NamedQuery namedQuery(JpaFile jpaFile, int tokenStart) {

		for (JpaStructureNode node : jpaFile.getRootStructureNodes()) {
			NamedQuery namedQuery = findNamedQuery(node, tokenStart);
			if (namedQuery != null) {
				return namedQuery;
			}
		}

		return null;
	}

	/**
	 * This twisted code is meant to retrieve the real string value that is not escaped and to also
	 * retrieve the position within the non-escaped string. The query could have escape characters,
	 * such as \r, \n etc being written as \\r, \\n, the position is based on that escaped string,
	 * the conversion will convert them into \r and \r and adjust the position accordingly.
	 *
	 * @param astRoot The parsed tree representation of the Java source file
	 * @param tokenStart The beginning of the query expression of the {@link javax.persistence.NamedQuery
	 * &#64;NamedQuery}'s query member within the source file
	 * @param tokenEnd The end of the query member within the source file
	 * @param position The position of the cursor within the query expression
	 * @return The actual value retrieved from the query element
	 */
	@SuppressWarnings("unchecked")
	private String retrieveQuery(CompilationUnit astRoot, int tokenStart, int tokenEnd) {

		// Dig into the TypeDeclarations
		for (AbstractTypeDeclaration type : (List<AbstractTypeDeclaration>) astRoot.types()) {

			if (isInsideNode(type, tokenStart, tokenEnd)) {

				// Dig inside its modifiers and annotations
				for (IExtendedModifier modifier : (List<IExtendedModifier>) type.modifiers()) {

					if (!modifier.isAnnotation()) {
						continue;
					}

					Annotation annotation = (Annotation) modifier;

					// Dig inside the annotation
					if (isInsideNode(annotation, tokenStart, tokenEnd)) {

						// @NamedQueries({...})
						if (annotation.isSingleMemberAnnotation()) {
							SingleMemberAnnotation singleMemberAnnotation = (SingleMemberAnnotation) annotation;
							Expression value = singleMemberAnnotation.getValue();

							if (value.getNodeType() == ASTNode.ARRAY_INITIALIZER) {
								ArrayInitializer array = (ArrayInitializer) value;

								for (Expression expression : (List<Expression>) array.expressions()) {
									if (isInsideNode(expression, tokenStart, tokenEnd)) {
										return retrieveQuery((NormalAnnotation) expression, tokenStart, tokenEnd);
									}
								}
							}
							else {
								NormalAnnotation childAnnotation = (NormalAnnotation) value;

								if (isInsideNode(childAnnotation, tokenStart, tokenEnd)) {
									return retrieveQuery(childAnnotation, tokenStart, tokenEnd);
								}
							}
						}
						// @NamedQuery()
						else if (annotation.isNormalAnnotation()) {
							return retrieveQuery((NormalAnnotation) annotation, tokenStart, tokenEnd);
						}
					}
				}
			}
		}

		return null;
	}

	@SuppressWarnings("unchecked")
	private String retrieveQuery(NormalAnnotation annotation, int tokenStart, int tokenEnd) {

		for (MemberValuePair pair : (List<MemberValuePair>) annotation.values()) {
			org.eclipse.jdt.core.dom.Expression expression = pair.getValue();

			if (isInsideNode(expression, tokenStart, tokenEnd)) {
				StringLiteral literal = (StringLiteral) pair.getValue();
				return literal.getEscapedValue();
			}
		}

		return null;
	}
}