/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * This is an implementation of an early-draft specification developed under the Java
 * Community Process (JCP) and is made available for testing and evaluation purposes
 * only. The code is not compatible with any specification of the JCP.
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Nikolay Metchev - Fixed https://bugs.eclipse.org/bugs/show_bug.cgi?id=29909
 *     Tom Eicher (Avaloq Evolution AG) - block selection mode
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.text.java;

import org.eclipse.core.runtime.Assert;

import org.eclipse.jface.preference.IPreferenceStore;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.DocumentCommand;
import org.eclipse.jface.text.DocumentRewriteSession;
import org.eclipse.jface.text.DocumentRewriteSessionType;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITypedRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jface.text.rules.FastPartitioner;
import org.eclipse.jface.text.source.ISourceViewer;

import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;

import org.eclipse.ui.texteditor.ITextEditorExtension3;

import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.compiler.IScanner;
import org.eclipse.jdt.core.compiler.ITerminalSymbols;
import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.DoStatement;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ForStatement;
import org.eclipse.jdt.core.dom.IfStatement;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.WhileStatement;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;

import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil;

import org.eclipse.jdt.ui.PreferenceConstants;
import org.eclipse.jdt.ui.text.IJavaPartitions;

import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.corext.dom.IASTSharedValues;
import org.eclipse.jdt.internal.ui.javaeditor.EditorUtility;
import org.eclipse.jdt.internal.ui.text.FastJavaPartitionScanner;
import org.eclipse.jdt.internal.ui.text.FastJavaPartitioner;
import org.eclipse.jdt.internal.ui.text.JavaHeuristicScanner;
import org.eclipse.jdt.internal.ui.text.JavaIndenter;
import org.eclipse.jdt.internal.ui.text.Symbols;


/**
 * Auto indent strategy sensitive to brackets.
 */
public class JavaAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy {

	/** The line comment introducer. Value is "{@value}" */
	private static final String LINE_COMMENT= "//"; //$NON-NLS-1$

		private static class CompilationUnitInfo {

			char[] buffer;
			int delta;

			CompilationUnitInfo(char[] buffer, int delta) {
				this.buffer= buffer;
				this.delta= delta;
			}
		}


	private boolean fCloseBrace;
	private boolean fIsSmartMode;
	private boolean fIsSmartTab;
	private boolean fIsSmartIndentAfterNewline;

	private String fPartitioning;
	private final IJavaProject fProject;
	private static IScanner fgScanner= ToolFactory.createScanner(false, false, false, false);
	/**
	 * The viewer.
	 * @since 3.5
	 */
	private final ISourceViewer fViewer;

	/**
	 * Creates a new Java auto indent strategy for the given document partitioning.
	 *
	 * @param partitioning the document partitioning
	 * @param project the project to get formatting preferences from, or null to use default preferences
	 * @param viewer the source viewer that this strategy is attached to
	 */
	public JavaAutoIndentStrategy(String partitioning, IJavaProject project, ISourceViewer viewer) {
		fPartitioning= partitioning;
		fProject= project;
		fViewer= viewer;
 	}

	private int getBracketCount(IDocument d, int startOffset, int endOffset, boolean ignoreCloseBrackets) throws BadLocationException {

		int bracketCount= 0;
		while (startOffset < endOffset) {
			char curr= d.getChar(startOffset);
			startOffset++;
			switch (curr) {
				case '/' :
					if (startOffset < endOffset) {
						char next= d.getChar(startOffset);
						if (next == '*') {
							// a comment starts, advance to the comment end
							startOffset= getCommentEnd(d, startOffset + 1, endOffset);
						} else if (next == '/') {
							// '//'-comment: nothing to do anymore on this line
							startOffset= endOffset;
						}
					}
					break;
				case '*' :
					if (startOffset < endOffset) {
						char next= d.getChar(startOffset);
						if (next == '/') {
							// we have been in a comment: forget what we read before
							bracketCount= 0;
							startOffset++;
						}
					}
					break;
				case '{' :
					bracketCount++;
					ignoreCloseBrackets= false;
					break;
				case '}' :
					if (!ignoreCloseBrackets) {
						bracketCount--;
					}
					break;
				case '"' :
				case '\'' :
					startOffset= getStringEnd(d, startOffset, endOffset, curr);
					break;
				default :
					}
		}
		return bracketCount;
	}

	// ----------- bracket counting ------------------------------------------------------

	private int getCommentEnd(IDocument d, int offset, int endOffset) throws BadLocationException {
		while (offset < endOffset) {
			char curr= d.getChar(offset);
			offset++;
			if (curr == '*') {
				if (offset < endOffset && d.getChar(offset) == '/') {
					return offset + 1;
				}
			}
		}
		return endOffset;
	}

	private String getIndentOfLine(IDocument d, int line) throws BadLocationException {
		if (line > -1) {
			int start= d.getLineOffset(line);
			int end= start + d.getLineLength(line) - 1;
			int whiteEnd= findEndOfWhiteSpace(d, start, end);
			return d.get(start, whiteEnd - start);
		} else {
			return ""; //$NON-NLS-1$
		}
	}

	private int getStringEnd(IDocument d, int offset, int endOffset, char ch) throws BadLocationException {
		while (offset < endOffset) {
			char curr= d.getChar(offset);
			offset++;
			if (curr == '\\') {
				// ignore escaped characters
				offset++;
			} else if (curr == ch) {
				return offset;
			}
		}
		return endOffset;
	}

