/*=============================================================================#
 # Copyright (c) 2008, 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.r.core.refactoring;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jface.text.AbstractDocument;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.osgi.util.NLS;
import org.eclipse.text.edits.TextEdit;

import org.eclipse.statet.jcommons.text.core.BasicTextRegion;
import org.eclipse.statet.jcommons.text.core.TextRegion;
import org.eclipse.statet.jcommons.text.core.input.StringParserInput;
import org.eclipse.statet.jcommons.text.core.input.TextParserInput;

import org.eclipse.statet.ecommons.text.IndentUtil;
import org.eclipse.statet.ecommons.text.core.PartitionConstraint;

import org.eclipse.statet.internal.r.core.refactoring.Messages;
import org.eclipse.statet.ltk.ast.core.AstInfo;
import org.eclipse.statet.ltk.ast.core.util.AstSelection;
import org.eclipse.statet.ltk.model.core.ModelManager;
import org.eclipse.statet.ltk.model.core.element.SourceUnit;
import org.eclipse.statet.ltk.model.core.element.SourceUnitModelInfo;
import org.eclipse.statet.ltk.refactoring.core.RefactoringAdapter;
import org.eclipse.statet.r.core.RCodeStyleSettings;
import org.eclipse.statet.r.core.RCore;
import org.eclipse.statet.r.core.RCoreAccess;
import org.eclipse.statet.r.core.model.RModel;
import org.eclipse.statet.r.core.model.RSourceUnit;
import org.eclipse.statet.r.core.rlang.RTerminal;
import org.eclipse.statet.r.core.rsource.RLexer;
import org.eclipse.statet.r.core.rsource.RSourceConstants;
import org.eclipse.statet.r.core.rsource.RSourceIndenter;
import org.eclipse.statet.r.core.rsource.ast.Assignment;
import org.eclipse.statet.r.core.rsource.ast.RAstNode;
import org.eclipse.statet.r.core.rsource.ast.RParser;
import org.eclipse.statet.r.core.rsource.ast.SourceComponent;
import org.eclipse.statet.r.core.source.RDocumentConstants;
import org.eclipse.statet.r.core.source.RHeuristicTokenScanner;


/**
 * RefactoringAdapter for R
 */
public class RRefactoringAdapter extends RefactoringAdapter {
	
	
	private RLexer lexer;
	
	
	public RRefactoringAdapter() {
		super(RModel.R_TYPE_ID);
	}
	
	
	@Override
	public String getPluginIdentifier() {
		return RCore.BUNDLE_ID;
	}
	
	@Override
	public RHeuristicTokenScanner getScanner(final SourceUnit su) {
		return RHeuristicTokenScanner.create(su.getDocumentContentInfo());
	}
	
	@Override
	public boolean isCommentContent(final ITypedRegion partition) {
		return (partition != null
				&& partition.getType() == RDocumentConstants.R_COMMENT_CONTENT_TYPE );
	}
	
	public TextRegion trimToAstRegion(final AbstractDocument document, final TextRegion region,
			final RHeuristicTokenScanner scanner) {
		scanner.configure(document, RDocumentConstants.R_CODE_CONTENT_CONSTRAINT);
		int start= region.getStartOffset();
		int stop= region.getEndOffset();
		int result;
		
		while (stop > start) {
			result= scanner.findNonBlankBackward(stop, start, true);
			if (result >= 0) {
				if (scanner.getChar() == ';') {
					stop= result;
					continue;
				}
				else {
					stop= result + 1;
					break;
				}
			}
			else {
				stop= start;
				break;
			}
		}
		
		while (start < stop) {
			result= scanner.findNonBlankForward(start, stop, true);
			if (result >= 0) {
				if (scanner.getChar() == ';') {
					start= result + 1;
					continue;
				}
				else {
					start= result;
					break;
				}
			}
			else {
				start= stop;
				break;
			}
		}
		
		return new BasicTextRegion(start, stop);
	}
	
