/*=============================================================================#
 # 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.ITextEditToolSynchronizer;
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 ITextEditToolSynchronizer}</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);
			if (context instanceof IWorkbenchTemplateContext) {
				return new DefaultBrowserInformationInput(
						null, getDisplayString(), ((IWorkbenchTemplateContext) context).evaluateInfo(getTemplate()),
						DefaultBrowserInformationInput.FORMAT_SOURCE_INPUT );
			}
			
			final TemplateBuffer templateBuffer= context.evaluate(getTemplate());
			if (templateBuffer != null) {
				return new DefaultBrowserInformationInput(
						null, getDisplayString(), templateBuffer.toString(),
						DefaultBrowserInformationInput.FORMAT_SOURCE_INPUT );
			}
		}
		catch (final TemplateException e) {}
		catch (final 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 ITextEditToolSynchronizer 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();
	}
	
}
