/*=============================================================================#
 # Copyright (c) 2005, 2019 IBM Corporation 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:
 #     IBM Corporation - org.eclipse.jdt: initial API and implementation
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.ltk.ui.sourceediting.assist;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

import com.ibm.icu.text.Collator;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jface.text.AbstractDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.contentassist.ContentAssistEvent;
import org.eclipse.jface.text.contentassist.ICompletionListener;
import org.eclipse.jface.text.contentassist.ICompletionListenerExtension;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.IContentAssistProcessor;
import org.eclipse.jface.text.contentassist.IContextInformation;
import org.eclipse.jface.text.contentassist.IContextInformationValidator;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.osgi.util.NLS;
import org.eclipse.ui.statushandlers.StatusManager;

import org.eclipse.statet.jcommons.collections.CopyOnWriteIdentityListSet;
import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.lang.NonNull;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;

import org.eclipse.statet.ecommons.ui.SharedMessages;
import org.eclipse.statet.ecommons.ui.util.UIAccess;

import org.eclipse.statet.internal.ltk.ui.EditingMessages;
import org.eclipse.statet.ltk.core.LTK;
import org.eclipse.statet.ltk.ui.sourceediting.ISourceEditor;


/**
 * A content assist processor that aggregates the proposals of the {@link ContentAssistComputer}s
 * contributed via the extension point <code>org.eclipse.statet.ltk.advancedContentAssist</code>.
 * <p>
 * Subclasses may extend:
 * <ul>
 *   <li><code>createContext</code> to provide the context object passed to the computers</li>
 *   <li><code>createProgressMonitor</code> to change the way progress is reported</li>
 *   <li><code>filterAndSort</code> to add sorting and filtering</li>
 *   <li><code>getContextInformationValidator</code> to add context validation (needed if any
 *       contexts are provided)</li>
 *   <li><code>getErrorMessage</code> to change error reporting</li>
 * </ul></p>
 */
@NonNullByDefault
public class ContentAssistProcessor extends ContentAssist.Processor implements IContentAssistProcessor {
	
	
	private static final boolean DEBUG_LOG= Boolean.parseBoolean(
			Platform.getDebugOption("org.eclipse.statet.ltk/debug/ContentAssist/log") ); //$NON-NLS-1$
	
	private static final Collator NAME_COLLATOR= Collator.getInstance();
	
	static final Comparator<AssistProposal> PROPOSAL_COMPARATOR= new Comparator<AssistProposal>() {
		
		@Override
		public int compare(final AssistProposal proposal1, final AssistProposal proposal2) {
			final int diff= proposal2.getRelevance() - proposal1.getRelevance();
			if (diff != 0) {
				return diff; // reverse
			}
			return NAME_COLLATOR.compare(proposal1.getSortingString(), proposal2.getSortingString());
		}
		
	};
	
	private static final long INFO_ITER_SPAN= 3L * 1000000000L;
	
	
	/**
	 * The completion listener class for this processor.
	 */
	private final class CompletionListener implements ICompletionListener, ICompletionListenerExtension {
		
		@Override
		public void assistSessionStarted(final ContentAssistEvent event) {
			if (event.processor == ContentAssistProcessor.this) {
				startCompletionSession();
			}
		}
		
		@Override
		public void assistSessionRestarted(final ContentAssistEvent event) {
			if (isInCompletionProposalSession()) {
				if (event.processor == ContentAssistProcessor.this) {
					restartCompletionSession();
				}
				else {
					endCompletionSession();
				}
			}
		}
		
		@Override
		public void assistSessionEnded(final ContentAssistEvent event) {
			if (isInCompletionProposalSession()) {
				endCompletionSession();
			}
		}
		
		@Override
		public void selectionChanged(final @Nullable ICompletionProposal proposal, final boolean smartToggle) {
		}
		
	}
	
	
	/**
	 * The completion proposal registry.
	 */
	private final ContentAssistComputerRegistry computerRegistry;
	