	private void smartIndentAfterClosingBracket(IDocument d, DocumentCommand c) {
		if (c.offset == -1 || d.getLength() == 0)
			return;

		try {
			int p= (c.offset == d.getLength() ? c.offset - 1 : c.offset);
			int line= d.getLineOfOffset(p);
			int start= d.getLineOffset(line);
			int whiteend= findEndOfWhiteSpace(d, start, c.offset);

			JavaHeuristicScanner scanner= new JavaHeuristicScanner(d);
			JavaIndenter indenter= new JavaIndenter(d, scanner, fProject);

			// shift only when line does not contain any text up to the closing bracket
			if (whiteend == c.offset) {
				// evaluate the line with the opening bracket that matches out closing bracket
				int reference= indenter.findReferencePosition(c.offset, false, true, false, false);
				int indLine= d.getLineOfOffset(reference);
				if (indLine != -1 && indLine != line) {
					// take the indent of the found line
					StringBuilder replaceText= new StringBuilder(getIndentOfLine(d, indLine));
					// add the rest of the current line including the just added close bracket
					replaceText.append(d.get(whiteend, c.offset - whiteend));
					replaceText.append(c.text);
					// modify document command
					c.length += c.offset - start;
					c.offset= start;
					c.text= replaceText.toString();
				}
			}
		} catch (BadLocationException e) {
			JavaPlugin.log(e);
		}
	}

	private void smartIndentAfterOpeningBracket(IDocument d, DocumentCommand c) {
		if (c.offset < 1 || d.getLength() == 0)
			return;

		JavaHeuristicScanner scanner= new JavaHeuristicScanner(d);

		int p= (c.offset == d.getLength() ? c.offset - 1 : c.offset);

		try {
			// current line
			int line= d.getLineOfOffset(p);
			int lineOffset= d.getLineOffset(line);

			// make sure we don't have any leading comments etc.
			if (d.get(lineOffset, p - lineOffset).trim().length() != 0)
				return;

			// line of last Java code
			int pos= scanner.findNonWhitespaceBackward(p, JavaHeuristicScanner.UNBOUND);
			if (pos == -1)
				return;
			int lastLine= d.getLineOfOffset(pos);

			// only shift if the last java line is further up and is a braceless block candidate
			if (lastLine < line) {

				JavaIndenter indenter= new JavaIndenter(d, scanner, fProject);
				StringBuffer indent= indenter.computeIndentation(p, true);
				String toDelete= d.get(lineOffset, c.offset - lineOffset);
				if (indent != null && !indent.toString().equals(toDelete)) {
					c.text= indent.append(c.text).toString();
					c.length += c.offset - lineOffset;
					c.offset= lineOffset;
				}
			}

		} catch (BadLocationException e) {
			JavaPlugin.log(e);
		}

	}

	private void smartIndentAfterNewLine(IDocument d, DocumentCommand c) {
		JavaHeuristicScanner scanner= new JavaHeuristicScanner(d);
		JavaIndenter indenter= new JavaIndenter(d, scanner, fProject);
		StringBuffer indent= indenter.computeIndentation(c.offset);
		if (indent == null)
			indent= new StringBuffer();

		int docLength= d.getLength();
		if (c.offset == -1 || docLength == 0)
			return;

		try {
			int p= (c.offset == docLength ? c.offset - 1 : c.offset);
			int line= d.getLineOfOffset(p);

			StringBuilder buf= new StringBuilder(c.text + indent);


			IRegion reg= d.getLineInformation(line);
			int lineEnd= reg.getOffset() + reg.getLength();

			int contentStart= findEndOfWhiteSpace(d, c.offset, lineEnd);
			c.length=  Math.max(contentStart - c.offset, 0);

			int start= reg.getOffset();
			ITypedRegion region= TextUtilities.getPartition(d, fPartitioning, start, true);
			if (IJavaPartitions.JAVA_DOC.equals(region.getType()))
				start= d.getLineInformationOfOffset(region.getOffset()).getOffset();

			// insert closing brace on new line after an unclosed opening brace
			if (getBracketCount(d, start, c.offset, true) > 0 && closeBrace() && !isClosed(d, c.offset, c.length)) {
				c.caretOffset= c.offset + buf.length();
				c.shiftsCaret= false;

				int pos= c.offset - 1;
				char ch= d.getChar(pos);
				while (ch == ' ' || ch == '\t') {
					pos--;
					ch= d.getChar(pos);
				}
				// copy old content of line behind insertion point to new line
				// unless we think we are inserting an anonymous type definition

				if (c.offset == 0 || copyContent(d, pos + 1, fPartitioning, lineEnd)) {
					if (lineEnd - contentStart > 0) {
						c.length=  lineEnd - c.offset;
						buf.append(d.get(contentStart, lineEnd - contentStart).toCharArray());
					}
				}

				buf.append(TextUtilities.getDefaultLineDelimiter(d));
				StringBuffer reference= null;
				int nonWS= findEndOfWhiteSpace(d, start, lineEnd);
				if (nonWS < c.offset && d.getChar(nonWS) == '{')
					reference= new StringBuffer(d.get(start, nonWS - start));
				else
					reference= indenter.getReferenceIndentation(c.offset);
				if (reference != null)
					buf.append(reference);
				buf.append('}');
			}
			// insert extra line upon new line between two braces
			else if (c.offset > start && contentStart < lineEnd && d.getChar(contentStart) == '}') {
				int firstCharPos= scanner.findNonWhitespaceBackward(c.offset - 1, start);
				if (firstCharPos != JavaHeuristicScanner.NOT_FOUND && d.getChar(firstCharPos) == '{') {
					c.caretOffset= c.offset + buf.length();
					c.shiftsCaret= false;

					StringBuffer reference= null;
					int nonWS= findEndOfWhiteSpace(d, start, lineEnd);
					if (nonWS < c.offset && d.getChar(nonWS) == '{')
						reference= new StringBuffer(d.get(start, nonWS - start));
					else
						reference= indenter.getReferenceIndentation(c.offset);

					buf.append(TextUtilities.getDefaultLineDelimiter(d));

					if (reference != null)
						buf.append(reference);
				}
			}
			c.text= buf.toString();

		} catch (BadLocationException e) {
			JavaPlugin.log(e);
		}
	}