	public RAstNode searchPotentialNameNode(final SourceUnit su, TextRegion region,
			final boolean allowAssignRegion, final IProgressMonitor monitor) {
		final SubMonitor m= SubMonitor.convert(monitor, 5);
		
		su.connect(m.newChild(1));
		try {
			final AbstractDocument document= su.getDocument(m.newChild(1));
			final RHeuristicTokenScanner scanner= getScanner(su);
			
			region= trimToAstRegion(document, region, scanner);
			
			final SourceUnitModelInfo modelInfo= su.getModelInfo(RModel.R_TYPE_ID,
					ModelManager.MODEL_FILE, m.newChild(1) );
			if (modelInfo != null) {
				final AstSelection astSelection= AstSelection.search(modelInfo.getAst().getRoot(),
						region.getStartOffset(), region.getEndOffset(),
						AstSelection.MODE_COVERING_SAME_LAST );
				if (astSelection.getCovering() instanceof RAstNode) {
					final RAstNode node= (RAstNode) astSelection.getCovering();
					return getPotentialNameNode(node, allowAssignRegion);
				}
			}
			return null;
		}
		finally {
			m.setWorkRemaining(1);
			su.disconnect(m.newChild(1));
		}
	}
	
	public TextRegion expandSelectionRegion(final AbstractDocument document, final TextRegion region,
			final TextRegion limit, final RHeuristicTokenScanner scanner) {
		scanner.configure(document, new PartitionConstraint() {
			@Override
			public boolean matches(final String partitionType) {
				return (partitionType != RDocumentConstants.R_COMMENT_CONTENT_TYPE);
			}
		});
		final int min= limit.getStartOffset();
		final int max= limit.getEndOffset();
		int start= region.getStartOffset();
		int end= region.getEndOffset();
		int result;
		
		while (start > min) {
			result= scanner.findNonBlankBackward(start, min, true);
			if (result >= 0) {
				if (RDocumentConstants.R_DEFAULT_CONTENT_CONSTRAINT.matches(scanner.getPartition(result).getType())
						&& scanner.getChar() == ';') {
					start= result;
					continue;
				}
				else {
					start= result + 1;
					break;
				}
			}
			else {
				start= min;
				break;
			}
		}
		
		while (end < max) {
			result= scanner.findNonBlankForward(end, max, true);
			if (result >= 0) {
				if (RDocumentConstants.R_DEFAULT_CONTENT_CONSTRAINT.matches(scanner.getPartition(result).getType())
						&& scanner.getChar() == ';') {
					end= result + 1;
					continue;
				}
				else {
					end= result;
					break;
				}
			}
			else {
				end= max;
				break;
			}
		}
		
		return new BasicTextRegion(start, end);
	}
	
	
	public String validateIdentifier(final String value, final String identifierMessageName) {
		if (value == null || value.isEmpty()) { 
			return (identifierMessageName != null) ?
					NLS.bind(Messages.RIdentifiers_error_EmptyFor_message, identifierMessageName, Messages.RIdentifiers_error_Empty_message) :
					Messages.RIdentifiers_error_Empty_message;
		}
		if (this.lexer == null) {
			this.lexer= new RLexer();
		}
		this.lexer.reset(new StringParserInput(value).init());
		final RTerminal nextToken= this.lexer.next();
		if (nextToken == RTerminal.EOF) {
			return (identifierMessageName != null) ?
					NLS.bind(Messages.RIdentifiers_error_EmptyFor_message, identifierMessageName, Messages.RIdentifiers_error_Empty_message) :
					Messages.RIdentifiers_error_Empty_message;
		}
		if ((nextToken != RTerminal.SYMBOL && nextToken != RTerminal.SYMBOL_G)
				|| ((this.lexer.getFlags() & RSourceConstants.STATUSFLAG_REAL_ERROR) != 0)
				|| (this.lexer.next() != RTerminal.EOF)) {
			return (identifierMessageName != null) ?
					NLS.bind(Messages.RIdentifiers_error_InvalidFor_message, identifierMessageName, Messages.RIdentifiers_error_Empty_message) :
					Messages.RIdentifiers_error_Invalid_message;
		}
		return null;
	}
	
	static RAstNode getPotentialNameNode(final RAstNode node, final boolean allowAssignRegion) {
		switch (node.getNodeType()) {
		case A_LEFT:
		case A_RIGHT:
		case A_EQUALS:
		case A_COLON:
			if (allowAssignRegion) {
				final Assignment assignment= (Assignment) node;
				if (assignment.isSearchOperator()) {
					switch (assignment.getTargetChild().getNodeType()) {
					case SYMBOL:
					case STRING_CONST:
						return assignment.getTargetChild();
					default:
						break;
					}
				}
			}
			return null;
		case SYMBOL:
		case STRING_CONST:
			return node;
		default:
			return null;
		}
	}
	
