/*******************************************************************************
 * 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.ArrayList;
import java.util.Comparator;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.jpt.common.utility.internal.CollectionTools;
import org.eclipse.jpt.jpa.core.context.NamedQuery;
import org.eclipse.jpt.jpa.core.jpql.JpaJpqlQueryHelper;
import org.eclipse.jpt.jpa.core.prefs.JpaJpqlPreferencesManager;
import org.eclipse.jpt.jpa.ui.JptJpaUiPlugin;
import org.eclipse.jpt.jpa.ui.internal.JptUiIcons;
import org.eclipse.persistence.jpa.jpql.ContentAssistProposals;
import org.eclipse.persistence.jpa.jpql.WordParser;
import org.eclipse.persistence.jpa.jpql.parser.Expression;
import org.eclipse.persistence.jpa.jpql.parser.IdentifierRole;
import org.eclipse.persistence.jpa.jpql.spi.IEntity;
import org.eclipse.persistence.jpa.jpql.spi.IMapping;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Display;

import static org.eclipse.persistence.jpa.jpql.spi.IMappingType.*;

/**
 * The abstract definition of JPQL content assist support.
 *
 * @version 3.2
 * @since 3.0
 * @author Pascal Filion
 */
@SuppressWarnings("nls")
abstract class JpqlCompletionProposalComputer<T> {

	/**
	 * The current value of the query element.
	 */
	String actualQuery;

	/**
	 * The provider of content assist items based on the position of the cursor within the JPQL query.
	 */
	ContentAssistProposals contentAssistProposals;

	/**
	 * The local registry containing the images used to display the possible proposals. The registry is
	 * disposed when the session ended.
	 */
	private ImageRegistry imageRegistry;

	/**
	 * The same value as {@link #actualQuery} or the modified query that was used by the Hermes parser.
	 */
	String jpqlQuery;

	/**
	 * The JPA model object that is used to access the Java project.
	 */
	NamedQuery namedQuery;

	/**
	 * The start position of the query within the document.
	 */
	int offset;

	/**
	 * The word before the position of the cursor.
	 */
	private String partialWord;

	/**
	 * The position of the cursor within {@link #actualQuery}.
	 */
	int position;

	/**
	 * This helper contains all the information necessary for retrieving the possible proposals
	 * required by content assist and to validate JPQL queries.
	 */
	JpaJpqlQueryHelper queryHelper;

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

	/**
	 * Adds completion proposals for the abstract schema names that are possible proposals.
	 *
	 * @param proposals The list used to store the new completion proposals
	 */
	private void addAbstractSchemaNames(List<T> proposals) {
		for (IEntity abstractSchemaType : sortByNames(contentAssistProposals.abstractSchemaTypes())) {
			proposals.add(buildAbstractSchemaNameProposal(abstractSchemaType));
		}
	}

	/**
	 * Adds completion proposals for the identification variables that are possible proposals.
	 *
	 * @param proposals The list used to store the new completion proposals
	 */
	private void addIdentificationVariables(List<T> proposals) {
		for (String variable : sort(contentAssistProposals.identificationVariables())) {
			proposals.add(buildIdentificationVariableProposal(variable));
		}
	}

	/**
	 * Adds completion proposals for the JPQL identifiers that are possible proposals.
	 *
	 * @param proposals The list used to store the new completion proposals
	 */
	private void addIdentifiers(List<T> proposals) {
		for (String identifier : sort(contentAssistProposals.identifiers())) {
			proposals.add(buildIdentifierProposal(identifier));
		}
	}

	private String additionalInfo(String proposal) {
		return JpqlIdentifierMessages.localizedMessage(proposal);
	}

	/**
	 * Adds completion proposals for the state fields and association fields that are possible proposals.
	 *
	 * @param proposals The list used to store the new completion proposals
	 */
	private void addMappings(List<T> proposals) {
		for (IMapping mapping : sort(contentAssistProposals.mappings())) {
			proposals.add(buildMappingProposal(mapping));
		}
	}

	private T buildAbstractSchemaNameProposal(IEntity abstractSchemaType) {
		String proposal = abstractSchemaType.getName();
		return buildProposal(proposal, proposal, entityImage());
	}

	private Comparator<IEntity> buildEntityNameComparator() {
		return new Comparator<IEntity>() {
			public int compare(IEntity entity1, IEntity entity2) {
				return entity1.getName().compareTo(entity2.getName());
			}
		};
	}

	private String buildIdentificationVariableDisplayString(String identificationVariable) {

		IEntity abstractSchemaType = contentAssistProposals.getAbstractSchemaType(identificationVariable);

		if (abstractSchemaType != null) {
			StringBuilder sb = new StringBuilder();
			sb.append(identificationVariable);
			sb.append(" : ");
			sb.append(abstractSchemaType.getName());
			identificationVariable = sb.toString();
		}

		return identificationVariable;
	}