	/**
	 * Checks if it is required to copy the old content of the line after caret position to new line
	 * before inserting the closing brace.
	 *
	 * @param document the document being modified
	 * @param offset the offset of the caret position, relative to the line start.
	 * @param partitioning the document partitioning
	 * @param max the max position
	 * @return <code>true</code> if the old content of the line after caret position has to be
	 *         copied to new line before inserting the closing brace, <code>false</code> otherwise
	 */
	private boolean copyContent(IDocument document, int offset, String partitioning, int max) {
		// find the opening parenthesis for every closing parenthesis on the current line after offset
		// return true if it looks like a method declaration
		// or an expression for an if, while, for, catch statement

		JavaHeuristicScanner scanner= new JavaHeuristicScanner(document);
		int pos= offset;
		int length= max;
		int scanTo= scanner.scanForward(pos, length, '}');
		if (scanTo == -1)
			scanTo= length;

		int closingParen= findClosingParenToLeft(scanner, pos) - 1;
		int openingParen= -1;
		while (true) {
			int startScan= closingParen + 1;
			closingParen= scanner.scanForward(startScan, scanTo, ')');
			if (closingParen == -1) {
				if (openingParen != -1)
					return false;
				try {
					int p= findEndOfWhiteSpace(document, pos, scanTo);
					char ch= document.getChar(p);
					if (ch == ',' || ch == ';')
						return false;
				} catch (BadLocationException e) {
					// ignore
				}
				break;
			}

			openingParen= scanner.findOpeningPeer(closingParen - 1, '(', ')');

			// no way an expression at the beginning of the document can mean anything
			if (openingParen < 1)
				break;

			// only select insert positions for parenthesis currently embracing the caret
			if (openingParen > pos) {
				openingParen= -1;
				continue;
			}

			if (looksLikeAnonymousClassDef(document, partitioning, scanner, openingParen - 1))
				return false;
		}

		return true;
	}

	/**
	 * Finds a closing parenthesis to the left of <code>position</code> in document, where that parenthesis is only
	 * separated by whitespace from <code>position</code>. If no such parenthesis can be found, <code>position</code> is returned.
	 *
	 * @param scanner the java heuristic scanner set up on the document
	 * @param position the first character position in <code>document</code> to be considered
	 * @return the position of a closing parenthesis left to <code>position</code> separated only by whitespace, or <code>position</code> if no parenthesis can be found
	 */
	private static int findClosingParenToLeft(JavaHeuristicScanner scanner, int position) {
		if (position < 1)
			return position;

		if (scanner.previousToken(position - 1, JavaHeuristicScanner.UNBOUND) == Symbols.TokenRPAREN)
			return scanner.getPosition() + 1;
		return position;
	}

	/**
	 * Checks whether the content of <code>document</code> in the range (<code>offset</code>, <code>length</code>)
	 * contains the <code>new</code> keyword.
	 *
	 * @param document the document being modified
	 * @param offset the first character position in <code>document</code> to be considered
	 * @param length the length of the character range to be considered
	 * @param partitioning the document partitioning
	 * @return <code>true</code> if the specified character range contains a <code>new</code> keyword, <code>false</code> otherwise.
	 */
	private static boolean isNewMatch(IDocument document, int offset, int length, String partitioning) {
		Assert.isTrue(length >= 0);
		Assert.isTrue(offset >= 0);
		Assert.isTrue(offset + length < document.getLength() + 1);

		try {
			String text= document.get(offset, length);
			int pos= text.indexOf("new"); //$NON-NLS-1$

			while (pos != -1 && !isDefaultPartition(document, pos + offset, partitioning))
				pos= text.indexOf("new", pos + 2); //$NON-NLS-1$

			if (pos < 0)
				return false;

			if (pos != 0 && Character.isJavaIdentifierPart(text.charAt(pos - 1)))
				return false;

			if (pos + 3 < length && Character.isJavaIdentifierPart(text.charAt(pos + 3)))
				return false;

			return true;

		} catch (BadLocationException e) {
		}
		return false;
	}

	/**
	 * Checks whether the content of <code>document</code> at <code>position</code> looks like an
	 * anonymous class definition. <code>position</code> must be to the left of the opening
	 * parenthesis of the definition's parameter list.
	 *
	 * @param document the document being modified
	 * @param partitioning the document partitioning
	 * @param scanner the scanner
	 * @param position the first character position in <code>document</code> to be considered
	 * @return <code>true</code> if the content of <code>document</code> looks like an anonymous class definition, <code>false</code> otherwise
	 */
	private static boolean looksLikeAnonymousClassDef(IDocument document, String partitioning, JavaHeuristicScanner scanner, int position) {
		int previousCommaParenEqual= scanner.scanBackward(position - 1, JavaHeuristicScanner.UNBOUND, new char[] {',', '(', '='});
		if (previousCommaParenEqual == -1 || position < previousCommaParenEqual + 5) // 2 for borders, 3 for "new"
			return false;

		if (isNewMatch(document, previousCommaParenEqual + 1, position - previousCommaParenEqual - 2, partitioning))
			return true;

		return false;
	}

	/**
	 * Checks whether <code>position</code> resides in a default (Java) partition of <code>document</code>.
	 *
	 * @param document the document being modified
	 * @param position the position to be checked
	 * @param partitioning the document partitioning
	 * @return <code>true</code> if <code>position</code> is in the default partition of <code>document</code>, <code>false</code> otherwise
	 */
	private static boolean isDefaultPartition(IDocument document, int position, String partitioning) {
		Assert.isTrue(position >= 0);
		Assert.isTrue(position <= document.getLength());

		try {
			ITypedRegion region= TextUtilities.getPartition(document, partitioning, position, false);
			return region.getType().equals(IDocument.DEFAULT_CONTENT_TYPE);

		} catch (BadLocationException e) {
		}

		return false;
	}

