/*******************************************************************************
 * Copyright (c) 2016, 2019 Red Hat Inc. and others.
 * This program and the accompanying materials are made
 * available under the terms of the Eclipse Public License 2.0
 * which is available at https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *   Lucas Bullen (Red Hat Inc.) - initial implementation
 *   Michał Niewrzał (Rogue Wave Software Inc.)
 *   Lucas Bullen (Red Hat Inc.) - Refactored for incomplete completion lists
 *                               - [Bug 517428] Requests sent before initialization
 *   Max Bureck (Fraunhofer FOKUS) - [Bug 536089] Execute the CompletionItem.command given after applying the completion
 *                                 - [Bug 558928] Variables replacement fix for Windows
 *******************************************************************************/
package org.eclipse.lsp4e.operations.completion;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.jdt.annotation.NonNull;
import org.eclipse.jface.internal.text.html.BrowserInformationControl;
import org.eclipse.jface.text.AbstractReusableInformationControlCreator;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.contentassist.BoldStylerProvider;
import org.eclipse.jface.text.contentassist.CompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension3;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension4;
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.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.jface.text.link.ProposalPosition;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.jface.viewers.StyledString.Styler;
import org.eclipse.lsp4e.LSPEclipseUtils;
import org.eclipse.lsp4e.LanguageServerPlugin;
import org.eclipse.lsp4e.LanguageServiceAccessor;
import org.eclipse.lsp4e.command.CommandExecutor;
import org.eclipse.lsp4e.operations.hover.FocusableBrowserInformationControl;
import org.eclipse.lsp4e.ui.LSPImages;
import org.eclipse.lsp4j.Command;
import org.eclipse.lsp4j.CompletionItem;
import org.eclipse.lsp4j.InsertReplaceEdit;
import org.eclipse.lsp4j.InsertTextFormat;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.eclipse.lsp4j.TextEdit;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.eclipse.lsp4j.services.LanguageServer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.TextStyle;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.texteditor.link.EditorLinkedModeUI;

