/*******************************************************************************
 * Copyright (c) 2005, 2016 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
 *     Christian Georgi<christian.georgi@sap.com> - Bug 462770: Use OS symbol for 'Ctrl'
 *     Gábor Kövesdán - Contribution for Bug 350000 - [content assist] Include non-prefix matches in auto-complete suggestions
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.text.java;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;

import org.osgi.framework.Bundle;

import org.eclipse.osgi.util.TextProcessor;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.widgets.Shell;

import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;

import org.eclipse.jface.internal.text.html.BrowserInformationControl;
import org.eclipse.jface.internal.text.html.HTMLPrinter;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceConverter;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.viewers.StyledString;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BadPositionCategoryException;
import org.eclipse.jface.text.DefaultPositionUpdater;
import org.eclipse.jface.text.DocumentCommand;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.IPositionUpdater;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextPresentationListener;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.ITextViewerExtension2;
import org.eclipse.jface.text.ITextViewerExtension4;
import org.eclipse.jface.text.ITextViewerExtension5;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.TextPresentation;
import org.eclipse.jface.text.contentassist.BoldStylerProvider;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension2;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension3;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension5;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension6;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension7;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.link.ILinkedModeListener;
import org.eclipse.jface.text.link.LinkedModeModel;
import org.eclipse.jface.text.link.LinkedModeUI;
import org.eclipse.jface.text.link.LinkedModeUI.ExitFlags;
import org.eclipse.jface.text.link.LinkedModeUI.IExitPolicy;
import org.eclipse.jface.text.link.LinkedPosition;
import org.eclipse.jface.text.link.LinkedPositionGroup;

import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchSite;

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

import org.eclipse.jdt.core.CompletionProposal;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.CharOperation;
import org.eclipse.jdt.core.search.SearchPattern;

import org.eclipse.jdt.internal.corext.javadoc.JavaDocLocations;
import org.eclipse.jdt.internal.corext.util.Strings;

import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jdt.ui.text.IJavaPartitions;
import org.eclipse.jdt.ui.text.JavaTextTools;
import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;
import org.eclipse.jdt.ui.text.java.JavaContentAssistInvocationContext;

import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.text.java.hover.JavadocBrowserInformationControlInput;
import org.eclipse.jdt.internal.ui.text.java.hover.JavadocHover;
import org.eclipse.jdt.internal.ui.text.javadoc.JavadocContentAccess2;


/**
 *
 * @since 3.2
 */