	private boolean isClosed(IDocument document, int offset, int length) {

		CompilationUnitInfo info= getCompilationUnitForMethod(document, offset);
		if (info == null)
			return false;

		CompilationUnit compilationUnit= null;
		try {
			ASTParser parser= ASTParser.newParser(IASTSharedValues.SHARED_AST_LEVEL);
			parser.setSource(info.buffer);
			compilationUnit= (CompilationUnit) parser.createAST(null);
		} catch (ArrayIndexOutOfBoundsException x) {
			// work around for parser problem
			return false;
		}

		IProblem[] problems= compilationUnit.getProblems();
		for (int i= 0; i != problems.length; ++i) {
			if (problems[i].getID() == IProblem.UnmatchedBracket)
				return true;
		}

		final int relativeOffset= offset - info.delta;

		ASTNode node= NodeFinder.perform(compilationUnit, relativeOffset, length);

		if (length == 0) {
			while (node != null && (relativeOffset == node.getStartPosition() || relativeOffset == node.getStartPosition() + node.getLength()))
				node= node.getParent();
		}

		if (node == null)
			return false;

		switch (node.getNodeType()) {
			case ASTNode.BLOCK:
				return getBlockBalance(document, offset, fPartitioning) <= 0;

			case ASTNode.IF_STATEMENT:
			{
				IfStatement ifStatement= (IfStatement) node;
				Expression expression= ifStatement.getExpression();
				IRegion expressionRegion= createRegion(expression, info.delta);
				Statement thenStatement= ifStatement.getThenStatement();
				IRegion thenRegion= createRegion(thenStatement, info.delta);

				// between expression and then statement
				if (expressionRegion.getOffset() + expressionRegion.getLength() <= offset && offset + length <= thenRegion.getOffset())
					return thenStatement != null;

				Statement elseStatement= ifStatement.getElseStatement();
				IRegion elseRegion= createRegion(elseStatement, info.delta);

				if (elseStatement != null) {
					int sourceOffset= thenRegion.getOffset() + thenRegion.getLength();
					int sourceLength= elseRegion.getOffset() - sourceOffset;
					IRegion elseToken= getToken(document, new Region(sourceOffset, sourceLength), ITerminalSymbols.TokenNameelse);
					return elseToken != null && elseToken.getOffset() + elseToken.getLength() <= offset && offset + length < elseRegion.getOffset();
				}
			}
			break;

			case ASTNode.WHILE_STATEMENT:
			case ASTNode.FOR_STATEMENT:
			{
				Expression expression= node.getNodeType() == ASTNode.WHILE_STATEMENT ? ((WhileStatement) node).getExpression() : ((ForStatement) node).getExpression();
				IRegion expressionRegion= createRegion(expression, info.delta);
				Statement body= node.getNodeType() == ASTNode.WHILE_STATEMENT ? ((WhileStatement) node).getBody() : ((ForStatement) node).getBody();
				IRegion bodyRegion= createRegion(body, info.delta);

				// between expression and body statement
				if (expressionRegion.getOffset() + expressionRegion.getLength() <= offset && offset + length <= bodyRegion.getOffset())
					return body != null;
			}
			break;

			case ASTNode.DO_STATEMENT:
			{
				DoStatement doStatement= (DoStatement) node;
				IRegion doRegion= createRegion(doStatement, info.delta);
				Statement body= doStatement.getBody();
				IRegion bodyRegion= createRegion(body, info.delta);

				if (doRegion.getOffset() + doRegion.getLength() <= offset && offset + length <= bodyRegion.getOffset())
					return body != null;
			}
			break;
		}

		return true;
	}

	/**
	 * Installs a java partitioner with <code>document</code>.
	 *
	 * @param document the document
	 */
	private void installJavaStuff(Document document) {
		String[] types= new String[] {
									  IJavaPartitions.JAVA_DOC,
									  IJavaPartitions.JAVA_MULTI_LINE_COMMENT,
									  IJavaPartitions.JAVA_SINGLE_LINE_COMMENT,
									  IJavaPartitions.JAVA_STRING,
									  IJavaPartitions.JAVA_CHARACTER,
									  IJavaPartitions.JAVA_MULTI_LINE_STRING,
									  IDocument.DEFAULT_CONTENT_TYPE
		};
		FastPartitioner partitioner= new FastJavaPartitioner(new FastJavaPartitionScanner(fProject), types);
		partitioner.connect(document);
		document.setDocumentPartitioner(IJavaPartitions.JAVA_PARTITIONING, partitioner);
	}

	/**
	 * Installs a java partitioner with <code>document</code>.
	 *
	 * @param document the document
	 */
	private static void removeJavaStuff(Document document) {
		document.setDocumentPartitioner(IJavaPartitions.JAVA_PARTITIONING, null);
	}