	private final ISourceEditor editor;
	
	private char[] completionProposalsAutoActivationCharacters;
	private char[] contextInformationAutoActivationCharacters;
	
	private boolean isCompletionProposalSession;
	private int sessionCounter;
	
	/* cycling stuff */
	private int iterationPos= -1;
	private boolean noIteration;
	private final CopyOnWriteIdentityListSet<ContentAssistCategory> expliciteCategories= new CopyOnWriteIdentityListSet<>();
	private List<ContentAssistCategory> availableCategories;
	private List<List<ContentAssistCategory>> categoryIteration;
	
	private @Nullable AssistInvocationContext completionProposalContext;
	
	private @Nullable IContextInformationValidator contextInformationValidator;
	
	/* for detection if information mode is valid */
	private long informationModeTimestamp;
	private long informationModeModificationStamp;
	private int informationModeOffset;
	
	private ICompletionProposal @Nullable [] reloadCompletionProposals;
	
	
	public ContentAssistProcessor(final ContentAssist assistant, final String contentType,
			final ContentAssistComputerRegistry registry, final ISourceEditor editor) {
		super(assistant, contentType);
		assert(registry != null);
		assert(editor != null);
		
		this.computerRegistry= registry;
		this.editor= editor;
		
		getAssistant().enableColoredLabels(true);
		getAssistant().addCompletionListener(new CompletionListener());
	}
	
	
	protected ISourceEditor getEditor() {
		return this.editor;
	}
	
	
	protected final boolean isInCompletionProposalSession() {
		return this.isCompletionProposalSession;
	}
	
	protected final int getSessionCounter() {
		return this.sessionCounter;
	}
	
	public void addCategory(final ContentAssistCategory category) {
		this.expliciteCategories.add(category);
	}
	
	@Override
	protected ICompletionProposal @Nullable [] doComputeCompletionProposals(
			final ITextViewer viewer, final int offset) {
		if (!isInCompletionProposalSession()) {
			startCompletionSession();
		}
		
		clearState();
		
		if (this.reloadCompletionProposals != null) {
			return this.reloadCompletionProposals;
		}
		
		return computeCompletionProposals(offset);
	}
	
	private final ICompletionProposal @Nullable [] computeCompletionProposals(final int offset) {
		final ContentAssist assistant= getAssistant();
		
		final long startTime= System.nanoTime();
		
		final SubMonitor m= SubMonitor.convert(createProgressMonitor());
		m.beginTask(EditingMessages.ContentAssistProcessor_ComputingProposals_task, 3 + 10 + 1);
		try {
			final AssistInvocationContext context= getCompletionProposalContext(offset, m.newChild(3));
			
			final long setup= (DEBUG_LOG) ? System.nanoTime() : 0;
			
			final long modificationStamp= ((AbstractDocument) context.getSourceViewer().getDocument()).getModificationStamp();
			final int mode;
			if (assistant.isCompletionProposalSpecificSession()) {
				mode= ContentAssistComputer.SPECIFIC_MODE;
			}
			else if (!assistant.isProposalPopupActive1()
					&& (   startTime - this.informationModeTimestamp > INFO_ITER_SPAN
						|| offset != this.informationModeOffset
						|| !assistant.isContextInfoPopupActive1()
						|| modificationStamp != this.informationModeModificationStamp)
					&& forceContextInformation(context)) {
				assistant.setRepeatedInvocationMode(true);
				assistant.setShowEmptyList(true);
				assistant.enableAutoInsertTemporarily();
				
				assistant.setStatusLineVisible(true);
				assistant.setStatusMessage(EditingMessages.ContentAssistProcessor_ContextSelection_label);
				
				return computeContextInformationProposals(context, modificationStamp, m.newChild(10) );
			}
			else {
				iterate();
				
				mode= (this.iterationPos == 0) ? ContentAssistComputer.COMBINED_MODE : ContentAssistComputer.SPECIFIC_MODE;
				
				assistant.enableAutoInsertSetting();
			}
			
			final List<ContentAssistCategory> categories= getCurrentCategories();
			
			m.subTask(EditingMessages.ContentAssistProcessor_ComputingProposals_Collecting_task);
			
			final AssistProposalCollector proposals= createProposalCollector();
			collectCompletionProposals(context, mode, categories, proposals, m.newChild(10));
			final long collect= (DEBUG_LOG) ? System.nanoTime() : 0;
			
			m.subTask(EditingMessages.ContentAssistProcessor_ComputingProposals_Sorting_task);
			final AssistProposal[] result= filterAndSortCompletionProposals(proposals,
					context, m.newChild(1) );
			final long filter= (DEBUG_LOG) ? System.nanoTime() : 0;
			
			if (DEBUG_LOG) {
				final StringBuilder sb= new StringBuilder("Code Assist Stats"); //$NON-NLS-1$
				sb.append(" (").append(result.length).append(" proposals)"); //$NON-NLS-1$ //$NON-NLS-2$
				sb.append("\n\t" + "setup=   ").append((setup - startTime)); //$NON-NLS-1$ //$NON-NLS-2$
				sb.append("\n\t" + "collect= ").append((collect - setup)); //$NON-NLS-1$ //$NON-NLS-2$
				sb.append("\n\t" + "sort=    ").append((filter - collect)); //$NON-NLS-1$ //$NON-NLS-2$
				System.out.println(sb);
			}
			
			return result;
		}
		finally {
			m.done();
		}
	}
	
