/*******************************************************************************
 * Copyright (c) 2016 Red Hat Inc. 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:
 *     Mickael Istria (Red Hat Inc.) - [251156] async content assist
 *******************************************************************************/
package org.eclipse.jface.text.contentassist;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.function.Consumer;

import org.eclipse.osgi.util.NLS;

import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;

import org.eclipse.jface.contentassist.IContentAssistSubjectControl;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.TextUtilities;

/**
 * This class is used to present proposals asynchronously to the user. If additional information
 * exists for a proposal, then selecting that proposal will result in the information being
 * displayed in a secondary window.
 *
 * @since 3.12
 */
class AsyncCompletionProposalPopup extends CompletionProposalPopup {

	private static final int MAX_WAIT_IN_MS= 50; // TODO make it a preference
	private List<CompletableFuture<List<ICompletionProposal>>> fFutures;

	private static final class ComputingProposal implements ICompletionProposal, ICompletionProposalExtension {

		private final int fOffset;
		private final int fSize;
		private int fRemaining;

		public ComputingProposal(int offset, int size) {
			fSize= size;
			fRemaining = size;
			fOffset = offset;
		}

		@Override
		public void apply(IDocument document) {
			// Nothing to do, maybe show some progress report?
		}

		@Override
		public Point getSelection(IDocument document) {
			return new Point(fOffset, 0);
		}

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

		@Override
		public Image getImage() {
			return null;
		}

		@Override
		public String getDisplayString() {
			return NLS.bind(JFaceTextMessages.getString("AsyncCompletionProposalPopup.computing"), Long.valueOf(Math.round(100. * (fSize - fRemaining)/fSize))); //$NON-NLS-1$
		}

		@Override
		public String getAdditionalProposalInfo() {
			 return NLS.bind(JFaceTextMessages.getString("AsyncCompletionProposalPopup.computingDetails"), new Object[] { //$NON-NLS-1$;
				Integer.valueOf(fSize),
				Integer.valueOf(fSize - fRemaining),
				Integer.valueOf(fRemaining) });
		}

		@Override
		public void apply(IDocument document, char trigger, int offset) {
			// Nothing to do
		}

		@Override
		public boolean isValidFor(IDocument document, int offset) {
			return false;
		}

		@Override
		public char[] getTriggerCharacters() {
			return null;
		}

		@Override
		public int getContextInformationPosition() {
			return -1;
		}

		public void setRemaining(int size) {
			this.fRemaining = size;
		}
	}

	public AsyncCompletionProposalPopup(ContentAssistant contentAssistant, IContentAssistSubjectControl contentAssistSubjectControl, AdditionalInfoController infoController) {
		super(contentAssistant, contentAssistSubjectControl, infoController);
	}

	public AsyncCompletionProposalPopup(ContentAssistant contentAssistant, ITextViewer viewer, AdditionalInfoController infoController) {
		super(contentAssistant, viewer, infoController);
	}

	/**
	 * This methods differs from its super as it will show the list of proposals that
	 * gets augmented as the {@link IContentAssistProcessor#computeCompletionProposals(ITextViewer, int)}
	 * complete. All computations operation happen in a non-UI Thread so they're not blocking UI.
	 */
	@Override
	public String showProposals(boolean autoActivated) {
		if (fKeyListener == null)
			fKeyListener= new ProposalSelectionListener();

		final Control control= fContentAssistSubjectControlAdapter.getControl();

		if (!Helper.okToUse(fProposalShell) && control != null && !control.isDisposed()) {
			// add the listener before computing the proposals so we don't move the caret
			// when the user types fast.
			fContentAssistSubjectControlAdapter.addKeyListener(fKeyListener);

			fInvocationOffset= fContentAssistSubjectControlAdapter.getSelectedRange().x;
			fFilterOffset= fInvocationOffset;
			fLastCompletionOffset= fFilterOffset;
			// start invocation of processors as Futures, and make them populate the proposals upon completion
			fFutures= buildCompletionFuturesOrJobs(fInvocationOffset);
			runFutures(fInvocationOffset, null, true, autoActivated, true);
		} else {
			fLastCompletionOffset= fFilterOffset;
			handleRepeatedInvocation();
		}

		return getErrorMessage();
	}

