/*******************************************************************************
 * Copyright (c) 2000, 2006 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.text.java;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;

import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Shell;

import org.eclipse.jface.dialogs.MessageDialog;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationExtension;
import org.eclipse.jface.text.link.LinkedModeModel;
import org.eclipse.jface.text.link.LinkedModeUI;
import org.eclipse.jface.text.link.LinkedPosition;
import org.eclipse.jface.text.link.LinkedPositionGroup;

import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.texteditor.link.EditorLinkedModeUI;

import org.eclipse.jdt.core.CompletionProposal;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTRequestor;
import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;

import org.eclipse.jdt.internal.corext.template.java.SignatureUtil;

import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext;

import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.javaeditor.EditorHighlightingSynchronizer;
import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;

/**
 * An experimental proposal.
 */
public final class GenericJavaTypeProposal extends LazyJavaTypeCompletionProposal {
	/** Triggers for types. Do not modify. */
	private final static char[] GENERIC_TYPE_TRIGGERS= new char[] { '.', '\t', '[', '(', '<', ' ' };

	/**
	 * Short-lived context information object for generic types. Currently, these
	 * are only created after inserting a type proposal, as core doesn't give us
	 * the correct type proposal from within SomeType<|>.
	 */
	private static class ContextInformation implements IContextInformation, IContextInformationExtension {
		private final String fInformationDisplayString;
		private final String fContextDisplayString;
		private final Image fImage;
		private final int fPosition;
		
		ContextInformation(GenericJavaTypeProposal proposal) {
			// don't cache the proposal as content assistant
			// might hang on to the context info
			fContextDisplayString= proposal.getDisplayString();
			fInformationDisplayString= computeContextString(proposal);
			fImage= proposal.getImage();
			fPosition= proposal.getReplacementOffset() + proposal.getReplacementString().indexOf('<') + 1;
		}
		
		/*
		 * @see org.eclipse.jface.text.contentassist.IContextInformation#getContextDisplayString()
		 */
		public String getContextDisplayString() {
			return fContextDisplayString;
		}

		/*
		 * @see org.eclipse.jface.text.contentassist.IContextInformation#getImage()
		 */
		public Image getImage() {
			return fImage;
		}

		/*
		 * @see org.eclipse.jface.text.contentassist.IContextInformation#getInformationDisplayString()
		 */
		public String getInformationDisplayString() {
			return fInformationDisplayString;
		}

		private String computeContextString(GenericJavaTypeProposal proposal) {
			try {
				TypeArgumentProposal[] proposals= proposal.computeTypeArgumentProposals();
				if (proposals.length == 0)
					return null;
				
				StringBuffer buf= new StringBuffer();
				for (int i= 0; i < proposals.length; i++) {
					buf.append(proposals[i].getDisplayName());
					if (i < proposals.length - 1)
						buf.append(", "); //$NON-NLS-1$
				}
				return buf.toString();
				
			} catch (JavaModelException e) {
				return null;
			}
		}

		/*
		 * @see org.eclipse.jface.text.contentassist.IContextInformationExtension#getContextInformationPosition()
		 */
		public int getContextInformationPosition() {
			return fPosition;
		}
		
		/*
		 * @see java.lang.Object#equals(java.lang.Object)
		 */
		public boolean equals(Object obj) {
			if (obj instanceof ContextInformation) {
				ContextInformation ci= (ContextInformation) obj;
				return getContextInformationPosition() == ci.getContextInformationPosition() && getInformationDisplayString().equals(ci.getInformationDisplayString());
			}
			return false;
		}
	}

	private static final class TypeArgumentProposal {
		private final boolean fIsAmbiguous;
		private final String fProposal;
		private final String fTypeDisplayName;

		TypeArgumentProposal(String proposal, boolean ambiguous, String typeDisplayName) {
			fIsAmbiguous= ambiguous;
			fProposal= proposal;
			fTypeDisplayName= typeDisplayName;
		}

		public String getDisplayName() {
			return fTypeDisplayName;
		}

		boolean isAmbiguous() {
			return fIsAmbiguous;
		}

		String getProposals() {
			return fProposal;
		}

		public String toString() {
			return fProposal;
		}
	}

	private IRegion fSelectedRegion; // initialized by apply()
	private TypeArgumentProposal[] fTypeArgumentProposals;

	public GenericJavaTypeProposal(CompletionProposal typeProposal, JavaContentAssistInvocationContext context) {
		super(typeProposal, context);
	}