	private void startCompletionSession() {
		this.isCompletionProposalSession= true;
		this.sessionCounter++;
		
		final ContentAssist assistant= getAssistant();
		
		this.availableCategories= assistant.isCompletionProposalSpecificSession() ?
				this.computerRegistry.getCategory(assistant.getSpecificMode()) :
				this.computerRegistry.getCategories();
		this.categoryIteration= createCategoryIteration();
		
		notifySessionStarted();
		
		this.iterationPos= -1;
		
		if (this.categoryIteration.size() == 1) {
			assistant.setRepeatedInvocationMode(false);
			assistant.setShowEmptyList(false);
		}
		else {
			assistant.setRepeatedInvocationMode(true);
			assistant.setShowEmptyList(true);
			
			assistant.setStatusLineVisible(true);
			assistant.setStatusMessage(createIterationMessage(0));
		}
	}
	
	private void restartCompletionSession() {
		assert(this.isCompletionProposalSession);
		
		if (this.iterationPos >= 0) {
			this.iterationPos--;
		}
		
		this.completionProposalContext= null;
	}
	
	private void endCompletionSession() {
		assert(this.isCompletionProposalSession);
		
		this.isCompletionProposalSession= false;
		
		final ContentAssist assistant= getAssistant();
		
		notifySessionEnded();
		
		this.availableCategories= null;
		this.categoryIteration= null;
		this.iterationPos= -1;
		
		assistant.setRepeatedInvocationTrigger(null);
		assistant.setRepeatedInvocationMode(false);
		assistant.setShowEmptyList(false);
		assistant.enableAutoInsertSetting();
		assistant.setStatusLineVisible(false);
		
		this.completionProposalContext= null;
	}
	
	private void clearState() {
//		this.status= null;
	}
	
