/*=============================================================================#
 # Copyright (c) 2005, 2021 Stephan Wahlbrink 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, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

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

import static org.eclipse.statet.jcommons.lang.ObjectUtils.nonNullAssert;

import java.util.Comparator;

import com.ibm.icu.text.Collator;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.BadPositionCategoryException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.contentassist.ICompletionProposal;
import org.eclipse.jface.text.contentassist.ICompletionProposalExtension5;
import org.eclipse.jface.text.link.ILinkedModeListener;
import org.eclipse.jface.text.link.InclusivePositionUpdater;
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.text.templates.DocumentTemplateContext;
import org.eclipse.jface.text.templates.GlobalTemplateVariables;
import org.eclipse.jface.text.templates.Template;
import org.eclipse.jface.text.templates.TemplateBuffer;
import org.eclipse.jface.text.templates.TemplateContext;
import org.eclipse.jface.text.templates.TemplateException;
import org.eclipse.jface.text.templates.TemplateVariable;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.swt.graphics.Image;
import org.eclipse.ui.statushandlers.StatusManager;

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.jcommons.text.core.SearchPattern;
import org.eclipse.statet.jcommons.text.core.TextRegion;

import org.eclipse.statet.ecommons.text.ui.DefaultBrowserInformationInput;
import org.eclipse.statet.ecommons.text.ui.PositionBasedCompletionProposal;

import org.eclipse.statet.internal.ltk.ui.LTKUIPlugin;
import org.eclipse.statet.ltk.ui.LTKUI;
import org.eclipse.statet.ltk.ui.sourceediting.TextEditToolSynchronizer;
import org.eclipse.statet.ltk.ui.templates.IWorkbenchTemplateContext;
import org.eclipse.statet.ltk.ui.util.LTKSelectionUtils;


/**
 * Like default {@link org.eclipse.jface.text.templates.TemplateProposal}, but
 * <ul>
 *   <li>supports substring matching
 *   <li>supports {@link TextEditToolSynchronizer}</li>
 * </ul>
 */
@NonNullByDefault
public class TemplateProposal extends SourceProposal implements ICompletionProposalExtension5 {
	
	public static class TemplateComparator implements Comparator<TemplateProposal> {
		
		
		private final Collator collator= Collator.getInstance();
		
		
		public TemplateComparator() {
		}
		
		
		@Override
		public int compare(final TemplateProposal arg0, final TemplateProposal arg1) {
			final int result= this.collator.compare(arg0.getTemplate().getName(), arg1.getTemplate().getName());
			if (result != 0) {
				return result;
			}
			return this.collator.compare(arg0.getDisplayString(), arg1.getDisplayString());
		}
		
	}
	
	public static class TemplateProposalParameters<TContext extends AssistInvocationContext>
			extends ProposalParameters<TContext> {
		
		
		public final DocumentTemplateContext templateContext;
		
		public final TextRegion region;
		
		public Template template;
		
		
		@SuppressWarnings("null")
		public TemplateProposalParameters(
				final TContext context, final TextRegion region,
				final SearchPattern namePattern,
				final DocumentTemplateContext templateContext) {
			super(context, region.getStartOffset(), namePattern);
			
			this.templateContext= templateContext;
			this.region= region;
		}
		
		public TemplateProposalParameters(
				final TContext context, final TextRegion region,
				final DocumentTemplateContext templateContext, final Template template) {
			super(context, region.getStartOffset(), 0);
			
			this.templateContext= templateContext;
			this.region= region;
			
			this.template= template;
		}
		
	}
	
	
	private final Template template;
	private final DocumentTemplateContext templateContext;
	
	private final Image image;
	
	private TextRegion region;
	
	private @Nullable InclusivePositionUpdater updater;
	
	
	public TemplateProposal(final TemplateProposalParameters<?> parameters,
			final Image image) {
		super(parameters);
		
		this.template= nonNullAssert(parameters.template);
		this.templateContext= nonNullAssert(parameters.templateContext);
		this.image= nonNullAssert(image);
		this.region= nonNullAssert(parameters.region);
	}
	
	public TemplateProposal(final TemplateProposalParameters<?> parameters) {
		this(parameters,
				LTKUIPlugin.getInstance().getImageRegistry().get(LTKUI.OBJ_TEXT_TEMPLATE_IMAGE_ID) );
	}
	
	
	protected TemplateContext getContext() {
		return this.templateContext;
	}
	