	/*
	 * @see ICompletionProposalExtension#apply(IDocument, char)
	 */
	public void apply(IDocument document, char trigger, int offset) {

		if (shouldAppendArguments(document, offset, trigger)) {
			try {
				TypeArgumentProposal[] typeArgumentProposals= computeTypeArgumentProposals();
				if (typeArgumentProposals.length > 0) {

					int[] offsets= new int[typeArgumentProposals.length];
					int[] lengths= new int[typeArgumentProposals.length];
					StringBuffer buffer= createParameterList(typeArgumentProposals, offsets, lengths);

					// set the generic type as replacement string
					super.setReplacementString(buffer.toString());
					// add import & remove package, update replacement offset
					super.apply(document, '\0', offset);

					if (getTextViewer() != null) {
						if (hasAmbiguousProposals(typeArgumentProposals)) {
							adaptOffsets(offsets, buffer);
							installLinkedMode(document, offsets, lengths, typeArgumentProposals);
						} else {
							fSelectedRegion= new Region(getReplacementOffset() + getReplacementString().length(), 0);
						}
					}

					return;
				}
			} catch (JavaModelException e) {
				// log and continue
				JavaPlugin.log(e);
			}
		}

		// default is to use the super implementation
		// reasons:
		// - not a parameterized type,
		// - already followed by <type arguments>
		// - proposal type does not inherit from expected type
		super.apply(document, trigger, offset);
	}
	
	/*
	 * @see org.eclipse.jdt.internal.ui.text.java.LazyJavaTypeCompletionProposal#computeTriggerCharacters()
	 */
	protected char[] computeTriggerCharacters() {
		return GENERIC_TYPE_TRIGGERS;
	}

	/**
	 * Adapt the parameter offsets to any modification of the replacement
	 * string done by <code>apply</code>. For example, applying the proposal
	 * may add an import instead of inserting the fully qualified name.
	 * <p>
	 * This assumes that modifications happen only at the beginning of the
	 * replacement string and do not touch the type arguments list.
	 * </p>
	 *
	 * @param offsets the offsets to modify
	 * @param buffer the original replacement string
	 */
	private void adaptOffsets(int[] offsets, StringBuffer buffer) {
		String replacementString= getReplacementString();
		int delta= buffer.length() - replacementString.length(); // due to using an import instead of package
		for (int i= 0; i < offsets.length; i++) {
			offsets[i]-= delta;
		}
	}

	/**
	 * Computes the type argument proposals for this type proposals. If there is
	 * an expected type binding that is a super type of the proposed type, the
	 * wildcard type arguments of the proposed type that can be mapped through
	 * to type the arguments of the expected type binding are bound accordingly.
	 * <p>
	 * For type arguments that cannot be mapped to arguments in the expected
	 * type, or if there is no expected type, the upper bound of the type
	 * argument is proposed.
	 * </p>
	 * <p>
	 * The argument proposals have their <code>isAmbiguos</code> flag set to
	 * <code>false</code> if the argument can be mapped to a non-wildcard type
	 * argument in the expected type, otherwise the proposal is ambiguous.
	 * </p>
	 *
	 * @return the type argument proposals for the proposed type
	 * @throws JavaModelException if accessing the java model fails
	 */
	private TypeArgumentProposal[] computeTypeArgumentProposals() throws JavaModelException {
		if (fTypeArgumentProposals == null) {
			
			IType type= (IType) getJavaElement();
			if (type == null)
				return new TypeArgumentProposal[0];
			
			ITypeParameter[] parameters= type.getTypeParameters();
			if (parameters.length == 0)
				return new TypeArgumentProposal[0];
			
			TypeArgumentProposal[] arguments= new TypeArgumentProposal[parameters.length];
			
			ITypeBinding expectedTypeBinding= getExpectedType();
			if (expectedTypeBinding != null && expectedTypeBinding.isParameterizedType()) {
				// in this case, the type arguments we propose need to be compatible
				// with the corresponding type parameters to declared type
				
				IType expectedType= (IType) expectedTypeBinding.getJavaElement();
				
				IType[] path= computeInheritancePath(type, expectedType);
				if (path == null)
					// proposed type does not inherit from expected type
					// the user might be looking for an inner type of proposed type
					// to instantiate -> do not add any type arguments
					return new TypeArgumentProposal[0];
				
				int[] indices= new int[parameters.length];
				for (int paramIdx= 0; paramIdx < parameters.length; paramIdx++) {
					indices[paramIdx]= mapTypeParameterIndex(path, path.length - 1, paramIdx);
				}
				
				// for type arguments that are mapped through to the expected type's
				// parameters, take the arguments of the expected type
				ITypeBinding[] typeArguments= expectedTypeBinding.getTypeArguments();
				for (int paramIdx= 0; paramIdx < parameters.length; paramIdx++) {
					if (indices[paramIdx] != -1) {
						// type argument is mapped through
						ITypeBinding binding= typeArguments[indices[paramIdx]];
						arguments[paramIdx]= computeTypeProposal(binding, parameters[paramIdx]);
					}
				}
			}
			
			// for type arguments that are not mapped through to the expected type,
			// take the lower bound of the type parameter
			for (int i= 0; i < arguments.length; i++) {
				if (arguments[i] == null) {
					arguments[i]= computeTypeProposal(parameters[i]);
				}
			}
			fTypeArgumentProposals= arguments;
		}
		return fTypeArgumentProposals;
	}