	@Override
	void handleRepeatedInvocation() {
		cancelFutures();
		fFutures= buildCompletionFuturesOrJobs(fInvocationOffset);
		runFutures(fInvocationOffset, null, false, false, false);
	}

	private List<ICompletionProposal> runFutures(int offset, Consumer<List<ICompletionProposal>> callback, boolean createSelector, boolean autoActivated, boolean autoInsert) {
		List<ICompletionProposal> computedProposals= Collections.synchronizedList(new ArrayList<>());
		List<CompletableFuture<Void>> populateFutures= new ArrayList<>(fFutures.size());
		for (CompletableFuture<List<ICompletionProposal>> future : fFutures) {
			populateFutures.add(future.thenAccept(proposals -> computedProposals.addAll(proposals)));
		}

		long requestBeginningTimestamp= System.currentTimeMillis();
		long stillRemainingThreeshold= MAX_WAIT_IN_MS;
		for (CompletableFuture<?> future : populateFutures) {
			try {
				future.get(stillRemainingThreeshold, TimeUnit.MILLISECONDS);
			} catch (TimeoutException | ExecutionException | InterruptedException ex) {
				// future failed or took more time than we want to wait
			}
			stillRemainingThreeshold= MAX_WAIT_IN_MS - (System.currentTimeMillis() - requestBeginningTimestamp);
			if (stillRemainingThreeshold < 0) {
				// we already spent too much time (more than MAX_WAIT_IN_MS), stop waiting.
				break;
			}
		}
		fComputedProposals= computedProposals;
		if (stillRemainingThreeshold > 0) { // everything ready in time, go synchronous
			int count= computedProposals.size();
			if (count == 0 && hideWhenNoProposals(autoActivated))
				return computedProposals;

			if (autoInsert && count == 1 && !autoActivated && canAutoInsert(computedProposals.get(0))) {
				insertProposal(computedProposals.get(0), (char) 0, 0, offset);
				hide();
			} else {
				if (createSelector) {
					createProposalSelector();
				}
				if (callback != null) {
					callback.accept(computedProposals);
				} else {
					setProposals(computedProposals, false);
					displayProposals();
				}
			}
		} else { // processors took too much time, go asynchronous
			if (createSelector) {
				createProposalSelector();
			}
			ComputingProposal computingProposal= new ComputingProposal(offset, fFutures.size());
			computedProposals.add(0, computingProposal);
			setProposals(fComputedProposals, false);
			Set<CompletableFuture<Void>> remaining= Collections.synchronizedSet(new HashSet<>(populateFutures));
			for (CompletableFuture<Void> populateFuture : populateFutures) {
				populateFuture.thenRun(() -> {
					remaining.removeIf(CompletableFuture::isDone);
					computingProposal.setRemaining(remaining.size());
					if (remaining.isEmpty()) {
						computedProposals.remove(computingProposal);
					}
					List<ICompletionProposal> newProposals= new ArrayList<>(computedProposals);
					fComputedProposals= newProposals;
					Display.getDefault().asyncExec(() -> {
						if (autoInsert && !autoActivated && remaining.isEmpty() && newProposals.size() == 1 && canAutoInsert(newProposals.get(0))) {
							if (Helper.okToUse(fProposalShell)) {
								insertProposal(newProposals.get(0), (char) 0, 0, offset);
								hide();
							}
							return;
						}
						if (remaining.isEmpty() && callback != null) {
							callback.accept(newProposals);
						} else {
							setProposals(newProposals, false);
							displayProposals();
						}
					});
				});
			}
			displayProposals();
		}
		return computedProposals;
	}

