/*******************************************************************************
 * Copyright (c) 2000, 2010 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.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Shell;

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.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.dom.Bindings;
import org.eclipse.jdt.internal.corext.template.java.SignatureUtil;
import org.eclipse.jdt.internal.corext.util.Strings;

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;


/**
 * Proposal for generic types.
 * <p>
 * Only used when compliance is set to 5.0 or higher.
 * </p>
 */
public final class LazyGenericTypeProposal 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(LazyGenericTypeProposal 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(LazyGenericTypeProposal 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 Strings.markJavaElementLabelLTR(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)
		 */
		@Override
		public boolean equals(Object obj) {
			if (obj instanceof ContextInformation) {
				ContextInformation ci= (ContextInformation) obj;
				return getContextInformationPosition() == ci.getContextInformationPosition() && getInformationDisplayString().equals(ci.getInformationDisplayString());
			}
			return false;
		}

		/*
		 * @see java.lang.Object#hashCode()
		 * @since 3.1
		 */
		@Override
		public int hashCode() {
			int low= fContextDisplayString != null ? fContextDisplayString.hashCode() : 0;
			return fPosition << 24 | fInformationDisplayString.hashCode() << 16 | low;
		}

	}

	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;
		}

		@Override
		public String toString() {
			return fProposal;
		}
	}

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

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

	/*
	 * @see ICompletionProposalExtension#apply(IDocument, char)
	 */
	@Override
	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
					boolean insertClosingParenthesis= trigger == '(' && autocloseBrackets();
					if (insertClosingParenthesis)
						updateReplacementWithParentheses(buffer);
					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, insertClosingParenthesis);
						} else {
							if (insertClosingParenthesis)
								setUpLinkedMode(document, ')');
							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()
	 */
	@Override
	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 if this element does not exist or if an exception occurs while
	 *             accessing its corresponding resource
	 */
	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 if this element does not exist or if an exception occurs while
	 *             accessing its corresponding resource
	 * @see #computeTypeProposal(ITypeParameter)
	 */
	private TypeArgumentProposal computeTypeProposal(ITypeBinding binding, ITypeParameter parameter) throws JavaModelException {
		final String name= Bindings.getTypeQualifiedName(binding);
		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 if this element does not exist or if an exception occurs while
	 *             accessing its corresponding resource
	 */
	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<IType> path= new LinkedList<IType>();
		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 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 if this element does not exist or if an exception occurs while
	 *             accessing its corresponding resource
	 * @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);
		parser.setStatementsRecovery(true);

		final Map<String, IBinding> bindings= new HashMap<String, IBinding>();
		ASTRequestor requestor= new ASTRequestor() {
			@Override
			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) {
		/*
		 * No argument list if there were any special triggers (for example a period to qualify an
		 * inner type).
		 */
		if (trigger != '\0' && trigger != '<' && trigger != '(')
			return false;

		/* No argument list if the completion is empty (already within the argument list). */
		char[] completion= fProposal.getCompletion();
		if (completion.length == 0)
			return false;

		/* No argument list if there already is a generic signature behind the name. */
		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, boolean withParentheses) {
		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]));
					model.addGroup(group);
				}
			}
			if (withParentheses) {
				LinkedPositionGroup group= new LinkedPositionGroup();
				group.addPosition(new LinkedPosition(document, replacementOffset + getCursorPosition(), 0));
				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(withParentheses ? ')' : '>', 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)
	 */
	@Override
	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.FilledArgumentNamesMethodProposal_error_msg, e.getMessage());
	}

	/*
	 * @see org.eclipse.jdt.internal.ui.text.java.LazyJavaCompletionProposal#computeContextInformation()
	 */
	@Override
	protected IContextInformation computeContextInformation() {
		try {
			if (hasParameters()) {
				TypeArgumentProposal[] proposals= computeTypeArgumentProposals();
				if (hasAmbiguousProposals(proposals))
					return new ContextInformation(this);
			}
		} catch (JavaModelException e) {
		}
		return super.computeContextInformation();
	}

	@Override
	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;
		}
	}
}
