/*******************************************************************************
 * Copyright (c) 2000, 2013 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
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/

package org.eclipse.ant.internal.ui.editor;

import org.eclipse.ant.internal.ui.AntUIPlugin;
import org.eclipse.ant.internal.ui.editor.formatter.XmlDocumentFormatter;
import org.eclipse.ant.internal.ui.model.AntElementNode;
import org.eclipse.ant.internal.ui.model.AntModel;
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.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.ui.texteditor.AbstractDecoratedTextEditorPreferenceConstants;

/**
 * Auto edit strategy for Ant build files Current does special indenting.
 */
public class AntAutoEditStrategy extends DefaultIndentLineAutoEditStrategy {

	private AntModel fModel;
	private int fAccumulatedChange = 0;

	public AntAutoEditStrategy(AntModel model) {
		fModel = model;
	}

	/**
	 * Sets the indentation based on the Ant element node that contains the offset of the document command.
	 * 
	 * @param d
	 *            the document to work on
	 * @param c
	 *            the command to deal with
	 */
	private synchronized void autoIndentAfterNewLine(IDocument d, DocumentCommand c) {

		if (c.offset == -1 || d.getLength() == 0 || fModel.getProjectNode(false) == null) {
			return;
		}

		int position = (c.offset == d.getLength() ? c.offset - 1 : c.offset);
		AntElementNode node = fModel.getProjectNode(false).getNode(position - fAccumulatedChange);
		if (node == null) {
			return;
		}

		try {
			StringBuffer correct = XmlDocumentFormatter.getLeadingWhitespace(node.getOffset(), d);
			if (!nextNodeIsEndTag(c.offset, d)) {
				correct.append(XmlDocumentFormatter.createIndent());
			}
			StringBuilder buf = new StringBuilder(c.text);
			buf.append(correct);
			fAccumulatedChange += buf.length();

			int line = d.getLineOfOffset(position);
			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);
			c.caretOffset = c.offset + buf.length();
			c.shiftsCaret = false;
			c.text = buf.toString();

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

	private boolean nextNodeIsEndTag(int offset, IDocument document) {
		if (offset + 1 > document.getLength()) {
			return false;
		}
		try {
			IRegion lineRegion = document.getLineInformationOfOffset(offset);
			offset = findEndOfWhiteSpace(document, offset, lineRegion.getOffset() + lineRegion.getLength());
			String nextChars = document.get(offset, 2).trim();
			if ("</".equals(nextChars) || "/>".equals(nextChars)) { //$NON-NLS-1$ //$NON-NLS-2$
				return true;
			}
		}
		catch (BadLocationException e) {
			// do nothing
		}
		return false;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jface.text.IAutoEditStrategy#customizeDocumentCommand(org.eclipse.jface.text.IDocument,
	 * org.eclipse.jface.text.DocumentCommand)
	 */
	@Override
	public void customizeDocumentCommand(IDocument d, DocumentCommand c) {

		if (c.length == 0 && c.text != null && isLineDelimiter(d, c.text)) {
			autoIndentAfterNewLine(d, c);
		} else if (c.text.length() > 1) {
			smartPaste(d, c);
		}
	}

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

	public synchronized void reconciled() {
		fAccumulatedChange = 0;
	}

	private void smartPaste(IDocument document, DocumentCommand command) {
		try {
			if (command.offset == -1 || document.getLength() == 0 || fModel.getProjectNode(false) == null) {
				return;
			}
			String origChange = command.text;
			int position = (command.offset == document.getLength() ? command.offset - 1 : command.offset);
			AntElementNode node = fModel.getProjectNode(false).getNode(position - fAccumulatedChange);
			if (node == null) {
				return;
			}

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

			// handle the indentation computation inside a temporary document
			Document temp = new Document(command.text);

			// 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 lines = temp.getNumberOfLines();
			for (int l = firstLine; 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
					StringBuffer current = XmlDocumentFormatter.getLeadingWhitespace(lineOffset, temp);
					StringBuffer correct = XmlDocumentFormatter.getLeadingWhitespace(node.getOffset(), document);
					correct.append(XmlDocumentFormatter.createIndent());

					insertLength = subtractIndent(correct, current, addition);
					isIndentDetected = true;
				}

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

			// modify the command
			if (!origChange.equals(temp.get())) {
				fAccumulatedChange += temp.getLength();
				command.text = temp.get();
			}

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

	/**
	 * 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
	 * @throws BadLocationException
	 *             on concurrent document modification
	 */
	private void addIndent(Document document, int line, CharSequence indent) throws BadLocationException {
		IRegion region = document.getLineInformation(line);
		int insert = region.getOffset();

		// 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>.
	 * 
	 * @param document
	 *            the document
	 * @param line
	 *            the line
	 * @param toDelete
	 *            the number of space equivalents to delete.
	 * @throws BadLocationException
	 *             on concurrent document modification
	 */
	private void cutIndent(Document document, int line, int toDelete) throws BadLocationException {
		IRegion region = document.getLineInformation(line);
		int from = region.getOffset();
		int endOffset = region.getOffset() + region.getLength();

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

		document.replace(from, to - from, null);
	}

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

		return 1;
	}

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

		for (int i = 0; i < seq.length(); i++) {
			char ch = seq.charAt(i);
			if (ch == '\t') {
				size += tablen - size % tablen;
			} else {
				size++;
			}
		}
		return size;
	}

	/**
	 * 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
	 * @return the difference in length of <code>correct</code> and <code>current</code>
	 */
	private int subtractIndent(CharSequence correct, CharSequence current, StringBuffer difference) {
		int c1 = computeVisualLength(correct);
		int c2 = computeVisualLength(current);
		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);
		}

		return diff;
	}

	/**
	 * The preference setting for the visual tabulator display.
	 * 
	 * @return the number of spaces displayed for a tabulator in the editor
	 */
	private int getVisualTabLengthPreference() {
		return AntUIPlugin.getDefault().getCombinedPreferenceStore().getInt(AbstractDecoratedTextEditorPreferenceConstants.EDITOR_TAB_WIDTH);
	}
}