	/**
	 * Returns a type argument proposal for a given type parameter. The proposal is:
	 * <ul>
	 * <li>the type bound for type parameters with a single bound</li>
	 * <li>the type parameter name for all other (unbounded or more than one bound) type parameters</li>
	 * </ul>
	 * Type argument proposals for type parameters are always ambiguous.
	 * 
	 * @param parameter the type parameter of the inserted type
	 * @return a type argument proposal for <code>parameter</code>
	 * @throws JavaModelException
	 */
	private TypeArgumentProposal computeTypeProposal(ITypeParameter parameter) throws JavaModelException {
		String[] bounds= parameter.getBounds();
		String elementName= parameter.getElementName();
		String displayName= computeTypeParameterDisplayName(parameter, bounds);
		if (bounds.length == 1 && !"java.lang.Object".equals(bounds[0])) //$NON-NLS-1$
			return new TypeArgumentProposal(Signature.getSimpleName(bounds[0]), true, displayName);
		else
			return new TypeArgumentProposal(elementName, true, displayName);
	}

	private String computeTypeParameterDisplayName(ITypeParameter parameter, String[] bounds) {
		if (bounds.length == 0 || bounds.length == 1 && "java.lang.Object".equals(bounds[0])) //$NON-NLS-1$
			return parameter.getElementName();
		StringBuffer buf= new StringBuffer(parameter.getElementName());
		buf.append(" extends "); //$NON-NLS-1$
		for (int i= 0; i < bounds.length; i++) {
			buf.append(Signature.getSimpleName(bounds[i]));
			if (i < bounds.length - 1)
				buf.append(" & "); //$NON-NLS-1$
		}
		return buf.toString();
	}

	/**
	 * Returns a type argument proposal for a given type binding. The proposal is:
	 * <ul>
	 * <li>the simple type name for normal types or type variables (unambigous proposal)</li>
	 * <li>for wildcard types (ambigous proposals):
	 * <ul>
	 * <li>the upper bound for wildcards with an upper bound</li>
	 * <li>the {@linkplain #computeTypeProposal(ITypeParameter) parameter proposal} for unbounded
	 * wildcards or wildcards with a lower bound</li>
	 * </ul>
	 * </li>
	 * </ul>
	 * 
	 * @param binding the type argument binding in the expected type
	 * @param parameter the type parameter of the inserted type
	 * @return a type argument proposal for <code>binding</code>
	 * @throws JavaModelException
	 * @see #computeTypeProposal(ITypeParameter)
	 */
	private TypeArgumentProposal computeTypeProposal(ITypeBinding binding, ITypeParameter parameter) throws JavaModelException {
		final String name= binding.getName();
		if (binding.isWildcardType()) {

			if (binding.isUpperbound()) {
				// replace the wildcard ? with the type parameter name to get "E extends Bound" instead of "? extends Bound"
				String contextName= name.replaceFirst("\\?", parameter.getElementName()); //$NON-NLS-1$
				// upper bound - the upper bound is the bound itself
				return new TypeArgumentProposal(binding.getBound().getName(), true, contextName);
			}
			
			// no or upper bound - use the type parameter of the inserted type, as it may be more
			// restrictive (eg. List<?> list= new SerializableList<Serializable>()) 
			return computeTypeProposal(parameter);
		}

		// not a wildcard but a type or type variable - this is unambigously the right thing to insert
		return new TypeArgumentProposal(name, false, name);
	}