	private T buildIdentificationVariableProposal(String proposal) {
		return buildProposal(
			proposal,
			buildIdentificationVariableDisplayString(proposal),
			identificationVariableImage()
		);
	}

	private T buildIdentifierProposal(String proposal) {

		String additionalInfo = additionalInfo(proposal);
		IdentifierRole role = queryHelper.getQueryContext().getExpressionRegistry().getIdentifierRole(proposal);
		boolean realFunction = (role == IdentifierRole.FUNCTION) && isRealFunction(proposal);
		int cursorOffset = 0;

		// There is at least one letter before the cursor, if the setting "Match First Letter Case"
		// is true, then match the case of the JPQL identifier with the first character
		if ((partialWord.length() > 0) && shouldMatchFirstCharacterCase()) {
			if (Character.isLowerCase(partialWord.charAt(0))) {
				proposal = proposal.toLowerCase();
			}
		}
		// Convert the case of the JPQL identifier based on the setting
		else if (shouldUseLowercaseIdentifiers()) {
			proposal = proposal.toLowerCase();
		}

		// For JPQL function, we add () to the display string, example: AVG()
		// But for TRUE, FALSE, etc, we don't add ()
		if (realFunction) {
			proposal += "()";
			cursorOffset--;
		}

		return buildProposal(
			proposal,
			proposal,
			additionalInfo,
			identifierImage(realFunction),
			cursorOffset
		);
	}

	private T buildMappingProposal(IMapping mapping) {
		String proposal = mapping.getName();
		return buildProposal(proposal, proposal, mappingImage(mapping));
	}

	private T buildProposal(String proposal, String displayString, Image image) {
		return buildProposal(proposal, displayString, null, image, 0);
	}

	/**
	 * Creates a new completion proposal for the given proposal.
	 *
	 * @param proposal A valid proposal that can be inserted into the query
	 * @param displayString The human readable string of the proposal
	 * @param additionalInfo Optional additional information about the proposal. The additional
	 * information will be presented to assist the user in deciding if the selected proposal is the
	 * desired choice
	 * @param image The image that represents the proposal
	 * @param cursorOffset An offset that moves the cursor backward or forward after it is adjusted
	 * based on the given proposal
	 * @return The completion proposal
	 */
	abstract T buildProposal(String proposal,
	                         String displayString,
	                         String additionalInfo,
	                         Image image,
	                         int cursorOffset);

	/**
	 * Creates the list of completion proposals based on the current content of the JPQL query and at
	 * the specified position.
	 *
	 * @param namedQuery The model object used to access the application metadata information
	 * @param actualQuery The model object may sometimes be out of sync with the actual content, the
	 * actual query is required for proper content assist
	 * @param offset The beginning of the string within the document
	 * @param position The position of the cursor within the query, which starts at the beginning of
	 * that query and not the document
	 * @return The list of completion proposals
	 */
	final List<T> buildProposals(NamedQuery namedQuery, String actualQuery, int offset, int position) {

		try {
			this.offset      = offset;
			this.actualQuery = actualQuery;
			this.namedQuery  = namedQuery;

			// It's possible the string has literal representation of the escape characters, if required,
			// convert them into actual escape characters and adjust the position accordingly
			int[] positions  = { position };
			this.jpqlQuery   = modifyJpqlQuery(actualQuery, positions);
			this.position    = positions[0];
			this.partialWord = partialWord();

			// Create the query helper, initialize it and then retrieve the content assist proposals
			if (this.queryHelper == null) {
				this.queryHelper = namedQuery.getPersistenceUnit().createJpqlQueryHelper();
			}

			this.queryHelper.setQuery(namedQuery, jpqlQuery);
			this.contentAssistProposals = queryHelper.buildContentAssistProposals(positions[0]);

			// Create the proposals for those proposals
			List<T> proposals = new ArrayList<T>();
			addAbstractSchemaNames    (proposals);
			addIdentificationVariables(proposals);
			addIdentifiers            (proposals);
			addMappings               (proposals);

			return proposals;
		}
		finally {
			clearInformation();
		}
	}

	final void checkCanceled(IProgressMonitor monitor) throws InterruptedException {
		if (monitor.isCanceled()) {
			throw new InterruptedException();
		}
	}

	/**
	 * Clears the cached information.
	 */
	final void clearInformation() {
		namedQuery  = null;
		offset      = -1;
		position    = -1;
		actualQuery = null;
		namedQuery  = null;
		partialWord = null;
		contentAssistProposals = null;
	}

	private Image entityImage() {
		return getImage(JptUiIcons.ENTITY);
	}