	protected Template getTemplate() {
		return this.template;
	}
	
	protected boolean isSelectionTemplate() {
		if (this.templateContext instanceof DocumentTemplateContext) {
			final DocumentTemplateContext docContext= this.templateContext;
			if (docContext.getCompletionLength() > 0) {
				return true;
			}
		}
		return false;
	}
	
	
	@Override
	protected String getName() {
		return this.template.getName();
	}
	
	
	@Override
	public String getSortingString() {
		return this.template.getName();
	}
	
	
	@Override
	public String getDisplayString() {
		return getStyledDisplayString().getString();
	}
	
	@Override
	public StyledString computeStyledText() {
		final StyledString styledText= new StyledString(this.template.getName());
		if (!this.template.getDescription().isEmpty()) {
			styledText.append(QUALIFIER_SEPARATOR, StyledString.QUALIFIER_STYLER);
			styledText.append(this.template.getDescription(), StyledString.QUALIFIER_STYLER);
		}
		return styledText;
	}
	
	@Override
	public Image getImage() {
		return this.image;
	}
	
	
	@Override
	public @Nullable Object getAdditionalProposalInfo(final IProgressMonitor monitor) {
		try {
			final TemplateContext context= getContext();
			context.setReadOnly(true);
			final String preview;
			if (context instanceof IWorkbenchTemplateContext) {
				preview= ((IWorkbenchTemplateContext)context).evaluateInfo(getTemplate());
			}
			else {
				final TemplateBuffer templateBuffer= context.evaluate(getTemplate());
				preview= (templateBuffer != null) ? templateBuffer.toString() : null;
			}
			
			if (preview != null) {
				return new DefaultBrowserInformationInput(getDisplayString(),
						preview, DefaultBrowserInformationInput.FORMAT_SOURCE_INPUT,
						getInvocationContext().getTabSize() );
			}
		}
		catch (final TemplateException | BadLocationException e) {}
		return null;
	}
	
	
	@Override
	public boolean isAutoInsertable() {
		if (isSelectionTemplate()) {
			return false;
		}
		return this.template.isAutoInsertable();
	}
	
	
	@Override
	public @Nullable CharSequence getPrefixCompletionText(final IDocument document, final int offset) {
		if (isSelectionTemplate()) {
			return null;
		}
		return super.getPrefixCompletionText(document, offset);
	}
	
	
	@Override
	public void apply(final ITextViewer viewer, final char trigger, final int stateMask, final int offset) {
		final IDocument document= viewer.getDocument();
		final ApplyData applyData= getApplyData();
		
		final Position regionPosition= new Position(this.region.getStartOffset(), this.region.getLength());
		final Position offsetPosition= new Position(offset, 0);
		try {
			document.addPosition(regionPosition);
			document.addPosition(offsetPosition);
			this.templateContext.setReadOnly(false);
			TemplateBuffer templateBuffer;
			try {
				templateBuffer= nonNullAssert(this.templateContext.evaluate(this.template));
			}
			catch (final TemplateException | NullPointerException e) {
				applyData.setSelection(this.region);
				return;
			}
			
			this.region= LTKSelectionUtils.toTextRegion(regionPosition);
			final int start= getReplaceOffset();
			final int end= Math.max(getReplaceEndOffset(), offsetPosition.getOffset());
			
			// insert template string
			final String templateString= templateBuffer.getString();
			document.replace(start, end - start, templateString);
			
			// translate positions
			final LinkedModeModel model= new LinkedModeModel();
			final TemplateVariable[] variables= templateBuffer.getVariables();
			boolean hasPositions= false;
			for (int i= 0; i != variables.length; i++) {
				final TemplateVariable variable= variables[i];
				
				if (variable.isUnambiguous()) {
					continue;
				}
				
				final LinkedPositionGroup group= new LinkedPositionGroup();
				
				final int[] offsets= variable.getOffsets();
				final int length= variable.getLength();
				
				final String[] values= variable.getValues();
				final ICompletionProposal[] proposals= new @NonNull ICompletionProposal[values.length];
				for (int j= 0; j < values.length; j++) {
					ensurePositionCategoryInstalled(document, model);
					final Position pos= new Position(offsets[0] + start, length);
					document.addPosition(getCategory(), pos);
					proposals[j]= new PositionBasedCompletionProposal(values[j], pos, length);
				}
				
				for (int j= 0; j < offsets.length; j++) {
					if (j == 0 && proposals.length > 1) {
						group.addPosition(new ProposalPosition(document, offsets[j] + start, length, proposals));
					}
					else {
						group.addPosition(new LinkedPosition(document, offsets[j] + start, length));
					}
				}
				
				model.addGroup(group);
				hasPositions= true;
			}
			
			if (hasPositions) {
				model.forceInstall();
				
				final TextEditToolSynchronizer toolSynchronizer= getInvocationContext().getEditor()
						.getTextEditToolSynchronizer();
				if (toolSynchronizer != null) {
					toolSynchronizer.install(model);
				}
				
				final LinkedModeUI ui= new LinkedModeUI(model, viewer);
				ui.setExitPosition(viewer, getCaretOffset(templateBuffer) + start, 0, Integer.MAX_VALUE);
				ui.enter();
				
				applyData.setSelection(LTKSelectionUtils.toTextRegion(ui.getSelectedRegion()));
			}
			else {
				ensurePositionCategoryRemoved(document);
				applyData.setSelection(getCaretOffset(templateBuffer) + start);
			}
		}
		catch (final BadLocationException | BadPositionCategoryException e) {
			StatusManager.getManager().handle(new Status(IStatus.ERROR, LTKUIPlugin.BUNDLE_ID, 0,
					"Template Evaluation Error",
					e ));
			applyData.clearSelection();
		}
		finally {
			document.removePosition(regionPosition);
			document.removePosition(offsetPosition);
		}
	}
	
	
	private String getCategory() {
		return "TemplateProposalCategory_" + toString(); //$NON-NLS-1$
	}
	