	private void smartPaste(IDocument document, DocumentCommand command) {
		int newOffset= command.offset;
		int newLength= command.length;
		String newText= command.text;

		try {
			JavaHeuristicScanner scanner= new JavaHeuristicScanner(document);
			JavaIndenter indenter= new JavaIndenter(document, scanner, fProject);
			int offset= newOffset;

			// reference position to get the indent from
			int refOffset= indenter.findReferencePosition(offset);
			if (refOffset == JavaHeuristicScanner.NOT_FOUND)
				return;
			int peerOffset= getPeerPosition(document, command);
			peerOffset= indenter.findReferencePosition(peerOffset);
			if (peerOffset != JavaHeuristicScanner.NOT_FOUND)
				refOffset= Math.min(refOffset, peerOffset);

			// eat any WS before the insertion to the beginning of the line
			int firstLine= 1; // don't format the first line per default, as it has other content before it
			IRegion line= document.getLineInformationOfOffset(offset);
			String notSelected= document.get(line.getOffset(), offset - line.getOffset());
			if (notSelected.trim().length() == 0) {
				newLength += notSelected.length();
				newOffset= line.getOffset();
				firstLine= 0;
			}

			// prefix: the part we need for formatting but won't paste
			IRegion refLine= document.getLineInformationOfOffset(refOffset);
			String prefix= document.get(refLine.getOffset(), newOffset - refLine.getOffset());

			// handle the indentation computation inside a temporary document
			Document temp= new Document(prefix + newText);
			DocumentRewriteSession session= temp.startRewriteSession(DocumentRewriteSessionType.STRICTLY_SEQUENTIAL);
			scanner= new JavaHeuristicScanner(temp);
			indenter= new JavaIndenter(temp, scanner, fProject);
			installJavaStuff(temp);

			// indent the first and second line
			// compute the relative indentation difference from the second line
			// (as the first might be partially selected) and use the value to
			// indent all other lines.
			boolean isIndentDetected= false;
			StringBuffer addition= new StringBuffer();
			int insertLength= 0;
			int firstLineInsertLength= 0;
			int firstLineIndent= 0;
			int first= document.computeNumberOfLines(prefix) + firstLine; // don't format first line
			int lines= temp.getNumberOfLines();
			int tabLength= getVisualTabLengthPreference();
			boolean changed= false;
			for (int l= first; l < lines; l++) { // we don't change the number of lines while adding indents

				IRegion r= temp.getLineInformation(l);
				int lineOffset= r.getOffset();
				int lineLength= r.getLength();

				if (lineLength == 0) // don't modify empty lines
					continue;

				if (!isIndentDetected) {

					// indent the first pasted line
					String current= getCurrentIndent(temp, l);
					StringBuffer correct= indenter.computeIndentation(lineOffset);
					if (correct == null)
						return; // bail out

					insertLength= subtractIndent(correct, current, addition, tabLength);
					if (l == first) {
						firstLineInsertLength= insertLength;
						firstLineIndent= current.length();
					}
					if (l != first && temp.get(lineOffset, lineLength).trim().length() != 0) {
						isIndentDetected= true;
						if (firstLineIndent >= current.length())
							insertLength= firstLineInsertLength;
						if (insertLength == 0) {
							 // no adjustment needed, bail out
							if (firstLine == 0) {
								// but we still need to adjust the first line
								command.offset= newOffset;
								command.length= newLength;
								if (changed)
									break; // still need to get the leading indent of the first line
							}
							return;
						}
					} else {
						changed= insertLength != 0;
					}
				}

				// relatively indent all pasted lines
				if (insertLength > 0)
					addIndent(temp, l, addition, tabLength);
				else if (insertLength < 0)
					cutIndent(temp, l, -insertLength, tabLength);

			}

			removeJavaStuff(temp);
			temp.stopRewriteSession(session);
			newText= temp.get(prefix.length(), temp.getLength() - prefix.length());

			command.offset= newOffset;
			command.length= newLength;
			command.text= newText;

		} catch (BadLocationException e) {
			JavaPlugin.log(e);
		}

	}

	/**
	 * Returns the indentation of the line <code>line</code> in <code>document</code>.
	 * The returned string may contain pairs of leading slashes that are considered
	 * part of the indentation. The space before the asterisk in a javadoc-like
	 * comment is not considered part of the indentation.
	 *
	 * @param document the document
	 * @param line the line
	 * @return the indentation of <code>line</code> in <code>document</code>
	 * @throws BadLocationException if the document is changed concurrently
	 */
	private static String getCurrentIndent(Document document, int line) throws BadLocationException {
		IRegion region= document.getLineInformation(line);
		int from= region.getOffset();
		int endOffset= region.getOffset() + region.getLength();

		// go behind line comments
		int to= from;
		while (to < endOffset - 2 && document.get(to, 2).equals(LINE_COMMENT))
			to += 2;

		while (to < endOffset) {
			char ch= document.getChar(to);
			if (!Character.isWhitespace(ch))
				break;
			to++;
		}

		// don't count the space before javadoc like, asterisk-style comment lines
		if (to > from && to < endOffset - 1 && document.get(to - 1, 2).equals(" *")) { //$NON-NLS-1$
			String type= TextUtilities.getContentType(document, IJavaPartitions.JAVA_PARTITIONING, to, true);
			if (type.equals(IJavaPartitions.JAVA_DOC) || type.equals(IJavaPartitions.JAVA_MULTI_LINE_COMMENT))
				to--;
		}

		return document.get(from, to - from);
	}

	/**
	 * Computes the difference of two indentations and returns the difference in
	 * length of current and correct. If the return value is positive, <code>addition</code>
	 * is initialized with a substring of that length of <code>correct</code>.
	 *
	 * @param correct the correct indentation
	 * @param current the current indentation (might contain non-whitespace)
	 * @param difference a string buffer - if the return value is positive, it will be cleared and set to the substring of <code>current</code> of that length
	 * @param tabLength the length of a tab
	 * @return the difference in length of <code>correct</code> and <code>current</code>
	 */
	private int subtractIndent(CharSequence correct, CharSequence current, StringBuffer difference, int tabLength) {
		int c1= computeVisualLength(correct, tabLength);
		int c2= computeVisualLength(current, tabLength);
		int diff= c1 - c2;
		if (diff <= 0)
			return diff;

		difference.setLength(0);
		int len= 0, i= 0;
		while (len < diff) {
			char c= correct.charAt(i++);
			difference.append(c);
			len += computeVisualLength(c, tabLength);
		}


		return diff;
	}

	/**
	 * Indents line <code>line</code> in <code>document</code> with <code>indent</code>.
	 * Leaves leading comment signs alone.
	 *
	 * @param document the document
	 * @param line the line
	 * @param indent the indentation to insert
	 * @param tabLength the length of a tab
	 * @throws BadLocationException on concurrent document modification
	 */
	private void addIndent(Document document, int line, CharSequence indent, int tabLength) throws BadLocationException {
		IRegion region= document.getLineInformation(line);
		int insert= region.getOffset();
		int endOffset= region.getOffset() + region.getLength();

		// Compute insert after all leading line comment markers
		int newInsert= insert;
		while (newInsert < endOffset - 2 && document.get(newInsert, 2).equals(LINE_COMMENT))
			newInsert += 2;

		// Heuristic to check whether it is commented code or just a comment
		if (newInsert > insert) {
			int whitespaceCount= 0;
			int i= newInsert;
			while (i < endOffset - 1) {
				 char ch= document.get(i, 1).charAt(0);
				 if (!Character.isWhitespace(ch))
					 break;
				 whitespaceCount= whitespaceCount + computeVisualLength(ch, tabLength);
				 i++;
			}

			if (whitespaceCount != 0 && whitespaceCount >= CodeFormatterUtil.getIndentWidth(fProject))
				insert= newInsert;
		}

		// Insert indent
		document.replace(insert, 0, indent.toString());
	}