public abstract class AbstractJavaCompletionProposal implements IJavaCompletionProposal, ICompletionProposalExtension, ICompletionProposalExtension2, ICompletionProposalExtension3,
		ICompletionProposalExtension5, ICompletionProposalExtension6, ICompletionProposalExtension7 {


	/**
	 * The key modifier that toggles whether to insert or overwrite.
	 */
	public static final int MODIFIER_TOGGLE_COMPLETION_MODE= SWT.CTRL;

	/**
	 * A class to simplify tracking a reference position in a document.
	 */
	static final class ReferenceTracker {

		/** The reference position category name. */
		private static final String CATEGORY= "reference_position"; //$NON-NLS-1$
		/** The position updater of the reference position. */
		private final IPositionUpdater fPositionUpdater= new DefaultPositionUpdater(CATEGORY);
		/** The reference position. */
		private final Position fPosition= new Position(0);

		/**
		 * Called before document changes occur. It must be followed by a call to postReplace().
		 *
		 * @param document the document on which to track the reference position.
		 * @param offset the offset
		 * @throws BadLocationException if the offset describes an invalid range in this document
		 *
		 */
		public void preReplace(IDocument document, int offset) throws BadLocationException {
			fPosition.setOffset(offset);
			try {
				document.addPositionCategory(CATEGORY);
				document.addPositionUpdater(fPositionUpdater);
				document.addPosition(CATEGORY, fPosition);

			} catch (BadPositionCategoryException e) {
				// should not happen
				JavaPlugin.log(e);
			}
		}

		/**
		 * Called after the document changed occurred. It must be preceded by a call to preReplace().
		 *
		 * @param document the document on which to track the reference position.
		 * @return offset after the replace
		 */
		public int postReplace(IDocument document) {
			try {
				document.removePosition(CATEGORY, fPosition);
				document.removePositionUpdater(fPositionUpdater);
				document.removePositionCategory(CATEGORY);

			} catch (BadPositionCategoryException e) {
				// should not happen
				JavaPlugin.log(e);
			}
			return fPosition.getOffset();
		}
	}

	protected static class ExitPolicy implements IExitPolicy {

		final char fExitCharacter;
		private final IDocument fDocument;

		public ExitPolicy(char exitCharacter, IDocument document) {
			fExitCharacter= exitCharacter;
			fDocument= document;
		}

		/*
		 * @see org.eclipse.jdt.internal.ui.text.link.LinkedPositionUI.ExitPolicy#doExit(org.eclipse.jdt.internal.ui.text.link.LinkedPositionManager, org.eclipse.swt.events.VerifyEvent, int, int)
		 */
		@Override
		public ExitFlags doExit(LinkedModeModel environment, VerifyEvent event, int offset, int length) {

			if (event.character == fExitCharacter) {
				if (environment.anyPositionContains(offset))
					return new ExitFlags(ILinkedModeListener.UPDATE_CARET, false);
				else
					return new ExitFlags(ILinkedModeListener.UPDATE_CARET, true);
			}

			switch (event.character) {
				case ';':
					return new ExitFlags(ILinkedModeListener.NONE, true);
				case SWT.CR:
					// 1) when entering an anonymous class as a parameter, we don't want
					// to jump after the parenthesis when return is pressed
					// 2) after auto completion of methods without parameters, exit from linked mode when return is pressed
					if (offset > 0) {
						try {
							char prevOffsetChar= fDocument.getChar(offset - 1);
							if (prevOffsetChar == '{' || prevOffsetChar == ';')
								return new ExitFlags(ILinkedModeListener.EXIT_ALL, true);
						} catch (BadLocationException e) {
						}
					}
					return null;
				default:
					return null;
			}
		}

	}

	private StyledString fDisplayString;
	private String fReplacementString;
	private int fReplacementOffset;
	private int fReplacementLength;
	private int fCursorPosition;
	private Image fImage;
	private IContextInformation fContextInformation;
	private ProposalInfo fProposalInfo;
	private char[] fTriggerCharacters;
	private String fSortString;
	private int fRelevance;
	private boolean fIsInJavadoc;

	private int fPatternMatchRule= -1;

	private StyleRange fRememberedStyleRange;

	private boolean fToggleEating;
	private ITextViewer fTextViewer;


	/**
	 * The control creator.
	 *
	 * @since 3.2
	 */
	private IInformationControlCreator fCreator;
	/**
	 * The CSS used to format javadoc information.
	 * @since 3.3
	 */
	private static String fgCSSStyles;

	/**
	 * The invocation context of this completion proposal. Can be <code>null</code>.
	 */
	protected final JavaContentAssistInvocationContext fInvocationContext;

	/**
	 * Cache to store last validation state.
	 * @since 3.5
	 */
	private boolean fIsValidated= true;

	/**
	 * The text presentation listener.
	 * @since 3.6
	 */
	private ITextPresentationListener fTextPresentationListener;

	protected AbstractJavaCompletionProposal() {
		fInvocationContext= null;
	}

	protected AbstractJavaCompletionProposal(JavaContentAssistInvocationContext context) {
		fInvocationContext= context;
	}

	/*
	 * @see ICompletionProposalExtension#getTriggerCharacters()
	 */
	@Override
	public char[] getTriggerCharacters() {
		return fTriggerCharacters;
	}

	/**
	 * Sets the trigger characters.
	 *
	 * @param triggerCharacters The set of characters which can trigger the application of this
	 *        completion proposal
	 */
	public void setTriggerCharacters(char[] triggerCharacters) {
		fTriggerCharacters= triggerCharacters;
	}

	/**
	 * Sets the proposal info.
	 *
	 * @param proposalInfo The additional information associated with this proposal or
	 *        <code>null</code>
	 */
	public void setProposalInfo(ProposalInfo proposalInfo) {
		fProposalInfo= proposalInfo;
	}

	/**
	 * Returns the additional proposal info, or <code>null</code> if none exists.
	 *
	 * @return the additional proposal info, or <code>null</code> if none exists
	 */
	protected ProposalInfo getProposalInfo() {
		return fProposalInfo;
	}

	/**
	 * Sets the cursor position relative to the insertion offset. By default this is the length of
	 * the completion string (Cursor positioned after the completion)
	 *
	 * @param cursorPosition The cursorPosition to set
	 */
	public void setCursorPosition(int cursorPosition) {
		Assert.isTrue(cursorPosition >= 0);
		fCursorPosition= cursorPosition;
	}

	protected int getCursorPosition() {
		return fCursorPosition;
	}

	/*
	 * @see ICompletionProposal#apply
	 */
	@Override
	public final void apply(IDocument document) {
		// not used any longer
		apply(document, (char) 0, getReplacementOffset() + getReplacementLength());
	}

	/*
	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension#apply(org.eclipse.jface.text.IDocument, char, int)
	 */
	@Override
	public void apply(IDocument document, char trigger, int offset) {

		if (isSupportingRequiredProposals()) {
			CompletionProposal coreProposal= ((MemberProposalInfo)getProposalInfo()).fProposal;
			CompletionProposal[] requiredProposals= coreProposal.getRequiredProposals();
			for (int i= 0; requiredProposals != null &&  i < requiredProposals.length; i++) {
				int oldLen= document.getLength();
				if (requiredProposals[i].getKind() == CompletionProposal.TYPE_REF) {
					LazyJavaCompletionProposal proposal= createRequiredTypeCompletionProposal(requiredProposals[i], fInvocationContext);
					proposal.apply(document);
					setReplacementOffset(getReplacementOffset() + document.getLength() - oldLen);
				} else if (requiredProposals[i].getKind() == CompletionProposal.TYPE_IMPORT) {
					ImportCompletionProposal proposal= new ImportCompletionProposal(requiredProposals[i], fInvocationContext, coreProposal.getKind());
					proposal.setReplacementOffset(getReplacementOffset());
					proposal.apply(document);
					setReplacementOffset(getReplacementOffset() + document.getLength() - oldLen);
				} else if (requiredProposals[i].getKind() == CompletionProposal.METHOD_IMPORT) {
					ImportCompletionProposal proposal= new ImportCompletionProposal(requiredProposals[i], fInvocationContext, coreProposal.getKind());
					proposal.setReplacementOffset(getReplacementOffset());
					proposal.apply(document);
					setReplacementOffset(getReplacementOffset() + document.getLength() - oldLen);
				} else if (requiredProposals[i].getKind() == CompletionProposal.FIELD_IMPORT) {
					ImportCompletionProposal proposal= new ImportCompletionProposal(requiredProposals[i], fInvocationContext, coreProposal.getKind());
					proposal.setReplacementOffset(getReplacementOffset());
					proposal.apply(document);
					setReplacementOffset(getReplacementOffset() + document.getLength() - oldLen);
				} else {
					/*
					 * In 3.3 we only support the above required proposals, see
					 * CompletionProposal#getRequiredProposals()
					 */
					 Assert.isTrue(false);
				}
			}
		}

		try {
			boolean isSmartTrigger= isSmartTrigger(trigger);

			String replacement;
			if (isSmartTrigger || trigger == (char) 0) {
				int referenceOffset= getReplacementOffset() + getReplacementLength();
				replacement= getReplacementString();
				//add ; to the replacement string if replacement string do not end with a semicolon and the document do not already have a ; at the reference offset.
				if (trigger == ';' && replacement.charAt(replacement.length() - 1) != ';' && (referenceOffset >= document.getLength() || document.getChar(referenceOffset) != ';')) {
					replacement= replacement + ";"; //$NON-NLS-1$
					setReplacementString(replacement);
				}
			} else {
				StringBuffer buffer= new StringBuffer(getReplacementString());

				// fix for PR #5533. Assumes that no eating takes place.
				if ((getCursorPosition() > 0 && getCursorPosition() <= buffer.length() && buffer.charAt(getCursorPosition() - 1) != trigger)) {
					// insert trigger ';' for methods with parameter at the end of the replacement string and not at the cursor position.
					int length= getReplacementString().length();
					if (trigger == ';' && getCursorPosition() != length) {
						if (buffer.charAt(length - 1) != trigger) {
							buffer.insert(length, trigger);
						}
					} else {
						buffer.insert(getCursorPosition(), trigger);
						setCursorPosition(getCursorPosition() + 1);
					}
				}

				replacement= buffer.toString();
				setReplacementString(replacement);
			}

			// reference position just at the end of the document change.
			int referenceOffset= getReplacementOffset() + getReplacementLength();
			final ReferenceTracker referenceTracker= new ReferenceTracker();
			referenceTracker.preReplace(document, referenceOffset);

			replace(document, getReplacementOffset(), getReplacementLength(), replacement);

			referenceOffset= referenceTracker.postReplace(document);
			setReplacementOffset(referenceOffset - (replacement == null ? 0 : replacement.length()));

			// PR 47097
			if (isSmartTrigger) {
				// avoid inserting redundant semicolon when smart insert is enabled.
				if (!(trigger == ';' && (replacement.endsWith(";") || document.getChar(referenceOffset) == ';'))) { //$NON-NLS-1$
					handleSmartTrigger(document, trigger, referenceOffset);
				}
			}

		} catch (BadLocationException x) {
			// ignore
		}
	}


	/**
	 * Creates the required type proposal.
	 * 
	 * @param completionProposal the core completion proposal
	 * @param invocationContext invocation context
	 * @return the required type completion proposal
	 * @since 3.5
	 */
	protected LazyJavaCompletionProposal createRequiredTypeCompletionProposal(CompletionProposal completionProposal, JavaContentAssistInvocationContext invocationContext) {
		if (PreferenceConstants.getPreferenceStore().getBoolean(PreferenceConstants.CODEASSIST_FILL_ARGUMENT_NAMES))
			return (LazyJavaCompletionProposal)new FillArgumentNamesCompletionProposalCollector(invocationContext).createJavaCompletionProposal(completionProposal);
		else
			return new LazyJavaTypeCompletionProposal(completionProposal, invocationContext);
	}

	private boolean isSmartTrigger(char trigger) {
		return trigger == ';' && JavaPlugin.getDefault().getCombinedPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SMART_SEMICOLON)
				|| trigger == '{' && JavaPlugin.getDefault().getCombinedPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SMART_OPENING_BRACE);
	}

	private void handleSmartTrigger(IDocument document, char trigger, int referenceOffset) throws BadLocationException {
		DocumentCommand cmd= new DocumentCommand() {
		};

		cmd.offset= referenceOffset;
		cmd.length= 0;
		cmd.text= Character.toString(trigger);
		cmd.doit= true;
		cmd.shiftsCaret= true;
		cmd.caretOffset= getReplacementOffset() + getCursorPosition();

		SmartSemicolonAutoEditStrategy strategy= new SmartSemicolonAutoEditStrategy(IJavaPartitions.JAVA_PARTITIONING);
		strategy.customizeDocumentCommand(document, cmd);

		replace(document, cmd.offset, cmd.length, cmd.text);
		setCursorPosition(cmd.caretOffset - getReplacementOffset() + cmd.text.length());
	}

	protected final void replace(IDocument document, int offset, int length, String string) throws BadLocationException {
		if (!document.get(offset, length).equals(string))
			document.replace(offset, length, string);
	}

	/*
	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension1#apply(org.eclipse.jface.text.ITextViewer, char, int, int)
	 */
	@Override
	public void apply(ITextViewer viewer, char trigger, int stateMask, int offset) {

		IDocument document= viewer.getDocument();
		if (fTextViewer == null)
			fTextViewer= viewer;

		// see https://bugs.eclipse.org/bugs/show_bug.cgi?id=96059
		// don't apply the proposal if for some reason we're not valid any longer
		if (!isInJavadoc() && !validate(document, offset, null)) {
			setCursorPosition(offset);
			if (trigger != '\0') {
				try {
					document.replace(offset, 0, String.valueOf(trigger));
					setCursorPosition(getCursorPosition() + 1);
					if (trigger == '(' && autocloseBrackets()) {
						document.replace(getReplacementOffset() + getCursorPosition(), 0, ")"); //$NON-NLS-1$
						setUpLinkedMode(document, ')');
					}
				} catch (BadLocationException x) {
					// ignore
				}
			}
			return;
		}

		// don't eat if not in preferences, XOR with Ctrl
		// but: if there is a selection, replace it!
		Point selection= viewer.getSelectedRange();
		fToggleEating= (stateMask & MODIFIER_TOGGLE_COMPLETION_MODE) != 0;
		int newLength= selection.x + selection.y - getReplacementOffset();
		if ((insertCompletion() ^ fToggleEating) && newLength >= 0)
			setReplacementLength(newLength);

		apply(document, trigger, offset);
		fToggleEating= false;
	}

	/**
	 * Tells whether the user toggled the insert mode by pressing the 'Ctrl' key.
	 * 
	 * @return <code>true</code> if the insert mode is toggled, <code>false</code> otherwise
	 * @since 3.5
	 */
	protected boolean isInsertModeToggled() {
		return fToggleEating;
	}

	/**
	 * Returns <code>true</code> if the proposal is within javadoc, <code>false</code> otherwise.
	 * 
	 * @return <code>true</code> if the proposal is within javadoc, <code>false</code> otherwise
	 */
	protected boolean isInJavadoc() {
		return fIsInJavadoc;
	}

	/**
	 * Sets the javadoc attribute.
	 *
	 * @param isInJavadoc <code>true</code> if the proposal is within javadoc
	 */
	protected void setInJavadoc(boolean isInJavadoc) {
		fIsInJavadoc= isInJavadoc;
	}

	/*
	 * @see ICompletionProposal#getSelection
	 */
	@Override
	public Point getSelection(IDocument document) {
		if (!fIsValidated)
			return null;
		return new Point(getReplacementOffset() + getCursorPosition(), 0);
	}

	/*
	 * @see ICompletionProposal#getContextInformation()
	 */
	@Override
	public IContextInformation getContextInformation() {
		return fContextInformation;
	}

	/**
	 * Sets the context information.
	 * @param contextInformation The context information associated with this proposal
	 */
	public void setContextInformation(IContextInformation contextInformation) {
		fContextInformation= contextInformation;
	}

	/*
	 * @see ICompletionProposal#getDisplayString()
	 */
	@Override
	public String getDisplayString() {
		if (fDisplayString != null)
			return fDisplayString.getString();
		return ""; //$NON-NLS-1$
	}

	/*
	 * @see ICompletionProposal#getAdditionalProposalInfo()
	 */
	@Override
	public String getAdditionalProposalInfo() {
		Object info= getAdditionalProposalInfo(new NullProgressMonitor());
		return info == null ? null : info.toString();
	}

	/*
	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension5#getAdditionalProposalInfo(org.eclipse.core.runtime.IProgressMonitor)
	 */
	@Override
	public Object getAdditionalProposalInfo(IProgressMonitor monitor) {
		if (getProposalInfo() != null) {
			String info= getProposalInfo().getInfo(monitor);
			if (info != null && info.length() > 0) {
				StringBuffer buffer= new StringBuffer();
				HTMLPrinter.insertPageProlog(buffer, 0, getCSSStyles());

				buffer.append(info);

				IJavaElement element= null;
				try {
					element= getProposalInfo().getJavaElement();
					if (element instanceof IMember) {
						String base= JavadocContentAccess2.extractBaseURL(info);
						if (base == null) {
							base= JavaDocLocations.getBaseURL(element, ((IMember) element).isBinary());
						}
						if (base != null) {
							int endHeadIdx= buffer.indexOf("</head>"); //$NON-NLS-1$
							buffer.insert(endHeadIdx, "\n<base href='" + base + "'>\n"); //$NON-NLS-1$ //$NON-NLS-2$
						}
					}
				} catch (JavaModelException e) {
					JavaPlugin.log(e);
				}

				HTMLPrinter.addPageEpilog(buffer);
				info= buffer.toString();

				return new JavadocBrowserInformationControlInput(null, element, info, 0);
			}
		}
		return null;
	}

	/**
	 * Returns the style information for displaying HTML (Javadoc) content.
	 *
	 * @return the CSS styles
	 * @since 3.3
	 */
	protected String getCSSStyles() {
		if (fgCSSStyles == null) {
			Bundle bundle= Platform.getBundle(JavaPlugin.getPluginId());
			URL url= bundle.getEntry("/JavadocHoverStyleSheet.css"); //$NON-NLS-1$
			if (url != null) {
				BufferedReader reader= null;
				try {
					url= FileLocator.toFileURL(url);
					reader= new BufferedReader(new InputStreamReader(url.openStream()));
					StringBuffer buffer= new StringBuffer(200);
					String line= reader.readLine();
					while (line != null) {
						buffer.append(line);
						buffer.append('\n');
						line= reader.readLine();
					}
					fgCSSStyles= buffer.toString();
				} catch (IOException ex) {
					JavaPlugin.log(ex);
				} finally {
					try {
						if (reader != null)
							reader.close();
					} catch (IOException e) {
					}
				}

			}
		}
		String css= fgCSSStyles;
		if (css != null) {
			FontData fontData= JFaceResources.getFontRegistry().getFontData(PreferenceConstants.APPEARANCE_JAVADOC_FONT)[0];
			css= HTMLPrinter.convertTopLevelFont(css, fontData);
		}
		return css;
	}

	/*
	 * @see ICompletionProposalExtension#getContextInformationPosition()
	 */
	@Override
	public int getContextInformationPosition() {
		if (getContextInformation() == null)
			return getReplacementOffset() - 1;
		return getReplacementOffset() + getCursorPosition();
	}

	/**
	 * Gets the replacement offset.
	 * @return Returns a int
	 */
	public int getReplacementOffset() {
		return fReplacementOffset;
	}

	/**
	 * Sets the replacement offset.
	 * @param replacementOffset The replacement offset to set
	 */
	public void setReplacementOffset(int replacementOffset) {
		Assert.isTrue(replacementOffset >= 0);
		fReplacementOffset= replacementOffset;
	}

	/*
	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension3#getCompletionOffset()
	 */
	@Override
	public int getPrefixCompletionStart(IDocument document, int completionOffset) {
		return getReplacementOffset();
	}

	/**
	 * Gets the replacement length.
	 * @return Returns a int
	 */
	public int getReplacementLength() {
		return fReplacementLength;
	}

	/**
	 * Sets the replacement length.
	 * @param replacementLength The replacementLength to set
	 */
	public void setReplacementLength(int replacementLength) {
		Assert.isTrue(replacementLength >= 0);
		fReplacementLength= replacementLength;
	}

	/**
	 * Gets the replacement string.
	 * @return Returns a String
	 */
	public String getReplacementString() {
		return fReplacementString;
	}

	/**
	 * Sets the replacement string.
	 * @param replacementString The replacement string to set
	 */
	public void setReplacementString(String replacementString) {
		Assert.isNotNull(replacementString);
		fReplacementString= replacementString;
	}

	/*
	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension3#getReplacementText()
	 */
	@Override
	public CharSequence getPrefixCompletionText(IDocument document, int completionOffset) {
		if (!isCamelCaseMatching())
			return getReplacementString();

		String prefix= getPrefix(document, completionOffset);
		return getCamelCaseCompound(prefix, getReplacementString());
	}

	/*
	 * @see ICompletionProposal#getImage()
	 */
	@Override
	public Image getImage() {
		return fImage;
	}

	/**
	 * Sets the image.
	 * @param image The image to set
	 */
	public void setImage(Image image) {
		fImage= image;
	}

	/*
	 * @see ICompletionProposalExtension#isValidFor(IDocument, int)
	 */
	@Override
	public boolean isValidFor(IDocument document, int offset) {
		return validate(document, offset, null);
	}

	/*
	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#validate(org.eclipse.jface.text.IDocument, int, org.eclipse.jface.text.DocumentEvent)
	 */
	@Override
	public boolean validate(IDocument document, int offset, DocumentEvent event) {

		if (!isOffsetValid(offset))
			return fIsValidated= false;

		fIsValidated= isValidPrefix(getPrefix(document, offset));

		if (fIsValidated && event != null) {
			// adapt replacement range to document change
			int delta= (event.fText == null ? 0 : event.fText.length()) - event.fLength;
			final int newLength= Math.max(getReplacementLength() + delta, 0);
			setReplacementLength(newLength);
		}

		return fIsValidated;
	}

	/**
	 * Checks whether the given offset is valid for this proposal.
	 * 
	 * @param offset the caret offset
	 * @return <code>true</code> if the offset is valid for this proposal
	 * @since 3.5
	 */
	protected boolean isOffsetValid(int offset) {
		return getReplacementOffset() <= offset;
	}

	/**
	 * Checks whether <code>pattern</code> is a valid pattern for this proposal. Usually, while code
	 * completion is in progress, the user types and edits the pattern in the document in order to
	 * filter the proposal list. From {@link #validate(IDocument, int, DocumentEvent) }, the current
	 * pattern in the document is extracted and this method is called to find out whether the
	 * proposal is still valid.
	 * <p>
	 * The default implementation checks if <code>pattern</code> matches the proposal's
	 * {@link #getDisplayString() display string} using the {@link #isPrefix(String, String) }
	 * method.
	 * </p>
	 *
	 * @param pattern the current pattern in the document
	 * @return <code>true</code> if <code>pattern</code> is a valid match for this proposal
	 */
	protected boolean isValidPrefix(String pattern) {
		/*
		 * See http://dev.eclipse.org/bugs/show_bug.cgi?id=17667
		 * why we do not use the replacement string.
		 * String word= fReplacementString;
		 *
		 * Besides that bug we also use the display string
		 * for performance reasons, as computing the
		 * replacement string can be expensive.
		 */
		return isPrefix(pattern, TextProcessor.deprocess(getDisplayString()));
	}

	/**
	 * Gets the proposal's relevance.
	 * @return Returns a int
	 */
	@Override
	public int getRelevance() {
		if (fPatternMatchRule == SearchPattern.R_SUBSTRING_MATCH) {
			return fRelevance - 1;
		}
		return fRelevance;
	}

	/**
	 * Sets the proposal's relevance.
	 * @param relevance The relevance to set
	 */
	public void setRelevance(int relevance) {
		fRelevance= relevance;
	}

	/**
	 * Returns the text in <code>document</code> from {@link #getReplacementOffset()} to
	 * <code>offset</code>. Returns the empty string if <code>offset</code> is before the
	 * replacement offset or if an exception occurs when accessing the document.
	 *
	 * @param document the document
	 * @param offset the offset
	 * @return the prefix
	 * @since 3.2
	 */
	protected String getPrefix(IDocument document, int offset) {
		try {
			int length= offset - getReplacementOffset();
			if (length > 0)
				return document.get(getReplacementOffset(), length);
		} catch (BadLocationException x) {
		}
		return ""; //$NON-NLS-1$
	}

	/**
	 * Case insensitive matching of the <code>pattern</code> within the given <code>string</code>.
	 *
	 * @param pattern the pattern
	 * @param string the string to look for the pattern
	 * @return <code>true</code> if the given pattern matches the string as a prefix, as a CamelCase
	 *         match, or as a substring pattern and <code>false</code> if <code>pattern</code> is
	 *         longer than <code>string</code> or if the pattern doesn't match the string based on
	 *         any of these rules
	 * @since 3.2
	 */
	protected boolean isPrefix(String pattern, String string) {
		if (pattern == null || string == null || pattern.length() > string.length())
			return false;
		fPatternMatchRule= getPatternMatchRule(pattern, string);
		return fPatternMatchRule != -1;
	}

	/**
	 * Matches the given <code>pattern</code> in <code>string</code> and returns the match rule.
	 * 
	 * @param pattern the pattern to match
	 * @param string the string to look for the pattern
	 * @return the match rule used to match the given <code>pattern</code> in <code>string</code>,
	 *         or -1 if the <code>pattern</code> doesn't match the <code>string</code> based on any
	 *         rule
	 * @since 3.12
	 */
	protected int getPatternMatchRule(String pattern, String string) {
		String start= string.substring(0, pattern.length());
		if (start.equalsIgnoreCase(pattern)) {
			return SearchPattern.R_PREFIX_MATCH;
		} else if (isCamelCaseMatching() && CharOperation.camelCaseMatch(pattern.toCharArray(), string.toCharArray())) {
			return SearchPattern.R_CAMELCASE_MATCH;
		} else if (isSubstringMatching() && CharOperation.substringMatch(pattern.toCharArray(), string.toCharArray())) {
			return SearchPattern.R_SUBSTRING_MATCH;
		} else {
			return -1;
		}
	}

	/**
	 * Matches <code>prefix</code> against <code>string</code> and replaces the matched region
	 * by prefix. Case is preserved as much as possible. This method returns <code>string</code> if camel case completion
	 * is disabled. Examples when camel case completion is enabled:
	 * <ul>
	 * <li>getCamelCompound("NuPo", "NullPointerException") -> "NuPointerException"</li>
	 * <li>getCamelCompound("NuPoE", "NullPointerException") -> "NuPoException"</li>
	 * <li>getCamelCompound("hasCod", "hashCode") -> "hasCode"</li>
	 * </ul>
	 *
	 * @param prefix the prefix to match against
	 * @param string the string to match
	 * @return a compound of prefix and any postfix taken from <code>string</code>
	 * @since 3.2
	 */
	protected final String getCamelCaseCompound(String prefix, String string) {
		if (prefix.length() > string.length())
			return string;

		// a normal prefix - no camel case logic at all
		String start= string.substring(0, prefix.length());
		if (start.equalsIgnoreCase(prefix))
			return string;

		final char[] patternChars= prefix.toCharArray();
		final char[] stringChars= string.toCharArray();

		for (int i= 1; i <= stringChars.length; i++)
			if (CharOperation.camelCaseMatch(patternChars, 0, patternChars.length, stringChars, 0, i))
				return prefix + string.substring(i);

		// Not a camel case match at all.
		// This should not happen -> stay with the default behavior
		return string;
	}

	/**
	 * Returns true if camel case matching is enabled.
	 *
	 * @return <code>true</code> if camel case matching is enabled
	 * @since 3.2
	 */
	protected boolean isCamelCaseMatching() {
		String value= JavaCore.getOption(JavaCore.CODEASSIST_CAMEL_CASE_MATCH);
		return JavaCore.ENABLED.equals(value);
	}

	/**
	 * Returns true if substring matching is enabled.
	 *
	 * @return <code>true</code> if substring matching is enabled
	 * @since 3.12
	 */
	protected boolean isSubstringMatching() {
		String value= JavaCore.getOption(JavaCore.CODEASSIST_SUBSTRING_MATCH);
		return JavaCore.ENABLED.equals(value);
	}

	protected static boolean insertCompletion() {
		IPreferenceStore preference= JavaPlugin.getDefault().getPreferenceStore();
		return preference.getBoolean(PreferenceConstants.CODEASSIST_INSERT_COMPLETION);
	}

	private static Color getForegroundColor() {
		IPreferenceStore preference= JavaPlugin.getDefault().getPreferenceStore();
		RGB rgb= PreferenceConverter.getColor(preference, PreferenceConstants.CODEASSIST_REPLACEMENT_FOREGROUND);
		JavaTextTools textTools= JavaPlugin.getDefault().getJavaTextTools();
		return textTools.getColorManager().getColor(rgb);
	}

	private static Color getBackgroundColor() {
		IPreferenceStore preference= JavaPlugin.getDefault().getPreferenceStore();
		RGB rgb= PreferenceConverter.getColor(preference, PreferenceConstants.CODEASSIST_REPLACEMENT_BACKGROUND);
		JavaTextTools textTools= JavaPlugin.getDefault().getJavaTextTools();
		return textTools.getColorManager().getColor(rgb);
	}

	private void repairPresentation(ITextViewer viewer) {
		if (fRememberedStyleRange != null) {
			if (viewer instanceof ITextViewerExtension2) {
				// attempts to reduce the redraw area
				ITextViewerExtension2 viewer2= (ITextViewerExtension2)viewer;
				viewer2.invalidateTextPresentation(fRememberedStyleRange.start, fRememberedStyleRange.length);
			} else
				viewer.invalidateTextPresentation();
		}
	}

	private void updateStyle(ITextViewer viewer) {
		StyledText text= viewer.getTextWidget();
		int widgetOffset= getWidgetOffset(viewer, fRememberedStyleRange.start);
		StyleRange range= new StyleRange(fRememberedStyleRange);
		range.start= widgetOffset;
		range.length= fRememberedStyleRange.length;
		StyleRange currentRange= text.getStyleRangeAtOffset(widgetOffset);
		if (currentRange != null) {
			range.strikeout= currentRange.strikeout;
			range.underline= currentRange.underline;
			range.fontStyle= currentRange.fontStyle;
		}

		// http://dev.eclipse.org/bugs/show_bug.cgi?id=34754
		try {
			text.setStyleRange(range);
		} catch (IllegalArgumentException x) {
			// catching exception as offset + length might be outside of the text widget
			fRememberedStyleRange= null;
		}
	}

	/**
	 * Convert a document offset to the corresponding widget offset.
	 * 
	 * @param viewer the text viewer
	 * @param documentOffset the document offset
	 * @return widget offset
	 * @since 3.6
	 */
	private int getWidgetOffset(ITextViewer viewer, int documentOffset) {
		if (viewer instanceof ITextViewerExtension5) {
			ITextViewerExtension5 extension= (ITextViewerExtension5)viewer;
			return extension.modelOffset2WidgetOffset(documentOffset);
		}
		IRegion visible= viewer.getVisibleRegion();
		int widgetOffset= documentOffset - visible.getOffset();
		if (widgetOffset > visible.getLength()) {
			return -1;
		}
		return widgetOffset;
	}


	/**
	 * Creates a style range for the text viewer.
	 * 
	 * @param viewer the text viewer
	 * @return the new style range for the text viewer or <code>null</code>
	 * @since 3.6
	 */
	private StyleRange createStyleRange(ITextViewer viewer) {
		StyledText text= viewer.getTextWidget();
		if (text == null || text.isDisposed())
			return null;

		int widgetCaret= text.getCaretOffset();

		int modelCaret= 0;
		if (viewer instanceof ITextViewerExtension5) {
			ITextViewerExtension5 extension= (ITextViewerExtension5) viewer;
			modelCaret= extension.widgetOffset2ModelOffset(widgetCaret);
		} else {
			IRegion visibleRegion= viewer.getVisibleRegion();
			modelCaret= widgetCaret + visibleRegion.getOffset();
		}

		if (modelCaret >= getReplacementOffset() + getReplacementLength())
			return null;

		int length= getReplacementOffset() + getReplacementLength() - modelCaret;

		Color foreground= getForegroundColor();
		Color background= getBackgroundColor();

		return new StyleRange(modelCaret, length, foreground, background);
	}

	/*
	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#selected(ITextViewer, boolean)
	 */
	@Override
	public void selected(final ITextViewer viewer, boolean smartToggle) {
		repairPresentation(viewer);
		fRememberedStyleRange= null;

		if (!insertCompletion() ^ smartToggle) {
			StyleRange range= createStyleRange(viewer);
			if (range == null)
				return;
			
			fRememberedStyleRange= range;

			if (viewer instanceof ITextViewerExtension4) {
				if (fTextPresentationListener == null) {
					fTextPresentationListener= new ITextPresentationListener() {
						@Override
						public void applyTextPresentation(TextPresentation textPresentation) {
							fRememberedStyleRange= createStyleRange(viewer);
							if (fRememberedStyleRange != null)
								textPresentation.mergeStyleRange(fRememberedStyleRange);
						}
					};
					((ITextViewerExtension4)viewer).addTextPresentationListener(fTextPresentationListener);
				}
				repairPresentation(viewer);
			} else
				updateStyle(viewer);
		}
	}

	/*
	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension2#unselected(ITextViewer)
	 */
	@Override
	public void unselected(ITextViewer viewer) {
		if (fTextPresentationListener != null) {
			((ITextViewerExtension4)viewer).removeTextPresentationListener(fTextPresentationListener);
			fTextPresentationListener= null;
		}
		repairPresentation(viewer);
		fRememberedStyleRange= null;
	}

	/*
	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension3#getInformationControlCreator()
	 */
	@Override
	public IInformationControlCreator getInformationControlCreator() {
		Shell shell= JavaPlugin.getActiveWorkbenchShell();
		if (shell == null || !BrowserInformationControl.isAvailable(shell))
			return null;

		if (fCreator == null) {
			/*
			 * FIXME: Take control creators (and link handling) out of JavadocHover,
			 * see https://bugs.eclipse.org/bugs/show_bug.cgi?id=232024
			 */
			JavadocHover.PresenterControlCreator presenterControlCreator= new JavadocHover.PresenterControlCreator(getSite());
			fCreator= new JavadocHover.HoverControlCreator(presenterControlCreator, true);
		}
		return fCreator;
	}

	private IWorkbenchSite getSite() {
		IWorkbenchPage page= JavaPlugin.getActivePage();
		if (page != null) {
			IWorkbenchPart part= page.getActivePart();
			if (part != null)
				return part.getSite();
		}
		return null;
	}

	public String getSortString() {
		return fSortString;
	}

	protected void setSortString(String string) {
		fSortString= string;
	}

	protected ITextViewer getTextViewer() {
		return fTextViewer;
	}

	protected boolean isToggleEating() {
		return fToggleEating;
	}

	/**
	 * Sets up a simple linked mode at {@link #getCursorPosition()} and an exit policy that will
	 * exit the mode when <code>closingCharacter</code> is typed and an exit position at
	 * <code>getCursorPosition() + 1</code>.
	 *
	 * @param document the document
	 * @param closingCharacter the exit character
	 */
	protected void setUpLinkedMode(IDocument document, char closingCharacter) {
		if (getTextViewer() != null && autocloseBrackets()) {
			int offset= getReplacementOffset() + getCursorPosition();
			int exit= getReplacementOffset() + getReplacementString().length();
			try {
				LinkedPositionGroup group= new LinkedPositionGroup();
				group.addPosition(new LinkedPosition(document, offset, 0, LinkedPositionGroup.NO_STOP));

				LinkedModeModel model= new LinkedModeModel();
				model.addGroup(group);
				model.forceInstall();

				LinkedModeUI ui= new EditorLinkedModeUI(model, getTextViewer());
				ui.setSimpleMode(true);
				ui.setExitPolicy(new ExitPolicy(closingCharacter, document));
				ui.setExitPosition(getTextViewer(), exit, 0, Integer.MAX_VALUE);
				ui.setCyclingMode(LinkedModeUI.CYCLE_NEVER);
				ui.enter();
			} catch (BadLocationException x) {
				JavaPlugin.log(x);
			}
		}
	}

	protected boolean autocloseBrackets() {
		IPreferenceStore preferenceStore= JavaPlugin.getDefault().getPreferenceStore();
		return preferenceStore.getBoolean(PreferenceConstants.EDITOR_CLOSE_BRACKETS);
	}

	protected void setDisplayString(String string) {
		fDisplayString= new StyledString(string);
	}

	/*
	 * @see org.eclipse.jface.text.contentassist.ICompletionProposalExtension6#getStyledDisplayString()
	 * @since 3.4
	 */
	@Override
	public StyledString getStyledDisplayString() {
		return fDisplayString;
	}

	public void setStyledDisplayString(StyledString text) {
		fDisplayString= text;
	}

	@Override
	public StyledString emphasizeMatch(IDocument document, int offset, BoldStylerProvider boldStylerProvider) {
		StyledString styledDisplayString= new StyledString();
		styledDisplayString.append(getStyledDisplayString());

		String pattern= getPatternToEmphasizeMatch(document, offset);
		if (pattern != null && pattern.length() > 0) {
			String displayString= styledDisplayString.getString();
			int index= displayString.indexOf('(');
			if (index == -1) {
				index= displayString.indexOf(':');
				if (index == -1) {
					index= displayString.indexOf('-');
				}
			}
			if (index != -1) {
				displayString= displayString.substring(0, index);
			}
			int patternMatchRule= getPatternMatchRule(pattern, displayString);
			int[] matchingRegions= SearchPattern.getMatchingRegions(pattern, displayString, patternMatchRule);
			Strings.markMatchingRegions(styledDisplayString, 0, matchingRegions, boldStylerProvider.getBoldStyler());
		}
		return styledDisplayString;
	}

	/**
	 * Computes the token at the given <code>offset</code> in <code>document</code> to emphasize the
	 * ranges matching this token in proposal's display string.
	 * 
	 * @param document the document where content assist is invoked
	 * @param offset the offset in the document at current caret location
	 * @return the token at the given <code>offset</code> in <code>document</code> to be used for
	 *         emphasizing matching ranges in proposal's display string
	 * @since 3.12
	 */
	protected String getPatternToEmphasizeMatch(IDocument document, int offset) {
		int start= getPrefixCompletionStart(document, offset);
		int patternLength= offset - start;
		String pattern= null;
		try {
			pattern= document.get(start, patternLength);
		} catch (BadLocationException e) {
			// return null
		}
		return pattern;
	}

	/*
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString() {
		return getDisplayString();
	}

	/**
	 * Returns the java element proposed by the receiver, possibly <code>null</code>.
	 *
	 * @return the java element proposed by the receiver, possibly <code>null</code>
	 */
	public IJavaElement getJavaElement() {
		if (getProposalInfo() != null)
			try {
				return getProposalInfo().getJavaElement();
			} catch (JavaModelException x) {
				JavaPlugin.log(x);
			}
		return null;
	}

	/**
	 * Tells whether required proposals are supported by this proposal.
	 *
	 * @return <code>true</code> if required proposals are supported by this proposal
	 * @see CompletionProposal#getRequiredProposals()
	 * @since 3.3
	 */
	protected boolean isSupportingRequiredProposals() {
		if (fInvocationContext == null)
			return false;

		ProposalInfo proposalInfo= getProposalInfo();
		if (!(proposalInfo instanceof MemberProposalInfo || proposalInfo instanceof AnonymousTypeProposalInfo))
			return false;

		CompletionProposal proposal= ((MemberProposalInfo)proposalInfo).fProposal;
		return proposal != null && (proposal.getKind() == CompletionProposal.METHOD_REF || proposal.getKind() == CompletionProposal.FIELD_REF || proposal.getKind() == CompletionProposal.TYPE_REF || proposal.getKind() == CompletionProposal.CONSTRUCTOR_INVOCATION || proposal.getKind() == CompletionProposal.ANONYMOUS_CLASS_CONSTRUCTOR_INVOCATION);
	}

}
