/*=============================================================================#
 # Copyright (c) 2009, 2019 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.internal.docmlet.tex.ui.editors;

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

import java.util.ArrayList;
import java.util.List;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentEvent;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentListener;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.text.contentassist.BoldStylerProvider;
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.source.SourceViewer;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.VerifyKeyListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Display;

import org.eclipse.statet.jcommons.collections.IntArrayList;
import org.eclipse.statet.jcommons.collections.IntIntervalArrays;
import org.eclipse.statet.jcommons.collections.IntList;
import org.eclipse.statet.jcommons.lang.NonNullByDefault;
import org.eclipse.statet.jcommons.text.core.SearchPattern;

import org.eclipse.statet.ecommons.text.ITokenScanner;
import org.eclipse.statet.ecommons.text.ui.BracketLevel;
import org.eclipse.statet.ecommons.ui.util.UIAccess;
import org.eclipse.statet.ecommons.ui.viewers.StyledTextUtils;

import org.eclipse.statet.docmlet.tex.core.commands.Argument;
import org.eclipse.statet.docmlet.tex.core.commands.EnvDefinitions;
import org.eclipse.statet.docmlet.tex.core.commands.TexCommand;
import org.eclipse.statet.docmlet.tex.core.source.LtxHeuristicTokenScanner;
import org.eclipse.statet.docmlet.tex.ui.TexUIResources;
import org.eclipse.statet.internal.docmlet.tex.ui.sourceediting.LtxAssistInvocationContext;
import org.eclipse.statet.internal.docmlet.tex.ui.sourceediting.TexBracketLevel;
import org.eclipse.statet.ltk.ui.sourceediting.assist.SourceProposal;


@NonNullByDefault
public class LtxCommandCompletionProposal extends SourceProposal<LtxAssistInvocationContext> {
	
	
	public static class LtxCommandProposalParameters extends ProposalParameters<LtxAssistInvocationContext> {
		
		
		public TexCommand command;
		
		
		public LtxCommandProposalParameters(
				final LtxAssistInvocationContext context, final int replacementOffset,
				final SearchPattern namePattern, final int baseRelevance) {
			super(context, replacementOffset, namePattern, baseRelevance);
		}
		
		public LtxCommandProposalParameters(
				final LtxAssistInvocationContext context, final int replacementOffset,
				final SearchPattern namePattern) {
			super(context, replacementOffset, namePattern);
		}
		
		public LtxCommandProposalParameters(final TexCommand command,
				final LtxAssistInvocationContext context, final int replacementOffset) {
			super(context, replacementOffset, null);
			
			this.command= command;
		}
		
	}
	
	
	public static class Env extends LtxCommandCompletionProposal {
		
		
		protected Env(final LtxCommandProposalParameters parameters) {
			super(parameters);
		}
		
		
		@Override
		protected StyledString computeStyledText() {
			final StyledString styledText= new StyledString(this.command.getControlWord());
			styledText.append(QUALIFIER_SEPARATOR, StyledString.QUALIFIER_STYLER);
			styledText.append(this.command.getDescription(), StyledString.QUALIFIER_STYLER);
			return styledText;
		}
		
	}
	
	
	private static class LinkedSepMode implements IDocumentListener, VerifyKeyListener {
		
		private final SourceViewer viewer;
		private final IDocument document;
		private final int offset;
		
		private boolean inserted;
		private boolean intern;
		
		public LinkedSepMode(final SourceViewer viewer, final IDocument document, final int offset) {
			this.viewer= viewer;
			this.document= document;
			this.offset= offset;
		}
		
		public void install() {
			if (UIAccess.isOkToUse(this.viewer)) {
				this.viewer.getTextWidget().addVerifyKeyListener(this);
				this.document.addDocumentListener(this);
			}
		}
		
		@Override
		public void verifyKey(final VerifyEvent event) {
			if (this.viewer.getDocument() == this.document) {
				final Point selection= this.viewer.getSelectedRange();
				if (!this.inserted
						&& selection.x == this.offset && selection.y == 0
						&& (event.character != 0) ) {
					try {
						final int currentChar= (this.offset < this.document.getLength()) ? this.document.getChar(this.offset) : '\n';
						final char c= event.character;
						if (currentChar <= 0x20 && currentChar != c
								&& c >= 0x20 && !Character.isLetterOrDigit(c) ) {
							this.intern= true;
							this.document.replace(this.offset, 0, "" + c + c);
							// install linked mode?
							this.inserted= true;
							event.doit= false;
							this.viewer.setSelection(new TextSelection(this.offset+1, 0), true);
							return;
						}
					}
					catch (final BadLocationException e) {
					}
					finally {
						this.intern= false;
					}
				}
				if (this.inserted && event.character == SWT.BS
						&& selection.x == this.offset + 1 && selection.y == 0) {
					try {
						this.intern= true;
						this.document.replace(this.offset, 2, "");
						this.inserted= false;
						event.doit= false;
						return;
					}
					catch (final BadLocationException e) {
					}
					finally {
						this.intern= false;
					}
				}
			}
		}
		
		@Override
		public void documentAboutToBeChanged(final DocumentEvent event) {
		}
		
		@Override
		public void documentChanged(final DocumentEvent event) {
			if (!this.intern) {
				dispose();
			}
		}
		
		private void dispose() {
			this.viewer.getTextWidget().removeVerifyKeyListener(this);
			this.document.removeDocumentListener(this);
		}
		
	}
	
	
	private static final boolean isFollowedByOpeningBracket(final int forwardOffset, final boolean allowSquare,
			final LtxAssistInvocationContext context) {
		final LtxHeuristicTokenScanner scanner= context.getLtxHeuristicTokenScanner();
		scanner.configure(context.getDocument());
		final int idx= scanner.findAnyNonBlankForward(forwardOffset, ITokenScanner.UNBOUND, false);
		return (idx >= 0
				&& (scanner.getChar() == '{' || (allowSquare && scanner.getChar() == '[')) );
	}
	
	private static final boolean isClosedBracket(final int backwardOffset, final int forwardOffset,
			final LtxAssistInvocationContext context) {
		final int searchType= LtxHeuristicTokenScanner.CURLY_BRACKET_TYPE;
		int[] balance= new int[3];
		balance[searchType]++;
		final LtxHeuristicTokenScanner scanner= context.getLtxHeuristicTokenScanner();
		scanner.configureDefaultPartitions(context.getDocument());
		balance= scanner.computeBracketBalance(backwardOffset, forwardOffset, balance, searchType);
		return (balance[searchType] <= 0);
	}
	
	
	protected final TexCommand command;
	
	
	protected LtxCommandCompletionProposal(final LtxCommandProposalParameters parameters) {
		super(parameters);
		
		this.command= nonNullAssert(parameters.command);
	}
	
	
	@Override
	protected String getName() {
		return this.command.getControlWord();
	}
	
	@Override
	protected int computeReplacementLength(final int replacementOffset, final Point selection,
			final int caretOffset, final boolean overwrite) throws BadLocationException {
		int end= Math.max(caretOffset, selection.x + selection.y);
		if (overwrite) {
			final LtxAssistInvocationContext context= getInvocationContext();
			final IDocument document= context.getDocument();
			end--;
			SEARCH_END: while (++end < document.getLength()) {
				switch (document.getChar(end)) {
				case 'a':
				case 'b':
				case 'c':
				case 'd':
				case 'e':
				case 'f':
				case 'g':
				case 'h':
				case 'i':
				case 'j':
				case 'k':
				case 'l':
				case 'm':
				case 'n':
				case 'o':
				case 'p':
				case 'q':
				case 'r':
				case 's':
				case 't':
				case 'u':
				case 'v':
				case 'w':
				case 'x':
				case 'y':
				case 'z':
				case 'A':
				case 'B':
				case 'C':
				case 'D':
				case 'E':
				case 'F':
				case 'G':
				case 'H':
				case 'I':
				case 'J':
				case 'K':
				case 'L':
				case 'M':
				case 'N':
				case 'O':
				case 'P':
				case 'Q':
				case 'R':
				case 'S':
				case 'T':
				case 'U':
				case 'V':
				case 'W':
				case 'X':
				case 'Y':
				case 'Z':
					continue SEARCH_END;
				default:
					break SEARCH_END;
				}
			}
		}
		return (end - replacementOffset);
	}
	
	
	@Override
	public String getSortingString() {
		return this.command.getControlWord();
	}
	
	
	@Override
	public String getDisplayString() {
		return getStyledDisplayString().getString();
	}
	
	@Override
	protected StyledString computeStyledText() {
		final StyledString styledText= new StyledString(((this.command.getType() & TexCommand.MASK_MAIN) == TexCommand.ENV) ?
						this.command.getControlWord() : "\\" + this.command.getControlWord() );
		for (final Argument arg : this.command.getArguments()) {
			if ((arg.getType() & Argument.OPTIONAL) != 0) {
				styledText.append("[]");
			}
			else {
				styledText.append("{}");
			}
		}
		styledText.append(" – " + this.command.getDescription(), StyledString.QUALIFIER_STYLER);
		return styledText;
	}
	
	@Override
	protected void styleMatchingRegions(final StyledString styledText,
			final int matchRule, int[] matchingRegions,
			final BoldStylerProvider boldStylerProvider) {
		matchingRegions= IntIntervalArrays.insertRegion(matchingRegions, 0, 1);
		StyledTextUtils.setStyle(styledText, matchingRegions, boldStylerProvider.getBoldStyler());
	}
	
	@Override
	public Image getImage() {
		return TexUIResources.INSTANCE.getCommandImage(this.command);
	}
	
	
	@Override
	public boolean isAutoInsertable() {
		return true;
	}
	
	
	@Override
	protected void doApply(final char trigger, final int stateMask, final int caretOffset,
			final int replacementOffset, final int replacementLength) throws BadLocationException {
		final LtxAssistInvocationContext context= getInvocationContext();
		final IDocument document= context.getDocument();
		final ApplyData applyData= getApplyData();
		
		final StringBuilder replacement= new StringBuilder(this.command.getControlWord());
		if ((stateMask & 0x1) == 0x1) {
			replacement.insert(0, '\\');
		}
		int cursor= replacement.length();
		int mode= 0;
		IntList positions= null;
		if (this.command == EnvDefinitions.VERBATIM_verb_COMMAND) {
			mode= 201;
		}
		else if ((this.command.getType() & TexCommand.MASK_MAIN) != TexCommand.ENV) {
			final List<Argument> args= this.command.getArguments();
			if (args != null && !args.isEmpty()) {
				final boolean isFirstOptional= args.get(0).isOptional();
				int idxFirstRequired= -1;
				for (int i= (isFirstOptional) ? 1 : 0; i < args.size(); i++) {
					final Argument arg= args.get(i);
					if (arg.isRequired()) {
						idxFirstRequired= i;
						break;
					}
				}
				if (idxFirstRequired >= 0) {
					if (replacementOffset+replacementLength < document.getLength()-1
							&& (document.getChar(replacementOffset+replacementLength) == '{'
									|| (isFirstOptional && document.getChar(replacementOffset+replacementLength) == '[') )) {
						cursor ++;
						mode= 10;
					}
					else if (!isFollowedByOpeningBracket(
							replacementOffset + replacementLength, isFirstOptional, context )) {
						replacement.append('{');
						cursor ++;
						mode= 11;
					}
					if (mode >= 10) {
						if (mode == 11 && !isClosedBracket(
								replacementOffset, replacementOffset + replacementLength, context )) {
							replacement.append('}');
							
							positions= new IntArrayList();
							mode= 0;
							if (isFirstOptional) {
								positions.add(mode);
							}
							mode++;
							positions.add(mode++);
							for (int i= idxFirstRequired+1; i < args.size(); i++) {
								if (args.get(i).isRequired()) {
									replacement.append("{}");
									mode++;
									positions.add(mode++);
								}
								else if (positions.getAt(positions.size() - 1) != mode) {
									positions.add(mode);
								}
							}
							if (positions.getAt(positions.size() - 1) != mode) {
								positions.add(mode);
							}
							mode= 110 + 1;
							// add multiple arguments
						}
					}
				}
			}
		}
		document.replace(replacementOffset, replacementLength, replacement.toString());
		
		applyData.setSelection(replacementOffset + cursor);
		if (mode > 100 && mode < 200) {
			createLinkedMode(replacementOffset + cursor - (mode - 110), positions).enter();
		}
		else if (mode > 200 && mode < 300) {
			createLinkedVerbMode(replacementOffset + cursor);
		}
		if ((this.command.getType() & TexCommand.MASK_MAIN) == TexCommand.GENERICENV) {
			reinvokeAssist();
		}
	}
	
	private LinkedModeUI createLinkedMode(final int offset, final IntList positions)
			throws BadLocationException {
		final LtxAssistInvocationContext context= getInvocationContext();
		final IDocument document= context.getDocument();
		
		final LinkedModeModel model= new LinkedModeModel();
		int pos= 0;
		
		final List<LinkedPosition> linked= new ArrayList<>(positions.size());
		for (int i= 0; i < positions.size() - 1; i++) {
			final LinkedPositionGroup group= new LinkedPositionGroup();
			final LinkedPosition position= (positions.getAt(i) % 2 == 1) ?
					TexBracketLevel.createPosition('{', document,
							offset + positions.getAt(i), 0, pos++ ) :
					new LinkedPosition(document,
							offset + positions.getAt(i), 0, pos++ );
			group.addPosition(position);
			linked.add(position);
			model.addGroup(group);
		}
		
		model.forceInstall();
		
		final TexBracketLevel level= new TexBracketLevel(model,
				document, context.getEditor().getDocumentContentInfo(),
				linked, BracketLevel.AUTODELETE );
		
		/* create UI */
		final LinkedModeUI ui= new LinkedModeUI(model, context.getSourceViewer());
		ui.setCyclingMode(LinkedModeUI.CYCLE_WHEN_NO_PARENT);
		ui.setExitPosition(context.getSourceViewer(), offset + positions.getAt(positions.size() - 1), 0, pos);
		ui.setSimpleMode(true);
		ui.setExitPolicy(level);
		return ui;
	}
	
	private void createLinkedVerbMode(final int offset) throws BadLocationException {
		final LtxAssistInvocationContext context= getInvocationContext();
		final IDocument document= context.getDocument();
		
		final LinkedSepMode mode= new LinkedSepMode(context.getSourceViewer(), document, offset);
		Display.getCurrent().asyncExec(new Runnable() {
			@Override
			public void run() {
				mode.install();
			}
		});
	}
	
}