	/**
	 * Cuts the visual equivalent of <code>toDelete</code> characters out of the
	 * indentation of line <code>line</code> in <code>document</code>. Leaves
	 * leading comment signs alone.
	 *
	 * @param document the document
	 * @param line the line
	 * @param toDelete the number of space equivalents to delete
	 * @param tabLength the length of a tab
	 * @throws BadLocationException on concurrent document modification
	 */
	private void cutIndent(Document document, int line, int toDelete, int tabLength) throws BadLocationException {
		IRegion region= document.getLineInformation(line);
		int from= region.getOffset();
		int endOffset= region.getOffset() + region.getLength();

		// go behind line comments
		while (from < endOffset - 2 && document.get(from, 2).equals(LINE_COMMENT))
			from += 2;

		int to= from;
		while (toDelete > 0 && to < endOffset) {
			char ch= document.getChar(to);
			if (!Character.isWhitespace(ch))
				break;
			toDelete -= computeVisualLength(ch, tabLength);
			if (toDelete >= 0)
				to++;
			else
				break;
		}

		document.replace(from, to - from, ""); //$NON-NLS-1$
	}

	/**
	 * Returns the visual length of a given <code>CharSequence</code> taking into
	 * account the visual tabulator length.
	 *
	 * @param seq the string to measure
	 * @param tabLength the length of a tab
	 * @return the visual length of <code>seq</code>
	 */
	private int computeVisualLength(CharSequence seq, int tabLength) {
		int size= 0;

		for (int i= 0; i < seq.length(); i++) {
			char ch= seq.charAt(i);
			if (ch == '\t') {
				if (tabLength != 0)
					size += tabLength - size % tabLength;
				// else: size stays the same
			} else {
				size++;
			}
		}
		return size;
	}

	/**
	 * Returns the visual length of a given character taking into
	 * account the visual tabulator length.
	 *
	 * @param ch the character to measure
	 * @param tabLength the length of a tab
	 * @return the visual length of <code>ch</code>
	 */
	private int computeVisualLength(char ch, int tabLength) {
		if (ch == '\t')
			return tabLength;
		else
			return 1;
	}

	/**
	 * The preference setting for the visual tabulator display.
	 *
	 * @return the number of spaces displayed for a tabulator in the editor
	 */
	private int getVisualTabLengthPreference() {
		return CodeFormatterUtil.getTabWidth(fProject);
	}

	/**
	 * The preference setting that tells whether to insert spaces when pressing the Tab key.
	 *
	 * @return <code>true</code> if spaces are inserted when pressing the Tab key
	 * @since 3.5
	 */
	private boolean isInsertingSpacesForTab() {
		return JavaCore.SPACE.equals(getCoreOption(fProject, DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR));
	}

	/**
	 * Returns the possibly <code>project</code>-specific core preference defined under
	 * <code>key</code>.
	 *
	 * @param project the project to get the preference from, or <code>null</code> to get the global
	 *            preference
	 * @param key the key of the preference
	 * @return the value of the preference
	 * @since 3.5
	 */
	private static String getCoreOption(IJavaProject project, String key) {
		if (project == null)
			return JavaCore.getOption(key);
		return project.getOption(key, true);
	}

	private int getPeerPosition(IDocument document, DocumentCommand command) {
		if (document.getLength() == 0)
			return 0;
    	/*
    	 * Search for scope closers in the pasted text and find their opening peers
    	 * in the document.
    	 */
    	Document pasted= new Document(command.text);
    	installJavaStuff(pasted);
    	int firstPeer= command.offset;

    	JavaHeuristicScanner pScanner= new JavaHeuristicScanner(pasted);
    	JavaHeuristicScanner dScanner= new JavaHeuristicScanner(document);

    	// add scope relevant after context to peer search
    	int afterToken= dScanner.nextToken(command.offset + command.length, JavaHeuristicScanner.UNBOUND);
    	try {
			switch (afterToken) {
			case Symbols.TokenRBRACE:
				pasted.replace(pasted.getLength(), 0, "}"); //$NON-NLS-1$
				break;
			case Symbols.TokenRPAREN:
				pasted.replace(pasted.getLength(), 0, ")"); //$NON-NLS-1$
				break;
			case Symbols.TokenRBRACKET:
				pasted.replace(pasted.getLength(), 0, "]"); //$NON-NLS-1$
				break;
			}
		} catch (BadLocationException e) {
			// cannot happen
			Assert.isTrue(false);
		}

    	int pPos= 0; // paste text position (increasing from 0)
    	int dPos= Math.max(0, command.offset - 1); // document position (decreasing from paste offset)
    	while (true) {
    		int token= pScanner.nextToken(pPos, JavaHeuristicScanner.UNBOUND);
   			pPos= pScanner.getPosition();
    		switch (token) {
    			case Symbols.TokenLBRACE:
    			case Symbols.TokenLBRACKET:
    			case Symbols.TokenLPAREN:
    				pPos= skipScope(pScanner, pPos, token);
    				if (pPos == JavaHeuristicScanner.NOT_FOUND)
    					return firstPeer;
    				break; // closed scope -> keep searching
    			case Symbols.TokenRBRACE:
    				int peer= dScanner.findOpeningPeer(dPos, '{', '}');
    				dPos= peer - 1;
    				if (peer == JavaHeuristicScanner.NOT_FOUND)
    					return firstPeer;
    				firstPeer= peer;
    				break; // keep searching
    			case Symbols.TokenRBRACKET:
    				peer= dScanner.findOpeningPeer(dPos, '[', ']');
    				dPos= peer - 1;
    				if (peer == JavaHeuristicScanner.NOT_FOUND)
    					return firstPeer;
    				firstPeer= peer;
    				break; // keep searching
    			case Symbols.TokenRPAREN:
    				peer= dScanner.findOpeningPeer(dPos, '(', ')');
    				dPos= peer - 1;
    				if (peer == JavaHeuristicScanner.NOT_FOUND)
    					return firstPeer;
    				firstPeer= peer;
    				break; // keep searching
    			case Symbols.TokenCASE:
    			case Symbols.TokenDEFAULT:
    				JavaIndenter indenter= new JavaIndenter(document, dScanner, fProject);
    				peer= indenter.findReferencePosition(dPos, false, false, false, true);
    				if (peer == JavaHeuristicScanner.NOT_FOUND)
    					return firstPeer;
    				firstPeer= peer;
    				break; // keep searching

    			case Symbols.TokenEOF:
    				return firstPeer;
    			default:
    				// keep searching
    		}
    	}
    }

