/*=============================================================================#
 # 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.List;
import java.util.regex.Pattern;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.templates.GlobalTemplateVariables;
import org.eclipse.jface.text.templates.GlobalTemplateVariables.LineSelection;
import org.eclipse.jface.text.templates.GlobalTemplateVariables.WordSelection;
import org.eclipse.jface.text.templates.Template;
import org.eclipse.jface.text.templates.TemplateContextType;
import org.eclipse.jface.text.templates.TemplateException;
import org.eclipse.jface.text.templates.persistence.TemplateStore;
import org.eclipse.swt.graphics.Image;
import org.eclipse.text.templates.ContextTypeRegistry;

import org.eclipse.statet.jcommons.collections.ImCollections;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.lang.Nullable;
import org.eclipse.statet.jcommons.text.core.BasicTextRegion;
import org.eclipse.statet.jcommons.text.core.SearchPattern;
import org.eclipse.statet.jcommons.text.core.TextRegion;

import org.eclipse.statet.internal.ltk.ui.LtkUIPlugin;
import org.eclipse.statet.ltk.ui.LtkUI;
import org.eclipse.statet.ltk.ui.sourceediting.SourceEditor;
import org.eclipse.statet.ltk.ui.sourceediting.assist.SourceProposal.ProposalParameters;
import org.eclipse.statet.ltk.ui.sourceediting.assist.TemplateProposal.TemplateProposalParameters;
import org.eclipse.statet.ltk.ui.templates.SourceEditorTemplateContext;


/**
 * Content assist computer for editor templates.
 */
@NonNullByDefault
public abstract class TemplateCompletionComputer implements ContentAssistComputer {
	
	
	private static final byte SELECTION_NONE= 0;
	private static final byte SELECTION_INLINE= 1;
	private static final byte SELECTION_MULTILINE= 2;
	