	private void ensurePositionCategoryInstalled(final IDocument document, final LinkedModeModel model) {
		if (!document.containsPositionCategory(getCategory())) {
			document.addPositionCategory(getCategory());
			this.updater= new InclusivePositionUpdater(getCategory());
			document.addPositionUpdater(this.updater);
			
			model.addLinkingListener(new ILinkedModeListener() {
				
				@Override
				public void left(final LinkedModeModel environment, final int flags) {
					ensurePositionCategoryRemoved(document);
				}
				
				@Override
				public void suspend(final LinkedModeModel environment) {}
				@Override
				public void resume(final LinkedModeModel environment, final int flags) {}
			});
		}
	}
	
	private void ensurePositionCategoryRemoved(final IDocument document) {
		if (document.containsPositionCategory(getCategory())) {
			try {
				document.removePositionCategory(getCategory());
			} catch (final BadPositionCategoryException e) {
				// ignore
			}
			document.removePositionUpdater(this.updater);
		}
	}
	
	private int getCaretOffset(final TemplateBuffer buffer) {
		final TemplateVariable[] variables= buffer.getVariables();
		for (int i= 0; i != variables.length; i++) {
			final TemplateVariable variable= variables[i];
			if (variable.getType().equals(GlobalTemplateVariables.Cursor.NAME)) {
				return variable.getOffsets()[0];
			}
		}
		return buffer.getString().length();
	}
	
	/**
	 * Returns the offset of the range in the document that will be replaced by
	 * applying this template.
	 * 
	 * @return the offset of the range in the document that will be replaced by
	 *     applying this template
	 */
	protected final int getReplaceOffset() {
		int start;
		if (this.templateContext instanceof DocumentTemplateContext) {
			final DocumentTemplateContext docContext= this.templateContext;
			start= docContext.getStart();
		}
		else {
			start= this.region.getStartOffset();
		}
		return start;
	}
	
	/**
	 * Returns the end offset of the range in the document that will be replaced
	 * by applying this template.
	 * 
	 * @return the end offset of the range in the document that will be replaced
	 *     by applying this template
	 */
	protected final int getReplaceEndOffset() {
		int end;
		if (this.templateContext instanceof DocumentTemplateContext) {
			final DocumentTemplateContext docContext= this.templateContext;
			end= docContext.getEnd();
		}
		else {
			end= this.region.getEndOffset();
		}
		return end;
	}
	
	@Override
	public int getContextInformationPosition() {
		return this.region.getStartOffset();
	}
	
}