	/**
	 * Collects the proposals.
	 * 
	 * @param context the code assist invocation context
	 * @param mode
	 * @param categories list of categories to use
	 * @param proposals collector for the proposals
	 * @param monitor the progress monitor
	 * @return the list of proposals
	 */
	private boolean collectCompletionProposals(
			final AssistInvocationContext context, final int mode,
			final List<ContentAssistCategory> categories,
			final AssistProposalCollector proposals, final SubMonitor m) {
		m.setWorkRemaining(categories.size());
		
		for (final ContentAssistCategory category : categories) {
			final List<ContentAssistComputer> computers= category.getComputers(getContentType());
			final SubMonitor m1= m.newChild(1);
			for (final ContentAssistComputer computer : computers) {
				try {
					computer.computeCompletionProposals(context, mode, proposals, m1);
				}
				catch (final Exception e) {
					StatusManager.getManager().handle(new Status(IStatus.ERROR, LTK.BUNDLE_ID,
							"An error occurred when computing content assistant completion proposals.",
							e ));
				}
			}
		}
		return true;
	}
	
	
	@Override
	protected IContextInformation @Nullable [] doComputeContextInformation(
			final ITextViewer viewer, final int offset) {
		clearState();
		
		final SubMonitor m= SubMonitor.convert(createProgressMonitor(),
				EditingMessages.ContentAssistProcessor_ComputingContexts_task, 3 + 10 + 1);
		
		try {
			if (!this.isCompletionProposalSession) {
				this.sessionCounter++;
				this.availableCategories= this.computerRegistry.getCategories();
				
				notifySessionStarted();
			}
			
			final AssistInvocationContext context= getContextInformationContext(offset, m.newChild(3));
			
			final long modificationStamp= (!getAssistant().isContextInformationAutoRequest()) ?
					((AbstractDocument) context.getSourceViewer().getDocument()).getModificationStamp() :
					0;
			final AssistProposal[] proposals= computeContextInformationProposals(
					context, modificationStamp, m.newChild(10) );
			
			return (proposals != null) ? toInformationProposals(proposals, context) : null;
		}
		finally {
			if (!this.isCompletionProposalSession) {
				notifySessionEnded();
				this.availableCategories= null;
			}
			
			m.done();
		}
	}
	
	private AssistProposal @Nullable [] computeContextInformationProposals(
			final AssistInvocationContext context,
			final long modificationStamp,
			final SubMonitor m) {
		m.setWorkRemaining(10 + 1);
		m.subTask(EditingMessages.ContentAssistProcessor_ComputingContexts_Collecting_task);
		
		final ContentAssist assistant= getAssistant();
		
		final List<ContentAssistCategory> defaultGroup= new ArrayList<>();
		final List<ContentAssistCategory> otherGroup= new ArrayList<>();
		for (final ContentAssistCategory category : this.availableCategories) {
			if (category.isEnabledInDefault()) {
				defaultGroup.add(category);
			}
			else if (category.isEnabledInCircling()) {
				otherGroup.add(category);
			}
		}
		
		boolean ok;
		final AssistProposalCollector proposals= createProposalCollector();
		if (modificationStamp == 0) {
			ok= false;
			if (collectInformationProposals(context, defaultGroup, true, proposals,
					m.newChild(5) )) {
				if (proposals.getCount() == 1
						|| (collectInformationProposals(context, otherGroup, true, proposals,
									m.newChild(5) )
								&& proposals.getCount() == 1) ) {
					ok= true;
				}
			}
		}
		else {
			ok= true;
			collectInformationProposals(context, defaultGroup, false, proposals,
					m.newChild(5) );
			if (proposals.getCount() == 0) {
				collectInformationProposals(context, otherGroup, false, proposals,
						m.newChild(5) );
			}
		}
		
		if (!ok) {
			return null;
		}
		
		m.setWorkRemaining(1);
		m.subTask(EditingMessages.ContentAssistProcessor_ComputingContexts_Sorting_task);
		final AssistProposal[] result= filterAndSortCompletionProposals(proposals,
				context, m.newChild(1) );
		
		if (modificationStamp != 0) {
			this.informationModeOffset= context.getInvocationOffset();
			this.informationModeTimestamp= System.nanoTime();
			this.informationModeModificationStamp= modificationStamp;
		}
		
		return result;
	}
	