    /**
     * Skips the scope opened by <code>token</code>.
     *
     * @param scanner the scanner
     * @param start the start position
     * @param token the token
     * @return the position after the scope or <code>JavaHeuristicScanner.NOT_FOUND</code>
     */
    private static int skipScope(JavaHeuristicScanner scanner, int start, int token) {
    	int openToken= token;
    	int closeToken;
    	switch (token) {
    		case Symbols.TokenLPAREN:
    			closeToken= Symbols.TokenRPAREN;
    			break;
    		case Symbols.TokenLBRACKET:
    			closeToken= Symbols.TokenRBRACKET;
    			break;
    		case Symbols.TokenLBRACE:
    			closeToken= Symbols.TokenRBRACE;
    			break;
    		default:
    			Assert.isTrue(false);
    			return -1; // dummy
    	}

    	int depth= 1;
    	int p= start;

    	while (true) {
    		int tok= scanner.nextToken(p, JavaHeuristicScanner.UNBOUND);
    		p= scanner.getPosition();

    		if (tok == openToken) {
    			depth++;
    		} else if (tok == closeToken) {
    			depth--;
    			if (depth == 0)
    				return p + 1;
    		} else if (tok == Symbols.TokenEOF) {
    			return JavaHeuristicScanner.NOT_FOUND;
    		}
    	}
    }

    private boolean isLineDelimiter(IDocument document, String text) {
		String[] delimiters= document.getLegalLineDelimiters();
		if (delimiters != null)
			return TextUtilities.equals(delimiters, text) > -1;
		return false;
	}

	private void smartIndentOnKeypress(IDocument document, DocumentCommand command) {
		switch (command.text.charAt(0)) {
			case '}':
				smartIndentAfterClosingBracket(document, command);
				break;
			case '{':
				smartIndentAfterOpeningBracket(document, command);
				break;
			case 'e':
				smartIndentUponE(document, command);
				break;
		}
	}

	private void smartIndentUponE(IDocument d, DocumentCommand c) {
		if (c.offset < 4 || d.getLength() == 0)
			return;

		try {
			String content= d.get(c.offset - 3, 3);
			if (content.equals("els")) { //$NON-NLS-1$
				JavaHeuristicScanner scanner= new JavaHeuristicScanner(d);
				int p= c.offset - 3;

				// current line
				int line= d.getLineOfOffset(p);
				int lineOffset= d.getLineOffset(line);

				// make sure we don't have any leading comments etc.
				if (d.get(lineOffset, p - lineOffset).trim().length() != 0)
					return;

				// line of last Java code
				int pos= scanner.findNonWhitespaceBackward(p - 1, JavaHeuristicScanner.UNBOUND);
				if (pos == -1)
					return;
				int lastLine= d.getLineOfOffset(pos);

				// only shift if the last java line is further up and is a braceless block candidate
				if (lastLine < line) {

					JavaIndenter indenter= new JavaIndenter(d, scanner, fProject);
					int ref= indenter.findReferencePosition(p, true, false, false, false);
					if (ref == JavaHeuristicScanner.NOT_FOUND)
						return;
					int refLine= d.getLineOfOffset(ref);
					String indent= getIndentOfLine(d, refLine);

					if (indent != null) {
						c.text= indent.toString() + "else"; //$NON-NLS-1$
						c.length += c.offset - lineOffset;
						c.offset= lineOffset;
					}
				}

				return;
			}

			if (content.equals("cas")) { //$NON-NLS-1$
				JavaHeuristicScanner scanner= new JavaHeuristicScanner(d);
				int p= c.offset - 3;

				// current line
				int line= d.getLineOfOffset(p);
				int lineOffset= d.getLineOffset(line);

				// make sure we don't have any leading comments etc.
				if (d.get(lineOffset, p - lineOffset).trim().length() != 0)
					return;

				// line of last Java code
				int pos= scanner.findNonWhitespaceBackward(p - 1, JavaHeuristicScanner.UNBOUND);
				if (pos == -1)
					return;
				int lastLine= d.getLineOfOffset(pos);

				// only shift if the last java line is further up and is a braceless block candidate
				if (lastLine < line) {

					JavaIndenter indenter= new JavaIndenter(d, scanner, fProject);
					int ref= indenter.findReferencePosition(p, false, false, false, true);
					if (ref == JavaHeuristicScanner.NOT_FOUND)
						return;
					int refLine= d.getLineOfOffset(ref);
					int nextToken= scanner.nextToken(ref, JavaHeuristicScanner.UNBOUND);
					String indent;
					if (nextToken == Symbols.TokenCASE || nextToken == Symbols.TokenDEFAULT)
						indent= getIndentOfLine(d, refLine);
					else // at the brace of the switch
						indent= indenter.computeIndentation(p).toString();

					if (indent != null) {
						c.text= indent.toString() + "case"; //$NON-NLS-1$
						c.length += c.offset - lineOffset;
						c.offset= lineOffset;
					}
				}

				return;
			}

		} catch (BadLocationException e) {
			JavaPlugin.log(e);
		}
	}

