/*******************************************************************************
 * Copyright (c) 2005, 2007 IBM Corporation and others.
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 * 
 * SPDX-License-Identifier: EPL-2.0
 *
 
 *******************************************************************************/
package org.eclipse.dltk.javascript.internal.ui.text;

import org.eclipse.core.runtime.Assert;
import org.eclipse.dltk.core.IMethod;
import org.eclipse.dltk.core.IModelElement;
import org.eclipse.dltk.core.IScriptProject;
import org.eclipse.dltk.core.ISourceModule;
import org.eclipse.dltk.core.ModelException;
import org.eclipse.dltk.core.ScriptModelUtil;
import org.eclipse.dltk.internal.ui.editor.EditorUtility;
import org.eclipse.dltk.javascript.internal.corext.codemanipulation.JSCodeGeneration;
import org.eclipse.dltk.javascript.internal.ui.JavaScriptUI;
import org.eclipse.dltk.javascript.parser.jsdoc.JSDocTag;
import org.eclipse.dltk.javascript.scriptdoc.JavaHeuristicScanner;
import org.eclipse.dltk.javascript.scriptdoc.JavaIndenter;
import org.eclipse.dltk.javascript.ui.text.IJavaScriptPartitions;
import org.eclipse.dltk.ui.DLTKUIPlugin;
import org.eclipse.dltk.ui.PreferenceConstants;
import org.eclipse.dltk.ui.text.util.TabStyle;
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.TextUtilities;
import org.eclipse.jface.text.rules.FastPartitioner;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.texteditor.ITextEditorExtension3;

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

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

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

	private String fPartitioning;
	final IScriptProject fProject;
	JsPreferenceInterpreter prefs;

	/**
	 * 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
	 */
	public JavascriptAutoEditStrategy(String partitioning,
			IScriptProject project) {
		fPartitioning = partitioning;
		fProject = project;
		this.prefs = new JsPreferenceInterpreter(JavaScriptUI.getDefault()
				.getPreferenceStore());
	}

	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(String d, int offset, int endOffset, char ch) {
		while (offset < endOffset) {
			char curr = d.charAt(offset);
			if (curr == '\\') {
				// ignore escaped characters
				offset++;
			} else if (curr == ch) {
				return offset;
			}
			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
					StringBuffer replaceText = new StringBuffer(
							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) {
			DLTKUIPlugin.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) {
			DLTKUIPlugin.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);

			StringBuffer buf = new StringBuffer(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();
			// insert closing brace on new line after an unclosed opening brace
			if (closeBrace()
					&& countBrackets(d.get(), reg.getOffset(), c.offset, false) > 0
					&& !isClosed(d, c.offset, c.length)) {
				c.caretOffset = c.offset + buf.length();
				c.shiftsCaret = false;

				buf.append(TextUtilities.getDefaultLineDelimiter(d));
				final StringBuffer reference;
				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);
				}
			} else {
				IRegion prevLine = d.getLineInformation(line);
				String str = d.get(prevLine.getOffset(), prevLine.getLength());
				if (str.trim().startsWith(C_START)) {
					/*
					 * handle only comment/jsdoc start here, as it happens in
					 * code partition. Continuation is handled in
					 * JSDocAutoIndentStrategy attached to comment/jsdoc
					 * partitions.
					 */
					String result = handleJsCodeCompleteStars(str, prevLine,
							line, d, c);
					if (result != null) {
						buf.setLength(0);
						buf.append(result);
					}
				}
			}

			c.text = buf.toString();

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

	static final String C_START = "/*";
	static final String C_END = "*/";

	private String handleJsCodeCompleteStars(String str, IRegion prevLine,
			int line, IDocument d, DocumentCommand c) {
		int index = str.indexOf(C_START);
		// if it is directly closed then there is no doc to append.
		if (str.indexOf(C_END, index + 2) != -1)
			return null;

		// handle the start comment character prefix;
		if (prevLine.getOffset() + index < c.offset) {
			StringBuffer buf = new StringBuffer();
			StringBuffer indentStr = new StringBuffer(index);
			int counter = 0;
			while (counter < index) {
				char ch = str.charAt(counter++);
				if (Character.isWhitespace(ch)) {
					indentStr.append(ch);
				} else {
					indentStr.append(' ');
				}
			}

			boolean enclosedComment = false;
			try {
				index = line + 1;
				IRegion nextLine = null;
				while ((nextLine = d.getLineInformation(index++)) != null) {
					String strNextLine = d.get(nextLine.getOffset(),
							nextLine.getLength());
					int stComment = strNextLine.indexOf(C_START);
					int endComment = strNextLine.indexOf(C_END);

					if (stComment != -1 && endComment != -1) {
						if (stComment < endComment) {
							break;
						}
					} else if (endComment != -1) {
						enclosedComment = true;
						break;
					} else if (stComment != -1) {
						break;
					}

				}
			} catch (Exception ex) {

			}
			final String endTag = "\n" + indentStr + " */";
			String generatedString = null;
			if (!enclosedComment && JSDocAutoIndentStrategy.isGenerateStub()) {
				try {
					d.replace(c.offset, 0, endTag);
				} catch (BadLocationException e) {
					return null;
				}
				c.length = endTag.length();
				final IMethod method = findMethod(d,
						c.offset + endTag.length(), true);
				if (method != null) {
					final String lineDelimiter = TextUtilities
							.getDefaultLineDelimiter(d);
					generatedString = JSCodeGeneration.getMethodComment(method,
							null, lineDelimiter);
					if (generatedString != null) {
						generatedString = JSDocAutoIndentStrategy
								.normalizeGeneratedDoc(generatedString);
						generatedString = JSCodeGeneration.changeIndent(
								generatedString, 0, method.getScriptProject(),
								indentStr.toString(), lineDelimiter);
					}
				}
			}
			buf.append("\n" + indentStr + " * ");
			if (generatedString != null) {
				buf.append(generatedString);
			}
			c.caretOffset = c.offset + buf.length();
			c.shiftsCaret = false;
			if (!enclosedComment)
				buf.append(endTag);
			return buf.toString();
		}

		return null;
	}

	static IMethod findMethod(IDocument document, int offset, boolean reconcile) {
		final int len = document.getLength();
		try {
			while (offset < len
					&& Character.isWhitespace(document.getChar(offset))) {
				++offset;
			}
		} catch (BadLocationException e) {
			return null;
		}
		final IModelElement modelElement = EditorUtility
				.getActiveEditorModelInput();
		if (modelElement != null && modelElement instanceof ISourceModule) {
			final ISourceModule module = (ISourceModule) modelElement;
			if (reconcile) {
				try {
					ScriptModelUtil.reconcile(module);
				} catch (ModelException e) {
					return null;
				}
			}
			final IModelElement member;
			try {
				member = module.getElementAt(offset);
			} catch (ModelException e) {
				return null;
			}
			try {
				if (member instanceof IMethod
						&& ((IMethod) member).getSourceRange().getOffset() == offset) {
					return (IMethod) member;
				}
			} catch (ModelException e) {
				JavaScriptUI.log(e);
			}
		}
		return null;
	}

	private boolean isClosed(IDocument d, int offset, int length) {
		String sm = d.get();
		int levelBefore = countBrackets(sm, 0, offset, true);
		int levelAfter = -countBrackets(sm, offset, sm.length(), true);
		return levelBefore <= levelAfter;
	}

	/**
	 * @param offset
	 * @param sm
	 * @param levelBefore
	 */
	private int countBrackets(String sm, int start, int end, boolean countClose) {
		int level = 0;
		for (int a = start; a < end; a++) {
			char charAt = sm.charAt(a);
			switch (charAt) {
			case '\'': {
				a = getStringEnd(sm, a + 1, end, '\'');
				break;
			}
			case '"': {
				a = getStringEnd(sm, a + 1, end, '"');
				break;
			}
			case '/': {
				int aPlus1 = a + 1;
				if (aPlus1 < end) {
					// test if single line comment
					if (sm.charAt(aPlus1) == '/') {
						// skip it all.
						a = sm.indexOf('\n', aPlus1);
						if (a == -1)
							a = sm.length();
					} else if (sm.charAt(aPlus1) == '*') {
						// start of doc search for the end..
						a = sm.indexOf(C_END, aPlus1);
						if (a == -1)
							a = sm.length();
						else
							a = a + 1;
					} else // regexp?
					{
						aPlus1++;
						while (aPlus1 < end) {
							char c = sm.charAt(aPlus1);
							aPlus1++;
							if (c == '\\') {
								// escape char add one mre
								aPlus1++;
								continue;
							}
							if (c == '/') {
								// reg exp found (/xxx/)
								a = aPlus1;
								break;
							}
							if (c == '\n')
								break;
						}
					}
				}
				break;
			}
			case '<': {
				// xml test
				int aPlus1 = a + 1;
				StringBuilder sb = new StringBuilder(5);
				sb.append("</");
				while (aPlus1 < end) {
					char c = sm.charAt(aPlus1);
					if (Character.isJavaIdentifierPart(c)) {
						sb.append(c);
						aPlus1++;
					} else if ((c == '>' || c == ' ') && sb.length() > 2) {
						if (c == '>') {
							// search for close tag.
							int index = sm.substring(aPlus1, end).indexOf(
									sb.toString());
							if (index != -1) {
								a = aPlus1 + index + sb.length();
							}
						} else {
							while (++aPlus1 < end) {
								c = sm.charAt(aPlus1);
								if (c == '/') {
									if (++aPlus1 < end) {
										c = sm.charAt(aPlus1);
										if (c == '>') {
											a = aPlus1 + 1;
											break;
										}
										aPlus1--;
									}
								} else if (c == '>') {
									// search for close tag.
									int index = sm.substring(aPlus1, end)
											.indexOf(sb.toString());
									if (index != -1) {
										a = aPlus1 + index + sb.length();
									}
									break;
								} else if (c == '"' || c == '\'') {
									int index = sm.substring(aPlus1 + 1, end)
											.indexOf(c);
									if (index != -1) {
										aPlus1 = aPlus1 + index;
									}
								}
							}
						}
						break;
					} else {
						break;
					}
				}
				break;
			}
			case '{': {
				level++;
				break;
			}
			case '}': {
				if (countClose)
					level--;
				break;
			}
			}
		}
		return level;
	}

	/**
	 * Installs a java partitioner with <code>document</code>.
	 * 
	 * @param document
	 *            the document
	 */
	private static void installJavaStuff(Document document) {
		FastPartitioner partitioner = new FastPartitioner(
				new JavascriptPartitionScanner(),
				IJavaScriptPartitions.LEGAL_CONTENT_TYPES);
		partitioner.connect(document);
		document.setDocumentPartitioner(IJavaScriptPartitions.JS_PARTITIONING,
				partitioner);
	}

	/**
	 * Installs a java partitioner with <code>document</code>.
	 * 
	 * @param document
	 *            the document
	 */
	private static void removeJavaStuff(Document document) {
		document.setDocumentPartitioner(IJavaScriptPartitions.JS_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);
			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 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
							&& temp.get(lineOffset, lineLength).trim().length() != 0) {
						isIndentDetected = true;
						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;
						}
						removeJavaStuff(temp);
					} 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);

			}

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

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

		} catch (BadLocationException e) {
			DLTKUIPlugin.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,
					IJavaScriptPartitions.JS_PARTITIONING, to, true);
			if (type.equals(IJavaScriptPartitions.JS_DOC)
					|| type.equals(IJavaScriptPartitions.JS_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 >= 4)
				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 4;
	}

	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> in <code>document</code>,
	 * returns either the position of the
	 * 
	 * @param pos
	 * @param token
	 * @return the position after the scope
	 */
	private static int skipScope(JavaHeuristicScanner scanner, int pos,
			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 = pos;

		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.startsWith(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;
		// quotes and brackets are handled by JavaScriptBracketInserter
		// case '\"':
		// case '\'':
		// case '(':
		// case '[':
		// autoClose(document, command);
		// break;
		case 'e':
			smartIndentUponE(document, command);
			break;
		case '*':
			smartCloseJSDoc(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) {
			DLTKUIPlugin.log(e);
		}
	}

	static void smartCloseJSDoc(IDocument d, DocumentCommand c) {
		if (c.offset < 3 || d.getLength() == 0)
			return;
		try {
			final String content = d.get(c.offset - 2, 2);
			if (content.equals("/*")) { //$NON-NLS-1$
				final JavaHeuristicScanner scanner = new JavaHeuristicScanner(d);
				int pos = c.offset - 2;
				pos = scanner.findNonWhitespaceBackward(pos - 1,
						JavaHeuristicScanner.UNBOUND);
				if (pos == JavaHeuristicScanner.NOT_FOUND) {
					return;
				}
				final int prevToken = scanner.previousToken(pos,
						JavaHeuristicScanner.UNBOUND);
				if (prevToken == Symbols.TokenVAR
						|| prevToken == Symbols.TokenCOMMA
						&& scanner.looksLikeVarStatement(scanner.getPosition())) {
					c.text += " " + JSDocTag.TYPE + " {} */ ";
					c.shiftsCaret = false;
					c.caretOffset = c.offset + c.text.indexOf('}');
				} else {
					pos = scanner.findNonWhitespaceForward(c.offset,
							JavaHeuristicScanner.UNBOUND);
					if (pos == JavaHeuristicScanner.NOT_FOUND) {
						return;
					}
					final int nextToken = scanner.nextToken(pos,
							JavaHeuristicScanner.UNBOUND);
					if (nextToken == Symbols.TokenFUNCTION) {
						c.text += "  */";
						if (c.offset < d.getLength()
								&& !Character.isWhitespace(d.getChar(c.offset))) {
							c.text += " ";
						}
						c.shiftsCaret = false;
						c.caretOffset = c.offset + 2;
					}
				}
			}
		} catch (BadLocationException e) {
			DLTKUIPlugin.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 (!isSmartMode()) {
			super.customizeDocumentCommand(d, c);
			return;
		}
		if (!fIsSmartTab && isRepresentingTab(c.text))
			return;
		if (c.length == 0 && c.text != null && isLineDelimiter(d, c.text))
			smartIndentAfterNewLine(d, c);
		else if (c.text.length() == 1)
			smartIndentOnKeypress(d, c);
		else if (c.text.length() > 1
				&& getPreferenceStore().getBoolean(
						PreferenceConstants.EDITOR_SMART_PASTE))
			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.0
	 */
	private boolean isRepresentingTab(String text) {
		if (text == null)
			return false;

		if (TabStyle.SPACES == prefs.getTabStyle()) {
			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 JavaScriptUI.getDefault().getPreferenceStore();
	}

	private boolean closeBrace() {
		return fCloseBrace;
	}

	private boolean isSmartMode() {
		return fIsSmartMode;
	}

	private void clearCachedValues() {
		fCloseBrace = prefs.closeBrackets();
		fIsSmartTab = prefs.isSmartTab();
		fIsSmartMode = computeSmartMode();
	}

	protected boolean computeSmartMode() {
		IWorkbenchPage page = DLTKUIPlugin.getActivePage();
		if (page != null) {
			IEditorPart part = page.getActiveEditor();
			if (part instanceof ITextEditorExtension3) {
				ITextEditorExtension3 extension = (ITextEditorExtension3) part;
				return extension.getInsertMode() == ITextEditorExtension3.SMART_INSERT;
			}
		}
		return false;
	}
}