	/**
	 * @return <code>false</code> if cancelled
	 */
	private boolean collectInformationProposals(final AssistInvocationContext context,
			final List<ContentAssistCategory> categories, final boolean single,
			final AssistProposalCollector proposals, final SubMonitor m) {
		m.setWorkRemaining(categories.size());
		
		for (final ContentAssistCategory category : categories) {
			final List<ContentAssistComputer> computers= category.getComputers(getContentType());
			final SubMonitor m1= m.newChild(1);
			for (final ContentAssistComputer computer : computers) {
				computer.onSessionStarted(context.getEditor(), getAssistant());
				try {
					computer.computeInformationProposals(context, proposals, m1);
				}
				catch (final Exception e) {
					StatusManager.getManager().handle(new Status(IStatus.ERROR, LTK.BUNDLE_ID,
							"An error occurred when computing content assistant context information.",
							e ));
				}
				finally {
					computer.onSessionEnded();
				}
				if ((single && proposals.getCount() > 1)) {
					return false;
				}
			}
		}
		return true;
	}
	
	
	protected AssistProposalCollector createProposalCollector() {
		return new AssistProposalCollector();
	}
	
	/**
	 * Filters and sorts the proposals. The passed list may be modified
	 * and returned, or a new list may be created and returned.
	 * 
	 * @param proposals the list of collected proposals
	 * @param context 
	 * @param monitor a progress monitor
	 * @return the list of filtered and sorted proposals, ready for display
	 */
	protected AssistProposal[] filterAndSortCompletionProposals(
			final AssistProposalCollector proposals,
			final AssistInvocationContext context, final SubMonitor m) {
		final AssistProposal[] array= proposals.toArray();
		if (array.length > 1) {
			Arrays.sort(array, PROPOSAL_COMPARATOR);
		}
		
		return array;
	}
	
	protected AssistInformationProposal @Nullable [] toInformationProposals(
			final AssistProposal[] proposals, final AssistInvocationContext context) {
		final AssistInformationProposal[] infoProposals=
				new @NonNull AssistInformationProposal[proposals.length];
		for (int i= 0; i < proposals.length; i++) {
			final AssistProposal proposal= proposals[i];
			infoProposals[i]= (proposal instanceof AssistInformationProposal) ?
					(AssistInformationProposal) proposal :
					new AssistCompletionInformationProposalWrapper(proposal, context);
		}
		return infoProposals;
	}
	
	
	/**
	 * Sets this processor's set of characters triggering the activation of the
	 * completion proposal computation.
	 *
	 * @param activationSet the activation set
	 */
	public final void setCompletionProposalAutoActivationCharacters(final char[] activationSet) {
		this.completionProposalsAutoActivationCharacters= activationSet;
	}
	
	@Override
	public final char[] getCompletionProposalAutoActivationCharacters() {
		return this.completionProposalsAutoActivationCharacters;
	}
	
	/**
	 * Sets this processor's set of characters triggering the activation of the
	 * completion proposal computation.
	 *
	 * @param activationSet the activation set
	 */
	public final void setContextInformationAutoActivationCharacters(final char[] activationSet) {
		this.contextInformationAutoActivationCharacters= activationSet;
	}
	
	@Override
	public char[] getContextInformationAutoActivationCharacters() {
		return this.contextInformationAutoActivationCharacters;
	}
	
	
	@Override
	public @Nullable String getErrorMessage() {
//		final IStatus status= this.status;
//		return (status != null && status.getSeverity() == IStatus.ERROR) ? status.getMessage() : null;
		return null;
	}
	
	/**
	 * {@inheritDoc}
	 * 
	 * This implementation returns the validator created by
	 * {@link #createContextInformationValidator()}
	 */
	@Override
	public final @Nullable IContextInformationValidator getContextInformationValidator() {
		IContextInformationValidator contextInformationValidator= this.contextInformationValidator;
		if (contextInformationValidator == null) {
			contextInformationValidator= createContextInformationValidator();
			this.contextInformationValidator= contextInformationValidator;
		}
		return contextInformationValidator;
	}
	