	@Override
	public String incrementalComplete() {
		cancelFutures();
		if (Helper.okToUse(fProposalShell) && fFilteredProposals != null) {
			return super.incrementalComplete();
		}
		final Control control= fContentAssistSubjectControlAdapter.getControl();

		if (fKeyListener == null)
			fKeyListener= new ProposalSelectionListener();

		if (!Helper.okToUse(fProposalShell) && !control.isDisposed())
			fContentAssistSubjectControlAdapter.addKeyListener(fKeyListener);

		fInvocationOffset= fContentAssistSubjectControlAdapter.getSelectedRange().x;
		fFilterOffset= fInvocationOffset;
		fLastCompletionOffset= fFilterOffset;

		fFutures= buildCompletionFuturesOrJobs(fInvocationOffset);
		fFilteredProposals= runFutures(fInvocationOffset, (List<ICompletionProposal> proposals) -> {
			ensureDocumentListenerInstalled();
			if (proposals.size() > 0 && completeCommonPrefix()) {
				hide();
			} else {
				fFilteredProposals= proposals;
				setProposals(proposals, false);
				displayProposals();
			}
		}, true, false, true);
		return getErrorMessage();
	}

	@Override
	List<ICompletionProposal> computeProposals(int offset) {
		if (fProposalShell != null) {
			fProposalShell.dispose();
		}
		showProposals(true);
		return fComputedProposals;
	}

	@Override
	void createProposalSelector() {
		super.createProposalSelector();
		fProposalShell.addDisposeListener(e -> cancelFutures());
	}

	void cancelFutures() {
		if (fFutures != null) {
			for (Future<?> future : fFutures) {
				future.cancel(true);
			}
			fFutures= null;
		}
	}

	@Override
	protected List<ICompletionProposal> computeFilteredProposals(int offset, DocumentEvent event) {
		if(fComputedProposals != null && fComputedProposals.size() > 0 && fComputedProposals.get(0) instanceof ComputingProposal) {
			Set<CompletableFuture<List<ICompletionProposal>>> remaining = Collections.synchronizedSet(new HashSet<>(fFutures));
			for (CompletableFuture<List<ICompletionProposal>> future : fFutures) {
				future.thenRun(() -> {
					remaining.removeIf(CompletableFuture::isDone);
					if (remaining.isEmpty()) {
						filterProposals();
					}
				});
			}
			return fComputedProposals;
		}
		return super.computeFilteredProposals(offset, event);
	}

	@Override
	public void hide() {
		super.hide();
		cancelFutures();
	}

	protected List<CompletableFuture<List<ICompletionProposal>>> buildCompletionFuturesOrJobs(int invocationOffset) {
		Set<IContentAssistProcessor> processors = null;
		try {
			processors= fContentAssistant.getContentAssistProcessors(getTokenContentType(invocationOffset));
		} catch (BadLocationException e) {
			// ignore
		}
		if (processors == null) {
			return Collections.emptyList();
		}
		List<CompletableFuture<List<ICompletionProposal>>> futures = new ArrayList<>(processors.size());
		for (IContentAssistProcessor processor : processors) {
			futures.add(CompletableFuture.supplyAsync(() -> {
				ICompletionProposal[] proposals= processor.computeCompletionProposals(fViewer, invocationOffset);
				if (proposals == null) {
					return Collections.emptyList();
				}
				return Arrays.asList(proposals);
			}));
		}
		return futures;
	}

	private String getTokenContentType(int invocationOffset) throws BadLocationException {
		if (fContentAssistSubjectControl != null) {
			IDocument document= fContentAssistSubjectControl.getDocument();
			if (document != null) {
				return TextUtilities.getContentType(document, fContentAssistant.getDocumentPartitioning(), invocationOffset, true);
			}
		} else {
			return TextUtilities.getContentType(fViewer.getDocument(), fContentAssistant.getDocumentPartitioning(), invocationOffset, true);
		}
		return IDocument.DEFAULT_CONTENT_TYPE;
	}

}