	/*
	 * @see org.eclipse.jface.text.IAutoIndentStrategy#customizeDocumentCommand(org.eclipse.jface.text.IDocument, org.eclipse.jface.text.DocumentCommand)
	 */
	@Override
	public void customizeDocumentCommand(IDocument d, DocumentCommand c) {
		if (c.doit == false)
			return;

		clearCachedValues();

		if (!fIsSmartMode) {
			super.customizeDocumentCommand(d, c);
			return;
		}

		if (!fIsSmartTab && isRepresentingTab(c.text))
			return;

		if (c.length == 0 && c.text != null && isLineDelimiter(d, c.text)) {
			if (fIsSmartIndentAfterNewline)
				smartIndentAfterNewLine(d, c);
			else
				super.customizeDocumentCommand(d, c);
		}
		else if (c.text.length() == 1)
			smartIndentOnKeypress(d, c);
		else if (c.text.length() > 1 && getPreferenceStore().getBoolean(PreferenceConstants.EDITOR_SMART_PASTE))
			if (fViewer == null || fViewer.getTextWidget() == null || !fViewer.getTextWidget().getBlockSelection())
				smartPaste(d, c); // no smart backspace for paste

	}

	/**
	 * Tells whether the given inserted string represents hitting the Tab key.
	 *
	 * @param text the text to check
	 * @return <code>true</code> if the text represents hitting the Tab key
	 * @since 3.5
	 */
	private boolean isRepresentingTab(String text) {
		if (text == null)
			return false;

		if (isInsertingSpacesForTab()) {
			if (text.length() == 0 || text.length() > getVisualTabLengthPreference())
				return false;
			for (int i= 0; i < text.length(); i++) {
				if (text.charAt(i) != ' ')
					return false;
			}
			return true;
		} else
			return text.length() == 1 && text.charAt(0) == '\t';
	}

	private static IPreferenceStore getPreferenceStore() {
		return JavaPlugin.getDefault().getCombinedPreferenceStore();
	}

	private boolean closeBrace() {
		return fCloseBrace;
	}

	private void clearCachedValues() {
        IPreferenceStore preferenceStore= getPreferenceStore();
		fCloseBrace= preferenceStore.getBoolean(PreferenceConstants.EDITOR_CLOSE_BRACES);
		fIsSmartTab= preferenceStore.getBoolean(PreferenceConstants.EDITOR_SMART_TAB);
		fIsSmartIndentAfterNewline= preferenceStore.getBoolean(PreferenceConstants.EDITOR_SMART_INDENT_AFTER_NEWLINE);
		fIsSmartMode= computeSmartMode();
	}

	private boolean computeSmartMode() {
		IWorkbenchPage page= JavaPlugin.getActivePage();
		if (page != null)  {
			IEditorPart part= page.getActiveEditor();
			if (part instanceof ITextEditorExtension3) {
				ITextEditorExtension3 extension= (ITextEditorExtension3) part;
				return extension.getInsertMode() == ITextEditorExtension3.SMART_INSERT;
			} else if (part != null && EditorUtility.isCompareEditorInput(part.getEditorInput())) {
				ITextEditorExtension3 extension = part.getAdapter(ITextEditorExtension3.class);
				if (extension != null)
					return extension.getInsertMode() == ITextEditorExtension3.SMART_INSERT;
			}
		}
		return false;
	}

	private static CompilationUnitInfo getCompilationUnitForMethod(IDocument document, int offset) {
		try {
			JavaHeuristicScanner scanner= new JavaHeuristicScanner(document);

			IRegion sourceRange= scanner.findSurroundingBlock(offset);
			if (sourceRange == null)
				return null;
			String source= document.get(sourceRange.getOffset(), sourceRange.getLength());

			StringBuilder contents= new StringBuilder();
			contents.append("class ____C{void ____m()"); //$NON-NLS-1$
			final int methodOffset= contents.length();
			contents.append(source);
			contents.append('}');

			char[] buffer= contents.toString().toCharArray();

			return new CompilationUnitInfo(buffer, sourceRange.getOffset() - methodOffset);

		} catch (BadLocationException e) {
			JavaPlugin.log(e);
		}

		return null;
	}

	/**
	 * Returns the block balance, i.e. zero if the blocks are balanced at <code>offset</code>, a
	 * negative number if there are more closing than opening braces, and a positive number if there
	 * are more opening than closing braces.
	 *
	 * @param document the document
	 * @param offset the offset
	 * @param partitioning the partitioning
	 * @return the block balance
	 */
	private static int getBlockBalance(IDocument document, int offset, String partitioning) {
		if (offset < 1)
			return -1;
		if (offset >= document.getLength())
			return 1;

		int begin= offset;
		int end= offset - 1;

		JavaHeuristicScanner scanner= new JavaHeuristicScanner(document);

		while (true) {
			begin= scanner.findOpeningPeer(begin - 1, '{', '}');
			end= scanner.findClosingPeer(end + 1, '{', '}');
			if (begin == -1 && end == -1)
				return 0;
			if (begin == -1)
				return -1;
			if (end == -1)
				return 1;
		}
	}

	private static IRegion createRegion(ASTNode node, int delta) {
		return node == null ? null : new Region(node.getStartPosition() + delta, node.getLength());
	}

	private static IRegion getToken(IDocument document, IRegion scanRegion, int tokenId)  {

		try {

			final String source= document.get(scanRegion.getOffset(), scanRegion.getLength());

			fgScanner.setSource(source.toCharArray());

			int id= fgScanner.getNextToken();
			while (id != ITerminalSymbols.TokenNameEOF && id != tokenId)
				id= fgScanner.getNextToken();

			if (id == ITerminalSymbols.TokenNameEOF)
				return null;

			int tokenOffset= fgScanner.getCurrentTokenStartPosition();
			int tokenLength= fgScanner.getCurrentTokenEndPosition() + 1 - tokenOffset; // inclusive end
			return new Region(tokenOffset + scanRegion.getOffset(), tokenLength);

		} catch (InvalidInputException x) {
			return null;
		} catch (BadLocationException x) {
			return null;
		}
	}
}