	/**
	 * Returns the reason why this computer was unable to produce any completion proposals or
	 * context information.
	 *
	 * @return An error message or <code>null</code> if no error occurred
	 */
	public String getErrorMessage() {
		return null;
	}

	private Image getImage(String key) {
		ImageRegistry imageRegistry = getImageRegistry();
		Image image = imageRegistry.get(key);
		if (image == null) {
			imageRegistry.put(key, getImageDescriptor(key));
			image = imageRegistry.get(key);
		}
		return image;
	}

	private ImageDescriptor getImageDescriptor(String key) {
		return JptJpaUiPlugin.getImageDescriptor(key);
	}

	private ImageRegistry getImageRegistry() {
		if (imageRegistry == null) {
			imageRegistry = new ImageRegistry(Display.getCurrent());
		}
		return imageRegistry;
	}

	private Image identificationVariableImage() {
		return getImage(JptUiIcons.JPQL_VARIABLE);
	}

	private Image identifierImage(boolean function) {

		if (function) {
			return getImage(JptUiIcons.JPQL_FUNCTION);
		}

		return getImage(JptUiIcons.JPQL_IDENTIFIER);
	}

	private boolean isRealFunction(String identifier) {
		return identifier != Expression.TRUE         &&
		       identifier != Expression.FALSE        &&
		       identifier != Expression.NULL         &&
		       identifier != Expression.CURRENT_DATE &&
		       identifier != Expression.CURRENT_TIME &&
		       identifier != Expression.CURRENT_TIMESTAMP;
	}

	private Image mappingImage(IMapping mapping) {
		switch (mapping.getMappingType()) {
			case BASIC:               return getImage(JptUiIcons.BASIC);
//			case BASIC_COLLECTION:    return getImage(JptUiIcons.ELEMENT_COLLECTION);
//			case BASIC_MAP:           return getImage(JptUiIcons.ELEMENT_COLLECTION);
			case ELEMENT_COLLECTION:  return getImage(JptUiIcons.ELEMENT_COLLECTION);
			case EMBEDDED:            return getImage(JptUiIcons.EMBEDDED);
			case EMBEDDED_ID:         return getImage(JptUiIcons.EMBEDDED_ID);
			case ID:                  return getImage(JptUiIcons.ID);
			case MANY_TO_MANY:        return getImage(JptUiIcons.MANY_TO_MANY);
			case MANY_TO_ONE:         return getImage(JptUiIcons.MANY_TO_ONE);
			case ONE_TO_MANY:         return getImage(JptUiIcons.ONE_TO_MANY);
			case ONE_TO_ONE:          return getImage(JptUiIcons.ONE_TO_ONE);
//			case TRANSFORMATION:      return getImage(JptUiIcons.BASIC);      // TODO
//			case VARIABLE_ONE_TO_ONE: return getImage(JptUiIcons.ONE_TO_ONE); // TODO
			case VERSION:             return getImage(JptUiIcons.VERSION);
			default:                  return getImage(JptUiIcons.TRANSIENT);
		}
	}

	/**
	 * In some context, the given JPQL query needs to be modified before it is parsed.
	 *
	 * @param jpqlQuery The JPQL query to keep unchanged or to modify before parsing it
	 * @param position The position of the cursor within the JPQL query, which needs to be updated if
	 * the query is modified
	 * @return The given JPQL query or a modified version that will be parsed
	 */
	String modifyJpqlQuery(String jpqlQuery, int[] position) {
		return jpqlQuery;
	}

	private String partialWord() {
		WordParser wordParser = new WordParser(jpqlQuery);
		wordParser.setPosition(position);
		return wordParser.partialWord();
	}

	/**
	 * Informs the computer that a content assist session has ended.
	 */
	public void sessionEnded() {

		queryHelper = null;
		clearInformation();

		if (imageRegistry != null) {
			imageRegistry.dispose();
		}
	}

	/**
	 * Informs the computer that a content assist session has started.
	 */
	public void sessionStarted() {
		// Nothing to do
	}

	private boolean shouldMatchFirstCharacterCase() {
		return JpaJpqlPreferencesManager.getMatchFirstCharacterCaseWorkspacePreference();
	}

	private boolean shouldUseLowercaseIdentifiers() {
		String value = JpaJpqlPreferencesManager.getIdentifiersCaseWorkspacePreference();
		return JpaJpqlPreferencesManager.JPQL_IDENTIFIER_LOWERCASE_PREF_VALUE.equals(value);
	}

	private <I extends Comparable<? super I>> Iterable<I> sort(Iterable<I> iterator) {
		return CollectionTools.sort(iterator);
	}

	private Iterable<IEntity> sortByNames(Iterable<IEntity> abstractSchemaTypes) {
		return CollectionTools.sort(abstractSchemaTypes, buildEntityNameComparator());
	}
}