	protected @Nullable IContextInformationValidator createContextInformationValidator() {
		return null;
	}
	
	/**
	 * Creates a progress monitor.
	 * <p>
	 * The default implementation creates a
	 * <code>NullProgressMonitor</code>.
	 * </p>
	 * 
	 * @return a progress monitor
	 */
	protected IProgressMonitor createProgressMonitor() {
		return new NullProgressMonitor();
	}
	
	private AssistInvocationContext getCompletionProposalContext(final int offset,
			final IProgressMonitor monitor) {
		AssistInvocationContext context= this.completionProposalContext;
		if (context == null || !context.reuse(getEditor(), offset)) {
			context= createCompletionProposalContext(offset, monitor);
			this.completionProposalContext= context;
		}
		context.session= this.sessionCounter;
		return context;
	}
	
	/**
	 * Creates the context that is passed to the completion proposal
	 * computers.
	 * 
	 * @param offset the content assist offset
	 * @return the context to be passed to the computers
	 */
	protected AssistInvocationContext createCompletionProposalContext(final int offset,
			final IProgressMonitor monitor) {
		return new AssistInvocationContext(getEditor(), offset, getContentType(), 0, monitor);
	}
	
	private AssistInvocationContext getContextInformationContext(final int offset,
			final SubMonitor m) {
		AssistInvocationContext context= this.completionProposalContext;
		if (context == null || !context.reuse(getEditor(), offset)) {
			context= createContextInformationContext(offset, m);
		}
		return context;
	}
	
	/**
	 * Creates the context that is passed to the completion proposal
	 * computers.
	 * 
	 * @param offset the content assist offset
	 * @return the context to be passed to the computers
	 */
	protected AssistInvocationContext createContextInformationContext(final int offset,
			final IProgressMonitor monitor) {
		return new AssistInvocationContext(getEditor(), offset, getContentType(), 0, monitor);
	}
	
	protected boolean forceContextInformation(final AssistInvocationContext context) {
		return false;
	}
	
	private void iterate() {
		if (this.categoryIteration == null) {
			this.noIteration= false;
			return;
		}
		if (this.noIteration) {
			if (this.iterationPos < 0) {
				this.iterationPos= 0;
			}
			this.noIteration= false;
			return;
		}
		
		this.iterationPos++;
		if (this.iterationPos >= this.categoryIteration.size()) {
			this.iterationPos= 0;
		}
	}
	
	private List<ContentAssistCategory> getCurrentCategories() {
		if (this.categoryIteration == null) {
			return this.availableCategories;
		}
		final int iterationPos= this.iterationPos % this.categoryIteration.size();
		
		final ContentAssist assistant= getAssistant();
		assistant.setStatusMessage(createIterationMessage(iterationPos));
		assistant.setEmptyMessage(createEmptyMessage(iterationPos));
		
		return this.categoryIteration.get(iterationPos);
	}
	
	private List<List<ContentAssistCategory>> createCategoryIteration() {
		final List<List<ContentAssistCategory>> sequence= new ArrayList<>(this.availableCategories.size());
		sequence.add(createDefaultCategories());
		for (final ContentAssistCategory category : createSeparateCategories()) {
			sequence.add(ImCollections.newList(category));
		}
		return sequence;
	}
	
	private List<ContentAssistCategory> createDefaultCategories() {
		final List<ContentAssistCategory> included= new ArrayList<>(this.availableCategories.size());
		for (final ContentAssistCategory category : this.availableCategories) {
			if (category.isEnabledInDefault() && category.hasComputers(getContentType())) {
				included.add(category);
			}
		}
		for (final ContentAssistCategory category : this.expliciteCategories.toList()) {
			if (category.isEnabledInDefault() && category.hasComputers(getContentType())) {
				included.add(category);
			}
		}
		return included;
	}
	