	public static String getQuotedIdentifier(final String identifier) {
		int length;
		if (identifier == null || (length= identifier.length()) == 0) {
			return "";
		}
		if (identifier.charAt(0) == '`') {
			if (length > 1 && identifier.charAt(length - 1) == '`') {
				return identifier;
			}
			else {
				return identifier + '`';
			}
		}
		else {
			return '`' + identifier + '`';
		}
	}
	
	public static String getUnquotedIdentifier(final String identifier) {
		int length;
		if (identifier == null || (length= identifier.length()) == 0) {
			return "";
		}
		if (identifier.charAt(0) == '`') {
			if (length > 1 && identifier.charAt(length - 1) == '`') {
				return identifier.substring(1, length - 2);
			}
			else {
				return identifier.substring(1, length - 1);
			}
		}
		else {
			return identifier;
		}
	}
	
	static String indent(final StringBuilder sb, final AbstractDocument orgDoc, final int offset,
			final SourceUnit su, final RHeuristicTokenScanner scanner) throws BadLocationException, CoreException {
		final RCoreAccess coreConfig= (su instanceof RSourceUnit) ? ((RSourceUnit)su).getRCoreAccess() : RCore.getWorkbenchAccess();
		
		final IndentUtil indentUtil= new IndentUtil(orgDoc, coreConfig.getRCodeStyle());
		final int column= indentUtil.getColumn(offset);
		final String initial= indentUtil.createIndentString(column);
		final String prefix= initial + "1\n"; //$NON-NLS-1$
		sb.insert(0, prefix);
		String text= sb.toString();
		final Document doc= new Document(text);
		final TextParserInput parseInput= new StringParserInput(text);
		text= null;
		
		final RParser rParser= new RParser(AstInfo.LEVEL_MINIMAL);
		final SourceComponent rootNode= rParser.scanSourceUnit(parseInput.init());
		
		final RSourceIndenter indenter= new RSourceIndenter(scanner, coreConfig);
		final TextEdit edits= indenter.getIndentEdits(doc, rootNode, 0, 1, doc.getNumberOfLines() - 1);
		edits.apply(doc, 0);
		return doc.get(prefix.length(), doc.getLength() - prefix.length());
	}
	
	/**
	 * Prepare the insertion of a command (text) before another command (offset)
	 * 
	 * The method prepares the insertion by modifying the text and returning the offset
	 * where to insert the modified text
	 * 
	 * @param text the command to insert, will be modified
	 * @param orgDoc the document
	 * @param offset the offset where to insert the command
	 * @param su the source unit, if available
	 * @return the offset to insert the modified text
	 * @throws BadLocationException
	 * @throws CoreException
	 */
	static int prepareInsertBefore(final StringBuilder text, final AbstractDocument orgDoc, final int offset,
			final SourceUnit su) throws BadLocationException, CoreException {
		final RCoreAccess coreConfig= (su instanceof RSourceUnit) ? ((RSourceUnit)su).getRCoreAccess() : RCore.getWorkbenchAccess();
		
		final IndentUtil indentUtil= new IndentUtil(orgDoc, coreConfig.getRCodeStyle());
		final int line= orgDoc.getLineOfOffset(offset);
		final int[] lineIndent= indentUtil.getLineIndent(line, false);
		if (lineIndent[IndentUtil.OFFSET_IDX] == offset) { // first char/command in line
			text.insert(0, indentUtil.createIndentString(lineIndent[IndentUtil.COLUMN_IDX]));
			text.append(orgDoc.getDefaultLineDelimiter());
			return orgDoc.getLineOffset(line);
		}
		else {
			text.append("; "); //$NON-NLS-1$
			return offset;
		}
	}
	
	static RCodeStyleSettings getCodeStyle(final SourceUnit su) {
		if (su instanceof RSourceUnit) {
			return ((RSourceUnit)su).getRCoreAccess().getRCodeStyle();
		}
		return RCore.getWorkbenchAccess().getRCodeStyle();
	}
	
}