	/**
	 * Computes one inheritance path from <code>superType</code> to
	 * <code>subType</code> or <code>null</code> if <code>subType</code>
	 * does not inherit from <code>superType</code>. Note that there may be
	 * more than one inheritance path - this method simply returns one.
	 * <p>
	 * The returned array contains <code>superType</code> at its first index,
	 * and <code>subType</code> at its last index. If <code>subType</code>
	 * equals <code>superType</code>, an array of length 1 is returned
	 * containing that type.
	 * </p>
	 *
	 * @param subType the sub type
	 * @param superType the super type
	 * @return an inheritance path from <code>superType</code> to
	 *         <code>subType</code>, or <code>null</code> if
	 *         <code>subType</code> does not inherit from
	 *         <code>superType</code>
	 * @throws JavaModelException
	 */
	private IType[] computeInheritancePath(IType subType, IType superType) throws JavaModelException {
		if (superType == null)
			return null;

		// optimization: avoid building the type hierarchy for the identity case
		if (superType.equals(subType))
			return new IType[] { subType };

		ITypeHierarchy hierarchy= subType.newSupertypeHierarchy(getProgressMonitor());
		if (!hierarchy.contains(superType))
			return null; // no path

		List path= new LinkedList();
		path.add(superType);
		do {
			// any sub type must be on a hierarchy chain from superType to subType
			superType= hierarchy.getSubtypes(superType)[0];
			path.add(superType);
		} while (!superType.equals(subType)); // since the equality case is handled above, we can spare one check

		return (IType[]) path.toArray(new IType[path.size()]);
	}

	private NullProgressMonitor getProgressMonitor() {
		return new NullProgressMonitor();
	}

	/**
	 * For the type parameter at <code>paramIndex</code> in the type at
	 * <code>path[pathIndex]</code>, this method computes the corresponding
	 * type parameter index in the type at <code>path[0]</code>. If the type
	 * parameter does not map to a type parameter of the super type,
	 * <code>-1</code> is returned.
	 *
	 * @param path the type inheritance path, a non-empty array of consecutive
	 *        sub types
	 * @param pathIndex an index into <code>path</code> specifying the type to
	 *        start with
	 * @param paramIndex the index of the type parameter to map -
	 *        <code>path[pathIndex]</code> must have a type parameter at that
	 *        index, lest an <code>ArrayIndexOutOfBoundsException</code> is
	 *        thrown
	 * @return the index of the type parameter in <code>path[0]</code>
	 *         corresponding to the type parameter at <code>paramIndex</code>
	 *         in <code>path[pathIndex]</code>, or -1 if there is no
	 *         corresponding type parameter
	 * @throws JavaModelException
	 * @throws ArrayIndexOutOfBoundsException if <code>path[pathIndex]</code>
	 *         has &lt;= <code>paramIndex</code> parameters
	 */
	private int mapTypeParameterIndex(IType[] path, int pathIndex, int paramIndex) throws JavaModelException, ArrayIndexOutOfBoundsException {
		if (pathIndex == 0)
			// break condition: we've reached the top of the hierarchy
			return paramIndex;

		IType subType= path[pathIndex];
		IType superType= path[pathIndex - 1];

		String superSignature= findMatchingSuperTypeSignature(subType, superType);
		ITypeParameter param= subType.getTypeParameters()[paramIndex];
		int index= findMatchingTypeArgumentIndex(superSignature, param.getElementName());
		if (index == -1) {
			// not mapped through
			return -1;
		}

		return mapTypeParameterIndex(path, pathIndex - 1, index);
	}