	private List<ContentAssistCategory> createSeparateCategories() {
		final ArrayList<ContentAssistCategory> sorted= new ArrayList<>(this.availableCategories.size());
		for (final ContentAssistCategory category : this.availableCategories) {
			if (category.isEnabledInCircling() && category.hasComputers(getContentType())) {
				sorted.add(category);
			}
		}
		return sorted;
	}
	
	private void notifySessionStarted() {
		for (final ContentAssistCategory category : this.availableCategories) {
			final List<ContentAssistComputer> computers= category.getComputers(getContentType());
			for (final ContentAssistComputer computer : computers) {
				computer.onSessionStarted(ContentAssistProcessor.this.editor, getAssistant());
			}
		}
	}
	
	private void notifySessionEnded() {
		if (this.availableCategories == null) {
			return;
		}
		for (final ContentAssistCategory category : this.availableCategories) {
			final List<ContentAssistComputer> computers= category.getComputers(getContentType());
			for (final ContentAssistComputer computer : computers) {
				try {
					computer.onSessionEnded();
				}
				catch (final Exception e) {
					StatusManager.getManager().handle(new Status(IStatus.ERROR, LTK.BUNDLE_ID, 0,
							"Error by contributed content assist computer.", e ));
				}
			}
		}
	}
	
	
	protected String createEmptyMessage(final int iterationPosition) {
		return NLS.bind(EditingMessages.ContentAssistProcessor_Empty_message, new String[] { 
				getCategoryName(iterationPosition)});
	}
	
	protected String createIterationMessage(final int iterationPosition) {
//		if (iterationPosition >= 0 && iterationPosition == iterationPosition % this.categoryIteration.size()) {
//			return getCategoryName(iterationPosition);
//		}
		final StringBuilder sb= new StringBuilder(
				getCategoryName(iterationPosition) );
		if (this.categoryIteration.size() > 0) {
			sb.append("\u2004\u2004"); //$NON-NLS-1$
			sb.append(NLS.bind(SharedMessages.DoToShow_message,
					getAssistant().getCompletionProposalIterationGesture(),
					getCategoryName(iterationPosition + 1) ));
		}
		return sb.toString();
	}
	
	protected String getCategoryName(final int repetition) {
		if (repetition < 0) {
			return EditingMessages.ContentAssistProcessor_ContextSelection_label;
		}
		final int iterationPosition= repetition % this.categoryIteration.size();
		if (iterationPosition == 0) {
			return EditingMessages.ContentAssistProcessor_DefaultProposalCategory;
		}
		return this.categoryIteration.get(iterationPosition).get(0).getDisplayName();
	}
	
	
	protected void reloadPossibleCompletions(final AssistInvocationContext context) {
		if (isInCompletionProposalSession()
				&& context.session == getSessionCounter()) {
			UIAccess.getDisplay().asyncExec(new Runnable() {
				@Override
				public void run() {
					final SourceViewer viewer= context.getSourceViewer();
					if (isInCompletionProposalSession()
							&& context.session == getSessionCounter()
							&& UIAccess.isOkToUse(viewer)
							&& viewer.getTextWidget().isFocusControl()
							&& context.isInitialState()
							&& getAssistant().getCompletionProposalSelectionCounter() <= 1 ) {
						ContentAssistProcessor.this.noIteration= true;
						try {
							ContentAssistProcessor.this.reloadCompletionProposals=
									computeCompletionProposals(context.getInvocationOffset());
							if (ContentAssistProcessor.this.reloadCompletionProposals != null
									&& ContentAssistProcessor.this.reloadCompletionProposals.length > 0 ) {
								getAssistant().reloadPossibleCompletions();
							}
						}
						finally {
							ContentAssistProcessor.this.noIteration= false;
							ContentAssistProcessor.this.reloadCompletionProposals= null;
						}
					}
				}
			});
		}
	}
	
}