	private static final Pattern SELECTION_INLINE_PATTERN= Pattern.compile(
			"\\$\\{" + WordSelection.NAME + "\\}"); //$NON-NLS-1$ //$NON-NLS-2$
	private static final Pattern SELECTION_ANY_PATTERN= Pattern.compile(
			"\\$\\{(?:" + WordSelection.NAME + "|" + LineSelection.NAME + ")\\}"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	
	protected static final int SELECTION_MATCH= 1 << 21;
	
	
	protected final TemplateStore templateStore;
	
	protected final org.eclipse.text.templates.ContextTypeRegistry typeRegistry;
	
	private int searchMatchRules;
	
	
	public TemplateCompletionComputer(final TemplateStore templateStore, final ContextTypeRegistry contextTypes) {
		this.templateStore= nonNullAssert(templateStore);
		this.typeRegistry= nonNullAssert(contextTypes);
	}
	
	
	protected final TemplateStore getTemplateStore() {
		return this.templateStore;
	}
	
	protected final ContextTypeRegistry getTypeRegistry() {
		return this.typeRegistry;
	}
	
	
	@Override
	public void onSessionStarted(final SourceEditor editor, final ContentAssist assist) {
		int matchRules= SearchPattern.PREFIX_MATCH;
		if (assist.getShowSubstringMatches()) {
			matchRules |= SearchPattern.SUBSTRING_MATCH;
		}
		this.searchMatchRules= matchRules;
	}
	
	@Override
	public void onSessionEnded() {
	}
	
	
	protected boolean handleRequest(final int mode, final String prefix) {
		return (prefix != null
				&& (prefix.length() > 0 || mode == SPECIFIC_MODE) );
	}
	
	protected int getSearchMatchRules() {
		return this.searchMatchRules;
	}
	
	
	@Override
	public void computeCompletionProposals(final AssistInvocationContext context,
			final int mode, final AssistProposalCollector proposals, final IProgressMonitor monitor) {
		final ISourceViewer viewer= context.getSourceViewer();
		final int flags= 0;
		
		String prefix= extractPrefix(context);
		if (!handleRequest(mode, prefix)) {
			return;
		}
		TextRegion region;
		if (context.getLength() == 0) {
			region= new BasicTextRegion(context.getInvocationOffset() - prefix.length(), context.getInvocationOffset());
		}
		else {
			region= context;
		}
		SourceEditorTemplateContext templateContext= createTemplateContext(context, region, flags);
		if (templateContext == null) {
			return;
		}
		
		int count= 0;
		if (context.getLength() > 0) {
			if (prefix.length() == context.getLength()) {
				final TemplateProposalParameters<?> parameters=  new TemplateProposalParameters<>(
						context, region,
						new SearchPattern(getSearchMatchRules(), prefix),
						templateContext );
				count= computeProposals0(parameters, 0, proposals);
			}
			prefix= ""; // wenn erfolglos, dann ohne prefix //$NON-NLS-1$
			if (count != 0) {
				templateContext= createTemplateContext(context, region, flags);
				if (templateContext == null) {
					return;
				}
			}
		}
		try {
			final int selectionType= configureTemplateContext(context, templateContext);
			
			final TemplateProposalParameters<?> parameters=  new TemplateProposalParameters<>(
					context, region,
					new SearchPattern(getSearchMatchRules(), prefix),
					templateContext );
			computeProposals0(parameters, selectionType, proposals);
		}
		catch (final BadLocationException e) {
		}
	}
	
	@Override
	public void computeInformationProposals(final AssistInvocationContext context,
			final AssistProposalCollector tenders, final IProgressMonitor monitor) {
	}
	
	
	private int computeProposals0(final TemplateProposalParameters<?> parameters,
			final int selectionType,
			final AssistProposalCollector proposals) {
		final int count= 0;
		final List<Template> templates= getTemplates(
				parameters.templateContext.getContextType().getId() );
		for (final Template template : templates) {
			parameters.matchRule= 0;
			if (include(template, parameters) || isSelectionTemplate(selectionType, template, parameters) ) {
				try {
					parameters.templateContext.getContextType().validate(template.getPattern());
				}
				catch (final TemplateException e) {
					continue;
				}
				
				parameters.template= template;
				switch (parameters.matchRule) {
				case SearchPattern.PREFIX_MATCH:
					parameters.baseRelevance= 20;
					break;
				case SELECTION_MATCH:
					parameters.baseRelevance= 16;
					break;
				case SearchPattern.OTHER_MATCH:
					parameters.baseRelevance= 15;
					break;
				default:
					parameters.baseRelevance= -100;
					break;
				}
				
				proposals.add(createProposal(parameters));
			}
		}
		
		return count;
	}
	
	protected boolean include(final Template template, final TemplateProposalParameters<?> parameters) {
		return parameters.matchesNamePattern(template.getName());
	}
	
	private boolean isSelectionTemplate(final int selectionType,
			final Template template, final ProposalParameters<?> parameters) {
		switch (selectionType) {
		case SELECTION_INLINE:
			if (SELECTION_INLINE_PATTERN.matcher(template.getPattern()).matches()) {
				parameters.matchRule= SELECTION_MATCH;
				return true;
			}
			return false;
		case SELECTION_MULTILINE:
			if (SELECTION_ANY_PATTERN.matcher(template.getPattern()).matches()) {
				parameters.matchRule= SELECTION_MATCH;
				return true;
			}
			return false;
		default:
			return false;
		}
	}
	
	
	protected @Nullable String extractPrefix(final AssistInvocationContext context) {
		return context.getIdentifierPrefix();
	}
	
	protected List<Template> getTemplates(final String contextTypeId) {
		return ImCollections.newList(this.templateStore.getTemplates(contextTypeId));
	}
	
	protected abstract @Nullable TemplateContextType getContextType(
			final AssistInvocationContext context, final TextRegion region);
	
	public @Nullable SourceEditorTemplateContext createTemplateContext(
			final AssistInvocationContext context, final TextRegion region,
			final int flags, final boolean configure) throws BadLocationException {
		final SourceEditorTemplateContext templateContext= createTemplateContext(context, region, flags);
		if (templateContext != null && configure) {
			configureTemplateContext(context, templateContext);
		}
		return templateContext;
	}
	
	protected @Nullable SourceEditorTemplateContext createTemplateContext(
			final AssistInvocationContext context, final TextRegion region,
			final int flags) {
		final TemplateContextType contextType= getContextType(context, region);
		if (contextType != null) {
			return new SourceEditorTemplateContext(contextType, context.getDocument(), region,
					context.getEditor(), flags );
		}
		return null;
	}
	
	protected int configureTemplateContext(final AssistInvocationContext context,
			final SourceEditorTemplateContext templateContext) throws BadLocationException {
		final IDocument document= context.getDocument();
		final String text= document.get(context.getOffset(), context.getLength());
		final int selectionType;
		if (text.isEmpty()) {
			selectionType= SELECTION_NONE;
		}
		else {
			selectionType= (text.indexOf('\n') >= 0) ? SELECTION_MULTILINE : SELECTION_INLINE;
			templateContext.setVariable("text", text); //$NON-NLS-1$
		}
		templateContext.setVariable(GlobalTemplateVariables.SELECTION, text);
		return selectionType;
	}
	
	protected TemplateProposal createProposal(final TemplateProposalParameters<?> parameters) {
		return new TemplateProposal(parameters, getImage(parameters.template));
	}
	
	protected @Nullable Image getImage(final Template template) {
		return LtkUIPlugin.getInstance().getImageRegistry().get(LtkUI.OBJ_TEXT_TEMPLATE_IMAGE_ID);
	}
	
}