@SuppressWarnings("restriction")
public class LSIncompleteCompletionProposal
		implements ICompletionProposal, ICompletionProposalExtension3, ICompletionProposalExtension4,
		ICompletionProposalExtension5, ICompletionProposalExtension6, ICompletionProposalExtension7,
		IContextInformation {

	private static final int RESOLVE_TIMEOUT = 500;
	// Those variables should be defined in LSP4J and reused here whenever done there
	// See https://github.com/eclipse/lsp4j/issues/149
	/** The currently selected text or the empty string */
	private static final String TM_SELECTED_TEXT = "TM_SELECTED_TEXT"; //$NON-NLS-1$
	/** The contents of the current line */
	private static final String TM_CURRENT_LINE = "TM_CURRENT_LINE"; //$NON-NLS-1$
	/** The contents of the word under cursor or the empty string */
	private static final String TM_CURRENT_WORD = "TM_CURRENT_WORD"; //$NON-NLS-1$
	/** The zero-index based line number */
	private static final String TM_LINE_INDEX = "TM_LINE_INDEX"; //$NON-NLS-1$
	/** The one-index based line number */
	private static final String TM_LINE_NUMBER = "TM_LINE_NUMBER"; //$NON-NLS-1$
	/** The filename of the current document */
	private static final String TM_FILENAME = "TM_FILENAME"; //$NON-NLS-1$
	/** The filename of the current document without its extensions */
	private static final String TM_FILENAME_BASE = "TM_FILENAME_BASE"; //$NON-NLS-1$
	/** The directory of the current document */
	private static final String TM_DIRECTORY = "TM_DIRECTORY"; //$NON-NLS-1$
	/** The full file path of the current document */
	private static final String TM_FILEPATH = "TM_FILEPATH"; //$NON-NLS-1$

	private static final Styler DEPRECATE = new Styler() {
		@Override
		public void applyStyles(TextStyle textStyle) {
			textStyle.strikeout = true;
			textStyle.foreground = PlatformUI.getWorkbench().getDisplay().getSystemColor(SWT.COLOR_DARK_GRAY);
		};
	};

	protected final CompletionItem item;
	private int initialOffset = -1;
	protected int bestOffset = -1;
	protected int currentOffset = -1;
	protected ITextViewer viewer;
	private final IDocument document;
	private IRegion selection;
	private LinkedPosition firstPosition;
	// private LSPDocumentInfo info;
	private Integer rankCategory;
	private Integer rankScore;
	private String documentFilter;
	private String documentFilterAddition = ""; //$NON-NLS-1$
	private LanguageServer languageServer;

	public LSIncompleteCompletionProposal(@NonNull IDocument document, int offset, @NonNull CompletionItem item,
			LanguageServer languageServer) {
		this.item = item;
		this.document = document;
		this.languageServer = languageServer;
		this.initialOffset = offset;
		this.currentOffset = offset;
		this.bestOffset = getPrefixCompletionStart(document, offset);
	}

	/**
	 * See {@link CompletionProposalTools#getFilterFromDocument} for filter
	 * generation logic
	 *
	 * @return The document filter for the given offset
	 */
	public String getDocumentFilter(int offset) throws BadLocationException {
		if (documentFilter != null) {
			if (offset != currentOffset) {
				documentFilterAddition = document.get(initialOffset, offset - initialOffset);
				rankScore = null;
				rankCategory = null;
				currentOffset = offset;
			}
			return documentFilter + documentFilterAddition;
		}
		currentOffset = offset;
		return getDocumentFilter();
	}

	/**
	 * See {@link CompletionProposalTools#getFilterFromDocument} for filter
	 * generation logic
	 *
	 * @return The document filter for the last given offset
	 */
	public String getDocumentFilter() throws BadLocationException {
		if (documentFilter != null) {
			return documentFilter + documentFilterAddition;
		}
		documentFilter = CompletionProposalTools.getFilterFromDocument(document, currentOffset,
				getFilterString(), bestOffset);
		documentFilterAddition = ""; //$NON-NLS-1$
		return documentFilter;
	}

	/**
	 * See {@link CompletionProposalTools#getScoreOfFilterMatch} for ranking logic
	 *
	 * @return The rank of the match between the document's filter and this
	 *         completion's filter.
	 */
	public int getRankScore() {
		if (rankScore != null)
			return rankScore;
		try {
			rankScore = CompletionProposalTools.getScoreOfFilterMatch(getDocumentFilter(),
					getFilterString());
		} catch (BadLocationException e) {
			LanguageServerPlugin.logError(e);
			rankScore = -1;
		}
		return rankScore;
	}

	/**
	 * See {@link CompletionProposalTools#getCategoryOfFilterMatch} for category
	 * logic
	 *
	 * @return The category of the match between the document's filter and this
	 *         completion's filter.
	 */
	public int getRankCategory() {
		if (rankCategory != null) {
			return rankCategory;
		}
		try {
			rankCategory = CompletionProposalTools.getCategoryOfFilterMatch(getDocumentFilter(),
					getFilterString());
		} catch (BadLocationException e) {
			LanguageServerPlugin.logError(e);
			rankCategory = 5;
		}
		return rankCategory;
	}

	public int getBestOffset() {
		return this.bestOffset;
	}

	public void updateOffset(int offset) {
		this.bestOffset = getPrefixCompletionStart(document, offset);
	}

	public CompletionItem getItem() {
		return this.item;
	}

	private boolean isDeprecated() {
		return item.getDeprecated() != null && item.getDeprecated().booleanValue();
	}

	@Override
	public StyledString getStyledDisplayString(IDocument document, int offset, BoldStylerProvider boldStylerProvider) {
		String rawString = getDisplayString();
		StyledString res = isDeprecated()
				? new StyledString(rawString, DEPRECATE)
				: new StyledString(rawString);
		if (offset > this.bestOffset) {
			try {
				String subString = getDocumentFilter(offset).toLowerCase();
				int lastIndex = 0;
				String lowerRawString = rawString.toLowerCase();
				for (Character c : subString.toCharArray()) {
					int index = lowerRawString.indexOf(c, lastIndex);
					if (index < 0) {
						return res;
					} else {
						res.setStyle(index, 1, new Styler() {

							@Override
							public void applyStyles(TextStyle textStyle) {
								if (isDeprecated()) {
									DEPRECATE.applyStyles(textStyle);
								}
								boldStylerProvider.getBoldStyler().applyStyles(textStyle);
							}

						});
						lastIndex = index + 1;
					}
				}
			} catch (BadLocationException e) {
				LanguageServerPlugin.logError(e);
			}
		}
		return res;
	}

	@Override
	public String getDisplayString() {
		return this.item.getLabel();
	}

	@Override
	public StyledString getStyledDisplayString() {
		if (Boolean.TRUE.equals(item.getDeprecated())) {
			return new StyledString(getDisplayString(), DEPRECATE);
		}
		return new StyledString(getDisplayString());
	}

	@Override
	public boolean isAutoInsertable() {
		// TODO consider what's best
		return false;
	}

	@Override
	public IInformationControlCreator getInformationControlCreator() {
		return new AbstractReusableInformationControlCreator() {
			@Override
			protected IInformationControl doCreateInformationControl(Shell parent) {
				if (BrowserInformationControl.isAvailable(parent)) {
					return new FocusableBrowserInformationControl(parent);
				} else {
					return new DefaultInformationControl(parent);
				}
			}
		};
	}

	@Override
	public String getAdditionalProposalInfo(IProgressMonitor monitor) {
		if (LanguageServiceAccessor.checkCapability(languageServer,
				capability -> Boolean.TRUE.equals(capability.getCompletionProvider().getResolveProvider()))) {
			try {
				languageServer.getTextDocumentService().resolveCompletionItem(item).thenAcceptAsync(this::updateCompletionItem)
						.get(RESOLVE_TIMEOUT, TimeUnit.MILLISECONDS);
			} catch (ExecutionException | TimeoutException e) {
				LanguageServerPlugin.logError(e);
			} catch (InterruptedException e) {
				LanguageServerPlugin.logError(e);
				Thread.currentThread().interrupt();
			}
		}

		StringBuilder res = new StringBuilder();
		if (this.item.getDetail() != null) {
			res.append("<p>" + this.item.getDetail() + "</p>"); //$NON-NLS-1$ //$NON-NLS-2$
		}
		if (res.length() > 0) {
			res.append("<br/>"); //$NON-NLS-1$
		}
		if (this.item.getDocumentation() != null) {
			String htmlDocString = LSPEclipseUtils.getHtmlDocString(this.item.getDocumentation());
			if (htmlDocString != null) {
				res.append(htmlDocString);
			}
		}

		return res.toString();
	}

	private void updateCompletionItem(CompletionItem resolvedItem) {
		if (resolvedItem == null) {
			return;
		}
		if (resolvedItem.getLabel() != null) {
			item.setLabel(resolvedItem.getLabel());
		}
		if (resolvedItem.getKind() != null) {
			item.setKind(resolvedItem.getKind());
		}
		if (resolvedItem.getDetail() != null) {
			item.setDetail(resolvedItem.getDetail());
		}
		if (resolvedItem.getDocumentation() != null) {
			item.setDocumentation(resolvedItem.getDocumentation());
		}
		if (resolvedItem.getInsertText() != null) {
			item.setInsertText(resolvedItem.getInsertText());
		}
		if (resolvedItem.getInsertTextFormat() != null) {
			item.setInsertTextFormat(resolvedItem.getInsertTextFormat());
		}
		if (resolvedItem.getTextEdit() != null) {
			item.setTextEdit(resolvedItem.getTextEdit());
		}
		if (resolvedItem.getAdditionalTextEdits() != null) {
			item.setAdditionalTextEdits(resolvedItem.getAdditionalTextEdits());
		}
	}

	@Override
	public CharSequence getPrefixCompletionText(IDocument document, int completionOffset) {
		return item.getInsertText().substring(completionOffset - this.bestOffset);
	}

	@Override
	public int getPrefixCompletionStart(IDocument document, int completionOffset) {
		Either<TextEdit, InsertReplaceEdit> textEdit = this.item.getTextEdit();
		if (textEdit != null) {
			if(textEdit.isLeft()) {
				try {
					return LSPEclipseUtils.toOffset(textEdit.getLeft().getRange().getStart(), document);
				} catch (BadLocationException e) {
					LanguageServerPlugin.logError(e);
				}
			} else {
				try {
					return LSPEclipseUtils.toOffset(textEdit.getRight().getInsert().getStart(), document);
				} catch (BadLocationException e) {
					LanguageServerPlugin.logError(e);
				}
			}
		}
		String insertText = getInsertText();
		try {
			String subDoc = document.get(
					Math.max(0, completionOffset - insertText.length()),
					Math.min(insertText.length(), completionOffset));
			for (int i = 0; i < insertText.length() && i < completionOffset; i++) {
				String tentativeCommonString = subDoc.substring(i);
				if (insertText.startsWith(tentativeCommonString)) {
					return completionOffset - tentativeCommonString.length();
				}
			}
		} catch (BadLocationException e) {
			LanguageServerPlugin.logError(e);
		}
		return completionOffset;
	}

	@Override
	public void apply(IDocument document) {
		apply(document, Character.MIN_VALUE, 0, this.bestOffset);
	}

	protected void apply(IDocument document, char trigger, int stateMask, int offset) {
		String insertText = null;
		Either<TextEdit, InsertReplaceEdit> eitherTextEdit = item.getTextEdit();
		TextEdit textEdit = null;
		if (eitherTextEdit != null) {
			if(eitherTextEdit.isLeft()) {
				textEdit = eitherTextEdit.getLeft();
			} else {
				// trick to partially support the new InsertReplaceEdit from LSP 3.16. Reuse previously code for TextEdit.
				InsertReplaceEdit insertReplaceEdit = eitherTextEdit.getRight();
				textEdit = new TextEdit(insertReplaceEdit.getInsert(), insertReplaceEdit.getNewText());
			}
		}
		try {
			if (textEdit == null) {
				insertText = getInsertText();
				Position start = LSPEclipseUtils.toPosition(this.bestOffset, document);
				Position end = LSPEclipseUtils.toPosition(offset, document); // need 2 distinct objects
				textEdit = new TextEdit(new Range(start, end), insertText);
			} else if (offset > this.initialOffset) {
				// characters were added after completion was activated
				int shift = offset - this.initialOffset;
				textEdit.getRange().getEnd().setCharacter(textEdit.getRange().getEnd().getCharacter() + shift);
			}
			{ // workaround https://github.com/Microsoft/vscode/issues/17036
				Position start = textEdit.getRange().getStart();
				Position end = textEdit.getRange().getEnd();
				if (start.getLine() > end.getLine() || (start.getLine() == end.getLine() && start.getCharacter() > end.getCharacter())) {
					textEdit.getRange().setEnd(start);
					textEdit.getRange().setStart(end);
				}
			}
			{ // allow completion items to be wrong with a too wide range
				Position documentEnd = LSPEclipseUtils.toPosition(document.getLength(), document);
				Position textEditEnd = textEdit.getRange().getEnd();
				if (documentEnd.getLine() < textEditEnd.getLine()
					|| (documentEnd.getLine() == textEditEnd.getLine() && documentEnd.getCharacter() < textEditEnd.getCharacter())) {
					textEdit.getRange().setEnd(documentEnd);
				}
			}

			if (insertText != null) {
				// try to reuse existing characters after completion location
				int shift = offset - this.bestOffset;
				int commonSize = 0;
				while (commonSize < insertText.length() - shift
					&& document.getLength() > offset + commonSize
					&& document.getChar(this.bestOffset + shift + commonSize) == insertText.charAt(commonSize + shift)) {
					commonSize++;
				}
				textEdit.getRange().getEnd().setCharacter(textEdit.getRange().getEnd().getCharacter() + commonSize);
			}
			insertText = textEdit.getNewText();
			LinkedHashMap<String, List<LinkedPosition>> regions = new LinkedHashMap<>();
			int insertionOffset = LSPEclipseUtils.toOffset(textEdit.getRange().getStart(), document);
			insertionOffset = computeNewOffset(item.getAdditionalTextEdits(), insertionOffset, document);
			if (item.getInsertTextFormat() == InsertTextFormat.Snippet) {
				int currentSnippetOffsetInInsertText = 0;
				while ((currentSnippetOffsetInInsertText = insertText.indexOf('$', currentSnippetOffsetInInsertText)) != -1) {
					StringBuilder keyBuilder = new StringBuilder();
					boolean isChoice = false;
					List<String> snippetProposals = new ArrayList<>();
					int offsetInSnippet = 1;
					while (currentSnippetOffsetInInsertText + offsetInSnippet < insertText.length() && Character.isDigit(insertText.charAt(currentSnippetOffsetInInsertText + offsetInSnippet))) {
						keyBuilder.append(insertText.charAt(currentSnippetOffsetInInsertText + offsetInSnippet));
						offsetInSnippet++;
					}
					if (keyBuilder.length() == 0 && insertText.substring(currentSnippetOffsetInInsertText).startsWith("${")) { //$NON-NLS-1$
						offsetInSnippet = 2;
						while (currentSnippetOffsetInInsertText + offsetInSnippet < insertText.length() && Character.isDigit(insertText.charAt(currentSnippetOffsetInInsertText + offsetInSnippet))) {
							keyBuilder.append(insertText.charAt(currentSnippetOffsetInInsertText + offsetInSnippet));
							offsetInSnippet++;
						}
						if (currentSnippetOffsetInInsertText + offsetInSnippet < insertText.length()) {
							char currentChar = insertText.charAt(currentSnippetOffsetInInsertText + offsetInSnippet);
							if (currentChar == ':' || currentChar == '|') {
								isChoice |= currentChar == '|';
								offsetInSnippet++;
							}
						}
						boolean close = false;
						StringBuilder valueBuilder = new StringBuilder();
						while (currentSnippetOffsetInInsertText + offsetInSnippet < insertText.length() && !close) {
							char currentChar = insertText.charAt(currentSnippetOffsetInInsertText + offsetInSnippet);
							if (valueBuilder.length() > 0 &&
								((isChoice && (currentChar == ',' || currentChar == '|') || currentChar == '}'))) {
								String value = valueBuilder.toString();
								if (value.startsWith("$")) { //$NON-NLS-1$
									String varValue = getVariableValue(value.substring(1));
									if (varValue != null) {
										value = varValue;
									}
								}
								snippetProposals.add(value);
								valueBuilder = new StringBuilder();
							} else if (currentChar != '}') {
								valueBuilder.append(currentChar);
							}
							close = currentChar == '}';
							offsetInSnippet++;
						}
					}
					String defaultProposal = snippetProposals.isEmpty() ? "" : snippetProposals.get(0); //$NON-NLS-1$
					if (keyBuilder.length() > 0) {
						String key = keyBuilder.toString();
						if (!regions.containsKey(key)) {
							regions.put(key, new ArrayList<>());
						}
						insertText = insertText.substring(0, currentSnippetOffsetInInsertText) + defaultProposal + insertText.substring(currentSnippetOffsetInInsertText + offsetInSnippet);
						LinkedPosition position = null;
						if (!snippetProposals.isEmpty()) {
							int replacementOffset = insertionOffset + currentSnippetOffsetInInsertText;
							ICompletionProposal[] proposals = snippetProposals.stream().map(string ->
								new CompletionProposal(string, replacementOffset, defaultProposal.length(), replacementOffset + string.length())
							).toArray(ICompletionProposal[]::new);
							position = new ProposalPosition(document, insertionOffset + currentSnippetOffsetInInsertText, defaultProposal.length(), proposals);
						} else {
							position = new LinkedPosition(document, insertionOffset + currentSnippetOffsetInInsertText, defaultProposal.length());
						}
						if (firstPosition == null) {
							firstPosition = position;
						}
						regions.get(key).add(position);
						currentSnippetOffsetInInsertText += defaultProposal.length();
					} else {
						currentSnippetOffsetInInsertText++;
					}
				}
			}
			textEdit.setNewText(insertText); // insertText now has placeholder removed
			List<TextEdit> additionalEdits = item.getAdditionalTextEdits();
			if (additionalEdits != null && !additionalEdits.isEmpty()) {
				List<TextEdit> allEdits = new ArrayList<>();
				allEdits.add(textEdit);
				allEdits.addAll(additionalEdits);
				LSPEclipseUtils.applyEdits(document, allEdits);
			} else {
				LSPEclipseUtils.applyEdit(textEdit, document);
			}

			if (viewer != null && !regions.isEmpty()) {
				LinkedModeModel model = new LinkedModeModel();
				for (List<LinkedPosition> positions: regions.values()) {
					LinkedPositionGroup group = new LinkedPositionGroup();
					for (LinkedPosition position : positions) {
						group.addPosition(position);
					}
					model.addGroup(group);
				}
				model.forceInstall();

				LinkedModeUI ui = new EditorLinkedModeUI(model, viewer);
				// ui.setSimpleMode(true);
				// ui.setExitPolicy(new ExitPolicy(closingCharacter, document));
				// ui.setExitPosition(getTextViewer(), exit, 0, Integer.MAX_VALUE);
				ui.setCyclingMode(LinkedModeUI.CYCLE_NEVER);
				ui.enter();
			} else {
				selection = new Region(insertionOffset + textEdit.getNewText().length(), 0);
			}

			LanguageServiceAccessor.resolveServerDefinition(languageServer).map(definition -> definition.id)
					.ifPresent(id -> {
						Command command = item.getCommand();
						if (command == null) {
							return;
						}
						CommandExecutor.executeCommand(command, document, id);
					});
		} catch (BadLocationException ex) {
			LanguageServerPlugin.logError(ex);
		}
	}

	private int computeNewOffset(List<TextEdit> additionalTextEdits, int insertionOffset, IDocument doc) {
		if (additionalTextEdits != null && !additionalTextEdits.isEmpty()) {
			int adjustment = 0;
			for (TextEdit edit : additionalTextEdits) {
				try {
					Range rng = edit.getRange();
					int start = LSPEclipseUtils.toOffset(rng.getStart(), doc);
					if (start <= insertionOffset) {
						int end = LSPEclipseUtils.toOffset(rng.getEnd(), doc);
						int orgLen = end - start;
						int newLeng = edit.getNewText().length();
						int editChange = newLeng - orgLen;
						adjustment += editChange;
					}
				} catch (BadLocationException e) {
					LanguageServerPlugin.logError(e);
				}
			}
			return insertionOffset + adjustment;
		}
		return insertionOffset;
	}

	private String getVariableValue(String variableName) {
		switch (variableName) {
		case TM_FILENAME_BASE:
			IPath pathBase = LSPEclipseUtils.toPath(document).removeFileExtension();
			String fileName = pathBase.lastSegment();
			return fileName != null ? fileName : ""; //$NON-NLS-1$
		case TM_FILENAME:
			return LSPEclipseUtils.toPath(document).lastSegment();
		case TM_FILEPATH:
			return getAbsoluteLocation(LSPEclipseUtils.toPath(document));
		case TM_DIRECTORY:
			IPath dirPath = LSPEclipseUtils.toPath(document).removeLastSegments(1);
			return getAbsoluteLocation(dirPath);
		case TM_LINE_INDEX:
			int lineIndex = getTextEditRange().getStart().getLine();
			return Integer.toString(lineIndex);
		case TM_LINE_NUMBER:
			int lineNumber = getTextEditRange().getStart().getLine();
			return Integer.toString(lineNumber + 1);
		case TM_CURRENT_LINE:
			int currentLineIndex = getTextEditRange().getStart().getLine();
			try {
				IRegion lineInformation = document.getLineInformation(currentLineIndex);
				String line = document.get(lineInformation.getOffset(), lineInformation.getLength());
				return line;
			} catch (BadLocationException e) {
				LanguageServerPlugin.logWarning(e.getMessage(), e);
				return ""; //$NON-NLS-1$
			}
		case TM_SELECTED_TEXT:
			Range selectedRange = getTextEditRange();
			try {
				int startOffset = LSPEclipseUtils.toOffset(selectedRange.getStart(), document);
				int endOffset = LSPEclipseUtils.toOffset(selectedRange.getEnd(), document);
				String selectedText = document.get(startOffset, endOffset - startOffset);
				return selectedText;
			} catch (BadLocationException e) {
				LanguageServerPlugin.logWarning(e.getMessage(), e);
				return ""; //$NON-NLS-1$
			}
		case TM_CURRENT_WORD:
			return ""; //$NON-NLS-1$
		default:
			return null;
		}
	}

	private Range getTextEditRange() {
		if (item.getTextEdit().isLeft()) {
			return item.getTextEdit().getLeft().getRange();
		} else {
			// here providing insert range, currently do not know if insert or replace is requested
			return item.getTextEdit().getRight().getInsert();
		}
	}

	/**
	 * Returns the absolute OS specific path for the given {@code path}.
	 * @param path to be turned into an OS specific path
	 * @return OS specific absolute path representation of argument {@code path}
	 */
	private String getAbsoluteLocation(IPath path) {
		IResource res = ResourcesPlugin.getWorkspace().getRoot().findMember(path);
		if(res != null) {
			// On projects getRawLocation() returns null if it is located
			// in the default location; getLocation(), however, returns the
			// absolute path in the local file system
			IPath location = res.getType() == IResource.PROJECT ? res.getLocation() : res.getRawLocation();
			if(location != null) {
				return location.toOSString();
			}
		}
		return path.toFile().getAbsolutePath();
	}

	protected String getInsertText() {
		String insertText = this.item.getInsertText();
		Either<TextEdit, InsertReplaceEdit> eitherTextEdit = this.item.getTextEdit();
		if (eitherTextEdit != null) {
			if(eitherTextEdit.isLeft()) {
				insertText = eitherTextEdit.getLeft().getNewText();
			} else {
				insertText = eitherTextEdit.getRight().getNewText();
			}
		}
		if (insertText == null) {
			insertText = this.item.getLabel();
		}
		return insertText;
	}

	@Override
	public Point getSelection(IDocument document) {
		if (this.firstPosition != null) {
			return new Point(this.firstPosition.getOffset(), this.firstPosition.getLength());
		}
		if (selection == null) {
			return null;
		}
		return new Point(selection.getOffset(), selection.getLength());
	}

	@Override
	public String getAdditionalProposalInfo() {
		return this.getAdditionalProposalInfo(new NullProgressMonitor());
	}

	@Override
	public Image getImage() {
		return LSPImages.imageFromCompletionItem(this.item);
	}

	@Override
	public IContextInformation getContextInformation() {
		return this;
	}

	@Override
	public String getContextDisplayString() {
		return getAdditionalProposalInfo();
	}

	@Override
	public String getInformationDisplayString() {
		return getAdditionalProposalInfo();
	}

	public String getSortText() {
		if (item.getSortText() != null && !item.getSortText().isEmpty()) {
			return item.getSortText();
		}
		return item.getLabel();
	}

	public String getFilterString() {
		if (item.getFilterText() != null && !item.getFilterText().isEmpty()) {
			return item.getFilterText();
		}
		return item.getLabel();
	}
}