	/**
	 * Finds and returns the super type signature in the
	 * <code>extends</code> or <code>implements</code> clause of
	 * <code>subType</code> that corresponds to <code>superType</code>.
	 *
	 * @param subType a direct and true sub type of <code>superType</code>
	 * @param superType a direct super type (super class or interface) of
	 *        <code>subType</code>
	 * @return the super type signature of <code>subType</code> referring
	 *         to <code>superType</code>
	 * @throws JavaModelException if extracting the super type signatures
	 *         fails, or if <code>subType</code> contains no super type
	 *         signature to <code>superType</code>
	 */
	private String findMatchingSuperTypeSignature(IType subType, IType superType) throws JavaModelException {
		String[] signatures= getSuperTypeSignatures(subType, superType);
		for (int i= 0; i < signatures.length; i++) {
			String signature= signatures[i];
			String qualified= SignatureUtil.qualifySignature(signature, subType);
			String subFQN= SignatureUtil.stripSignatureToFQN(qualified);

			String superFQN= superType.getFullyQualifiedName();
			if (subFQN.equals(superFQN)) {
				return signature;
			}

			// TODO handle local types
		}

		throw new JavaModelException(new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IStatus.OK, "Illegal hierarchy", null))); //$NON-NLS-1$
	}

	/**
	 * Finds and returns the index of the type argument named
	 * <code>argument</code> in the given super type signature.
	 * <p>
	 * If <code>signature</code> does not contain a corresponding type
	 * argument, or if <code>signature</code> has no type parameters (i.e. is
	 * a reference to a non-parameterized type or a raw type), -1 is returned.
	 * </p>
	 *
	 * @param signature the super type signature from a type's
	 *        <code>extends</code> or <code>implements</code> clause
	 * @param argument the name of the type argument to find
	 * @return the index of the given type argument, or -1 if there is none
	 */
	private int findMatchingTypeArgumentIndex(String signature, String argument) {
		String[] typeArguments= Signature.getTypeArguments(signature);
		for (int i= 0; i < typeArguments.length; i++) {
			if (Signature.getSignatureSimpleName(typeArguments[i]).equals(argument))
				return i;
		}
		return -1;
	}

	/**
	 * Returns the super interface signatures of <code>subType</code> if
	 * <code>superType</code> is an interface, otherwise returns the super
	 * type signature.
	 *
	 * @param subType the sub type signature
	 * @param superType the super type signature
	 * @return the super type signatures of <code>subType</code>
	 * @throws JavaModelException if any java model operation fails
	 */
	private String[] getSuperTypeSignatures(IType subType, IType superType) throws JavaModelException {
		if (superType.isInterface())
			return subType.getSuperInterfaceTypeSignatures();
		else
			return new String[] {subType.getSuperclassTypeSignature()};
	}

	/**
	 * Returns the type binding of the expected type as it is contained in the
	 * code completion context.
	 *
	 * @return the binding of the expected type
	 */
	private ITypeBinding getExpectedType() {
		char[][] chKeys= fInvocationContext.getCoreContext().getExpectedTypesKeys();
		if (chKeys == null || chKeys.length == 0)
			return null;

		String[] keys= new String[chKeys.length];
		for (int i= 0; i < keys.length; i++) {
			keys[i]= String.valueOf(chKeys[0]);
		}

		final ASTParser parser= ASTParser.newParser(AST.JLS3);
		parser.setProject(fCompilationUnit.getJavaProject());
		parser.setResolveBindings(true);

		final Map bindings= new HashMap();
		ASTRequestor requestor= new ASTRequestor() {
			public void acceptBinding(String bindingKey, IBinding binding) {
				bindings.put(bindingKey, binding);
			}
		};
		parser.createASTs(new ICompilationUnit[0], keys, requestor, null);

		if (bindings.size() > 0)
			return (ITypeBinding) bindings.get(keys[0]);

		return null;
	}

	/**
	 * Returns <code>true</code> if type arguments should be appended when
	 * applying this proposal, <code>false</code> if not (for example if the
	 * document already contains a type argument list after the insertion point.
	 *
	 * @param document the document
	 * @param offset the insertion offset
	 * @param trigger the trigger character
	 * @return <code>true</code> if arguments should be appended
	 */
	private boolean shouldAppendArguments(IDocument document, int offset, char trigger) {
		if (trigger != '\0' && trigger != '<')
			return false;
		
		try {
			IRegion region= document.getLineInformationOfOffset(offset);
			String line= document.get(region.getOffset(), region.getLength());

			int index= offset - region.getOffset();
			while (index != line.length() && Character.isUnicodeIdentifierPart(line.charAt(index)))
				++index;

			if (index == line.length())
				return true;

			char ch= line.charAt(index);
			return ch != '<';

		} catch (BadLocationException e) {
			return true;
		}
	}

	private StringBuffer createParameterList(TypeArgumentProposal[] typeArguments, int[] offsets, int[] lengths) {
		StringBuffer buffer= new StringBuffer();
		buffer.append(getReplacementString());

		FormatterPrefs prefs= getFormatterPrefs();
		final char LESS= '<';
		final char GREATER= '>';
		if (prefs.beforeOpeningBracket)
			buffer.append(SPACE);
		buffer.append(LESS);
		if (prefs.afterOpeningBracket)
			buffer.append(SPACE);
		StringBuffer separator= new StringBuffer(3);
		if (prefs.beforeTypeArgumentComma)
			separator.append(SPACE);
		separator.append(COMMA);
		if (prefs.afterTypeArgumentComma)
			separator.append(SPACE);

		for (int i= 0; i != typeArguments.length; i++) {
			if (i != 0)
				buffer.append(separator);

			offsets[i]= buffer.length();
			buffer.append(typeArguments[i]);
			lengths[i]= buffer.length() - offsets[i];
		}
		if (prefs.beforeClosingBracket)
			buffer.append(SPACE);
		buffer.append(GREATER);

		return buffer;
	}

	private void installLinkedMode(IDocument document, int[] offsets, int[] lengths, TypeArgumentProposal[] typeArgumentProposals) {
		int replacementOffset= getReplacementOffset();
		String replacementString= getReplacementString();

		try {
			LinkedModeModel model= new LinkedModeModel();
			for (int i= 0; i != offsets.length; i++) {
				if (typeArgumentProposals[i].isAmbiguous()) {
					LinkedPositionGroup group= new LinkedPositionGroup();
					group.addPosition(new LinkedPosition(document, replacementOffset + offsets[i], lengths[i], LinkedPositionGroup.NO_STOP));
					model.addGroup(group);
				}
			}

			model.forceInstall();
			JavaEditor editor= getJavaEditor();
			if (editor != null) {
				model.addLinkingListener(new EditorHighlightingSynchronizer(editor));
			}

			LinkedModeUI ui= new EditorLinkedModeUI(model, getTextViewer());
			ui.setExitPolicy(new ExitPolicy('>', document));
			ui.setExitPosition(getTextViewer(), replacementOffset + replacementString.length(), 0, Integer.MAX_VALUE);
			ui.setDoContextInfo(true);
			ui.enter();

			fSelectedRegion= ui.getSelectedRegion();

		} catch (BadLocationException e) {
			JavaPlugin.log(e);
			openErrorDialog(e);
		}
	}

	private boolean hasAmbiguousProposals(TypeArgumentProposal[] typeArgumentProposals) {
		boolean hasAmbiguousProposals= false;
		for (int i= 0; i < typeArgumentProposals.length; i++) {
			if (typeArgumentProposals[i].isAmbiguous()) {
				hasAmbiguousProposals= true;
				break;
			}
		}
		return hasAmbiguousProposals;
	}

	/**
	 * Returns the currently active java editor, or <code>null</code> if it
	 * cannot be determined.
	 *
	 * @return  the currently active java editor, or <code>null</code>
	 */
	private JavaEditor getJavaEditor() {
		IEditorPart part= JavaPlugin.getActivePage().getActiveEditor();
		if (part instanceof JavaEditor)
			return (JavaEditor) part;
		else
			return null;
	}

	/*
	 * @see ICompletionProposal#getSelection(IDocument)
	 */
	public Point getSelection(IDocument document) {
		if (fSelectedRegion == null)
			return super.getSelection(document);

		return new Point(fSelectedRegion.getOffset(), fSelectedRegion.getLength());
	}

	private void openErrorDialog(BadLocationException e) {
		Shell shell= getTextViewer().getTextWidget().getShell();
		MessageDialog.openError(shell, JavaTextMessages.ExperimentalProposal_error_msg, e.getMessage());
	}

	/*
	 * @see org.eclipse.jdt.internal.ui.text.java.LazyJavaCompletionProposal#computeContextInformation()
	 */
	protected IContextInformation computeContextInformation() {
		// only return information if we're already computed
		// -> avoids creating context information for invalid proposals
		if (fTypeArgumentProposals != null) {
			try {
				if (hasParameters()) {
					TypeArgumentProposal[] proposals= computeTypeArgumentProposals();
					if (hasAmbiguousProposals(proposals))
						return new ContextInformation(this);
				}
			} catch (JavaModelException e) {
			}
		}
		return super.computeContextInformation();
	}
	
	protected int computeCursorPosition() {
		if (fSelectedRegion != null)
			return fSelectedRegion.getOffset() - getReplacementOffset();
		return super.computeCursorPosition();
	}
	
	private boolean hasParameters() {
		try {
			IType type= (IType) getJavaElement();
			if (type == null)
				return false;

			return type.getTypeParameters().length > 0;
		} catch (JavaModelException e) {
			return false;
		}
	}
}
