/*******************************************************************************
 * Copyright (c) 2014, 2018 Mateusz Matela 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:
 *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] Formatter does not format Java code correctly, especially when max line width is set - https://bugs.eclipse.org/303519
 *******************************************************************************/
package org.eclipse.jdt.internal.formatter;

import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_LINE;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_BLOCK;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_JAVADOC;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameNotAToken;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameStringLiteral;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameTextBlock;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameWHITESPACE;

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

import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
import org.eclipse.jdt.internal.formatter.Token.WrapMode;
import org.eclipse.jdt.internal.formatter.Token.WrapPolicy;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.text.edits.ReplaceEdit;
import org.eclipse.text.edits.TextEdit;

/**
 * Creates the formatter's result TextEdit by scanning through the tokens and comparing them with the original source.
 */
public class TextEditsBuilder extends TokenTraverser {

	private final String source;
	private TokenManager tm;
	private final DefaultCodeFormatterOptions options;
	private final StringBuilder buffer;

	private final List<Token> stringLiteralsInLine = new ArrayList<Token>();
	private final List<TextEdit> edits = new ArrayList<TextEdit>();

	private final List<IRegion> regions;
	private int currentRegion = 0;

	private TextEditsBuilder childBuilder;
	private final TextEditsBuilder parent;
	private int alignChar;
	private int sourceLimit;
	private int parentTokenIndex;

	public TextEditsBuilder(String source, List<IRegion> regions, TokenManager tokenManager,
			DefaultCodeFormatterOptions options) {
		this.source = source;
		this.tm = tokenManager;
		this.options = options;
		this.regions = adaptRegions(regions);

		this.alignChar = this.options.align_with_spaces ? DefaultCodeFormatterOptions.SPACE : this.options.tab_char;
		this.sourceLimit = source.length();
		this.parent = null;

		this.buffer = new StringBuilder();
	}

	private TextEditsBuilder(TextEditsBuilder parent) {
		this.buffer = parent.buffer;
		this.parent = parent;
		this.source = parent.source;
		this.options = parent.options;
		this.regions = parent.regions;
		this.alignChar = DefaultCodeFormatterOptions.SPACE;
	}

	private List<IRegion> adaptRegions(List<IRegion> givenRegions) {
		// make sure regions don't begin or end inside multiline comments
		ArrayList<IRegion> result = new ArrayList<IRegion>();
		IRegion previous = null;
		for (IRegion region : givenRegions) {
			int start = region.getOffset();
			int end = start + region.getLength() - 1;
			int sourceStart = this.tm.get(0).originalStart;

			if (start > sourceStart) {
				Token token = this.tm.get(this.tm.findIndex(start, -1, false));
				if ((token.tokenType == TokenNameCOMMENT_BLOCK || token.tokenType == TokenNameCOMMENT_JAVADOC)
						&& start <= token.originalEnd) {
					start = token.originalStart;
				}
			}

			if (end > start && end > sourceStart) {
				Token token = this.tm.get(this.tm.findIndex(end, -1, false));
				if ((token.tokenType == TokenNameCOMMENT_BLOCK || token.tokenType == TokenNameCOMMENT_JAVADOC)
						&& end < token.originalEnd) {
					end = token.originalEnd;
				}
			}

			if (previous != null && previous.getOffset() + previous.getLength() >= start) {
				result.remove(result.size() - 1);
				start = previous.getOffset();
			}
			if (end + 1 == this.source.length())
				end++;
			IRegion adapted = new Region(start, end - start + 1);
			result.add(adapted);
			previous = adapted;
		}
		return result;
	}

	@Override
	protected boolean token(Token token, int index) {

		bufferWhitespaceBefore(token, index);

		List<Token> structure = token.getInternalStructure();
		if (token.tokenType == TokenNameCOMMENT_LINE) {
			handleSingleLineComment(token, index);
		} else if (structure != null && !structure.isEmpty()) {
			handleStructuredToken(token, index);
		} else {
			flushBuffer(token.originalStart);
			if (token.isToEscape()) {
				this.buffer.append(this.tm.toString(token));
				flushBuffer(token.originalEnd + 1);
			} else {
				this.counter = token.originalEnd + 1;
			}
		}

		if (token.tokenType == TokenNameStringLiteral)
			this.stringLiteralsInLine.add(token);

		if (getNext() == null) {
			for (int i = 0; i < token.getLineBreaksAfter(); i++)
				bufferLineSeparator(null, i + 1 == token.getLineBreaksAfter());
			char lastChar = this.source.charAt(this.sourceLimit - 1);
			if (token.getLineBreaksAfter() == 0 && (lastChar == '\r' || lastChar == '\n'))
				bufferLineSeparator(null, false);
			flushBuffer(this.sourceLimit);
		}
		return true;
	}

	private void bufferWhitespaceBefore(Token token, int index) {
		if (getLineBreaksBefore() > 0) {
			this.stringLiteralsInLine.clear();
			if (getLineBreaksBefore() > 1) {
				Token indentToken = null;
				if (this.options.indent_empty_lines && token.tokenType != TokenNameNotAToken) {
					if (index == 0) {
						indentToken = token;
					} else {
						boolean isBlockIndent = token.getWrapPolicy() != null
								&& token.getWrapPolicy().wrapMode == WrapMode.BLOCK_INDENT;
						Token previous = this.tm.get(this.tm.findFirstTokenInLine(index - 1, true, !isBlockIndent));
						indentToken = (token.getIndent() > previous.getIndent()) ? token : previous;
					}
				}
				for (int i = 1; i < getLineBreaksBefore(); i++) {
					bufferLineSeparator(token, true);
					if (indentToken != null)
						bufferIndent(indentToken, index);
				}
			}
			bufferLineSeparator(token, false);
			bufferAlign(token, index);
			bufferIndent(token, index);
		} else if (index == 0 && this.parent == null) {
			bufferIndent(token, index);
		} else {
			if (!bufferAlign(token, index) && isSpaceBefore())
				this.buffer.append(' ');
		}
	}

	private void bufferLineSeparator(Token token, boolean emptyLine) {
		if (this.parent == null) {
			this.buffer.append(this.options.line_separator);
			return;
		}

		boolean isTextBlock = token != null && token.tokenType == TokenNameTextBlock;
		this.parent.counter = this.counter;
		this.parent.bufferLineSeparator(null, false);
		if (!(isTextBlock && emptyLine && !this.options.indent_empty_lines))
			this.parent.bufferIndent(this.parent.tm.get(this.parentTokenIndex), this.parentTokenIndex);
		this.counter = this.parent.counter;

		if (isTextBlock)
			return;
		if (token != null && token.tokenType == TokenNameNotAToken)
			return; // this is an unformatted block comment, don't force asterisk
		if (getNext() == null && !emptyLine)
			return; // this is the last token of block comment, asterisk is included

		boolean asteriskFound = false;
		int searchLimit = token != null ? token.originalStart : this.sourceLimit;
		for (int i = this.counter; i < searchLimit; i++) {
			char c = this.source.charAt(i);
			if (c == '*') {
				this.buffer.append(' ');
				flushBuffer(i);
				while (i + 1 < this.sourceLimit && this.source.charAt(i + 1) == '*')
					i++;
				this.counter = i + 1;
				c = this.source.charAt(i + 1);
				if ((c != '\r' && c != '\n') || !emptyLine)
					this.buffer.append(' ');
				asteriskFound = true;
				break;
			}
			if (!ScannerHelper.isWhitespace(c))
				break;
		}
		if (!asteriskFound)
			this.buffer.append(" * "); //$NON-NLS-1$
	}

	private void bufferIndent(Token token, int index) {
		int indent = token.getIndent();
		if (getCurrent() != null && getCurrent() != token)
			indent += getCurrent().getEmptyLineIndentAdjustment();
		int spaces = 0;
		if (this.options.use_tabs_only_for_leading_indentations
				&& this.options.tab_char != DefaultCodeFormatterOptions.SPACE) {
			WrapPolicy wrapPolicy = token.getWrapPolicy();
			boolean isWrappedBlockComment = this.childBuilder != null && this.childBuilder.parentTokenIndex == index;
			if (isWrappedBlockComment) {
				Token lineStart = this.tm.get(this.tm.findFirstTokenInLine(index));
				spaces = token.getIndent() - lineStart.getIndent();
				token = lineStart;
				wrapPolicy = token.getWrapPolicy();
			}
			while (wrapPolicy != null) {
				Token parentLineStart = this.tm.get(this.tm.findFirstTokenInLine(wrapPolicy.wrapParentIndex));
				if (wrapPolicy.wrapMode != WrapMode.BLOCK_INDENT)
					spaces += token.getIndent() - parentLineStart.getIndent();
				token = parentLineStart;
				if (wrapPolicy == token.getWrapPolicy()) {
					assert wrapPolicy == WrapPolicy.FORCE_FIRST_COLUMN || wrapPolicy == WrapPolicy.DISABLE_WRAP;
					break;
				}
				wrapPolicy = token.getWrapPolicy();
			}
		}
		appendIndentationString(this.buffer, this.options.tab_char, this.options.tab_size, indent - spaces, spaces);
	}

	public static void appendIndentationString(StringBuilder target, int tabChar, int tabSize, int indent,
			int additionalSpaces) {
		int spacesCount = additionalSpaces;
		int tabsCount = 0;
		switch (tabChar) {
			case DefaultCodeFormatterOptions.SPACE:
				spacesCount += indent;
				break;
			case DefaultCodeFormatterOptions.TAB:
				if (tabSize > 0) {
					tabsCount += indent / tabSize;
					if (indent % tabSize > 0)
						tabsCount++;
				}
				break;
			case DefaultCodeFormatterOptions.MIXED:
				if (tabSize > 0) {
					tabsCount += indent / tabSize;
					spacesCount += indent % tabSize;
				} else {
					spacesCount += indent;
				}
				break;
			default:
				throw new IllegalStateException("Unrecognized tab char: " + tabChar); //$NON-NLS-1$
		}

		char[] indentChars = new char[tabsCount + spacesCount];
		Arrays.fill(indentChars, 0, tabsCount, '\t');
		Arrays.fill(indentChars, tabsCount, indentChars.length, ' ');
		target.append(indentChars);
	}

	private boolean bufferAlign(Token token, int index) {
		int align = token.getAlign();
		int alignmentChar = this.alignChar;
		if (align == 0 && getLineBreaksBefore() == 0 && this.parent != null) {
			align = token.getIndent();
			token.setAlign(align);
			alignmentChar = DefaultCodeFormatterOptions.SPACE;
		}
		if (align == 0)
			return false;

		int currentPositionInLine = 0;
		if (getLineBreaksBefore() > 0) {
			if (this.parent == null)
				currentPositionInLine = this.tm.toIndent(token.getIndent(), token.getWrapPolicy() != null);
		} else {
			currentPositionInLine = this.tm.getPositionInLine(index - 1);
			currentPositionInLine += this.tm.getLength(this.tm.get(index - 1), currentPositionInLine);
		}
		if (currentPositionInLine >= align)
			return false;

		final int tabSize = this.options.tab_size;
		switch (alignmentChar) {
			case DefaultCodeFormatterOptions.SPACE:
				while (currentPositionInLine++ < align) {
					this.buffer.append(' ');
				}
				break;
			case DefaultCodeFormatterOptions.TAB:
				while (currentPositionInLine < align && tabSize > 0) {
					this.buffer.append('\t');
					currentPositionInLine += tabSize - currentPositionInLine % tabSize;
				}
				break;
			case DefaultCodeFormatterOptions.MIXED:
				while (tabSize > 0 && currentPositionInLine + tabSize - currentPositionInLine % tabSize <= align) {
					this.buffer.append('\t');
					currentPositionInLine += tabSize - currentPositionInLine % tabSize;
				}
				while (currentPositionInLine++ < align) {
					this.buffer.append(' ');
				}
				break;
			default:
				throw new IllegalStateException("Unrecognized align char: " + alignmentChar); //$NON-NLS-1$
		}
		return true;
	}

	private void flushBuffer(int currentPosition) {
		String buffered = this.buffer.toString();
		boolean sourceMatch = this.source.startsWith(buffered, this.counter)
				&& this.counter + buffered.length() == currentPosition;
		while (!sourceMatch && this.currentRegion < this.regions.size()) {
			IRegion region = this.regions.get(this.currentRegion);
			if (currentPosition < region.getOffset())
				break;
			int regionEnd = region.getOffset() + region.getLength();
			if (this.counter >= regionEnd) {
				this.currentRegion++;
				continue;
			}
			if (this.currentRegion == this.regions.size() - 1
					|| this.regions.get(this.currentRegion + 1).getOffset() > currentPosition) {
				this.edits.add(getReplaceEdit(this.counter, currentPosition, buffered, region));
				break;
			}

			// this edit will span more than one region, split it
			IRegion nextRegion = this.regions.get(this.currentRegion + 1);
			int bestSplit = 0;
			int bestSplitScore = Integer.MAX_VALUE;
			for (int i = 0; i < buffered.length(); i++) {
				ReplaceEdit edit1 = getReplaceEdit(this.counter, regionEnd, buffered.substring(0, i), region);
				ReplaceEdit edit2 = getReplaceEdit(regionEnd, currentPosition, buffered.substring(i), nextRegion);
				int score = edit1.getLength() + edit1.getText().length() + edit2.getLength() + edit2.getText().length();
				if (score < bestSplitScore) {
					bestSplit = i;
					bestSplitScore = score;
				}
			}
			this.edits.add(getReplaceEdit(this.counter, regionEnd, buffered.substring(0, bestSplit), region));
			buffered = buffered.substring(bestSplit);
			this.counter = regionEnd;
		}
		this.buffer.setLength(0);
		this.counter = currentPosition;
	}

	private ReplaceEdit getReplaceEdit(int editStart, int editEnd, String text, IRegion region) {
		int regionEnd = region.getOffset() + region.getLength();
		if (editStart < region.getOffset() && regionEnd < editEnd) {
			int breaksInReplacement = this.tm.countLineBreaksBetween(text, 0, text.length());
			int breaksBeforeRegion = this.tm.countLineBreaksBetween(this.source, editStart, region.getOffset());
			int breaksAfterRegion = this.tm.countLineBreaksBetween(this.source, regionEnd, editEnd);
			if (breaksBeforeRegion + breaksAfterRegion > breaksInReplacement) {
				text = ""; //$NON-NLS-1$
				editStart = region.getOffset();
				editEnd = regionEnd;
			}
		}
		if (region.getOffset() > editStart && isOnlyWhitespace(text)) {
			int breaksInReplacement = this.tm.countLineBreaksBetween(text, 0, text.length());
			int breaksOutsideRegion = this.tm.countLineBreaksBetween(this.source, editStart, region.getOffset());
			int breaksToPreserve = breaksInReplacement - breaksOutsideRegion;
			text = adaptReplaceText(text, breaksToPreserve, false, region.getOffset() - 1);
			editStart = region.getOffset();
		}
		if (regionEnd < editEnd && isOnlyWhitespace(text)) {
			int breaksInReplacement = this.tm.countLineBreaksBetween(text, 0, text.length());
			int breaksOutsideRegion = this.tm.countLineBreaksBetween(this.source, regionEnd, editEnd);
			int breaksToPreserve = breaksInReplacement - breaksOutsideRegion;
			text = adaptReplaceText(text, breaksToPreserve, true, regionEnd);
			editEnd = regionEnd;
		}
		return new ReplaceEdit(editStart, editEnd - editStart, text);
	}

	private boolean isOnlyWhitespace(String text) {
		for (int i = 0; i < text.length(); i++)
			if (!ScannerHelper.isWhitespace(text.charAt(i)))
				return false;
		return true;
	}

	private String adaptReplaceText(String text, int breaksToPreserve, boolean isRegionEnd, int regionEdge) {
		int i = isRegionEnd ? 0 : text.length() - 1;
		int direction = isRegionEnd ? 1 : -1;
		int preservedBreaks = 0;
		for (; i >= 0 && i < text.length(); i += direction) {
			assert ScannerHelper.isWhitespace(text.charAt(i));
			char c1 = text.charAt(i);
			if (c1 == '\r' || c1 == '\n') {
				if (preservedBreaks >= breaksToPreserve)
					break;
				preservedBreaks++;
				int i2 = i + direction;
				if (i2 >= 0 && i2 < text.length()) {
					char c2 = text.charAt(i2);
					if ((c2 == '\r' || c2 == '\n') && c2 != c1)
						i = i2;
				}
			}
		}
		text = isRegionEnd ? text.substring(0, i) : text.substring(i + 1);

		// cut out text if the source outside region is a matching whitespace
		int textPos = isRegionEnd ? text.length() - 1 : 0;
		int sourcePos = regionEdge;
		theLoop: while (textPos >= 0 && textPos < text.length() && sourcePos >= 0 && sourcePos < this.source.length()) {
			char c1 = text.charAt(textPos);
			char c2 = this.source.charAt(sourcePos);
			if (c1 == c2 && (c1 == ' ' || c1 == '\t')) {
				textPos -= direction;
				sourcePos += direction;
			} else if (c1 == '\t' && c2 == ' ') {
				for (i = 0; i < this.options.tab_size; i++) {
					sourcePos += direction;
					if (i < this.options.tab_size - 1 && (sourcePos < 0 || sourcePos >= this.source.length()
							|| this.source.charAt(sourcePos) != ' '))
						continue theLoop;
				}
				textPos -= direction;
			} else if (c2 == '\t' && c1 == ' ') {
				for (i = 0; i < this.options.tab_size; i++) {
					textPos -= direction;
					if (i < this.options.tab_size - 1
							&& (textPos < 0 || textPos >= text.length() || text.charAt(textPos) != ' '))
						continue theLoop;
				}
				sourcePos += direction;
			} else {
				break;
			}
		}
		if (isRegionEnd) {
			text = text.substring(0, textPos + 1);
		} else {
			text = text.substring(textPos);
		}

		return text;
	}

	private void handleSingleLineComment(Token lineComment, int index) {
		List<Token> structure = lineComment.getInternalStructure();
		if (structure == null) {
			flushBuffer(lineComment.originalStart);
			this.counter = lineComment.originalEnd + 1;
			return;
		}
		if (structure.get(0).tokenType == TokenNameWHITESPACE) {
			flushBuffer(structure.get(0).originalStart);
		} else {
			flushBuffer(lineComment.originalStart);
		}

		for (int i = 0; i < structure.size(); i++) {
			Token fragment = structure.get(i);

			if (fragment.getLineBreaksBefore() > 0) {
				bufferLineSeparator(fragment, false);
				if (this.parent != null)
					bufferAlign(lineComment, index);
				bufferIndent(fragment, index);
			} else if (fragment.isSpaceBefore() && i > 0) {
				this.buffer.append(' ');
			}

			if (fragment.hasNLSTag()) {
				int tagNumber = this.stringLiteralsInLine.indexOf(fragment.getNLSTag());
				assert tagNumber >= 0;
				this.buffer.append("//$NON-NLS-").append(tagNumber + 1).append("$"); //$NON-NLS-1$ //$NON-NLS-2$
			} else if (fragment.originalStart < this.counter) {
				// Comment line prefix may be a copy of earlier code
				this.buffer.append(this.tm.toString(fragment));
			} else {
				flushBuffer(fragment.originalStart);
				this.counter = fragment.originalEnd + 1;
			}
		}

		if (lineComment.originalEnd > lineComment.originalStart) // otherwise it's a forged comment
			flushBuffer(lineComment.originalEnd + 1);
	}

	private void handleStructuredToken(Token comment, int index) {
		flushBuffer(comment.originalStart);
		if (this.childBuilder == null) {
			this.childBuilder = new TextEditsBuilder(this);
		}
		this.childBuilder.traverseInternalStructure(comment, index);
		this.edits.addAll(this.childBuilder.edits);
		this.childBuilder.edits.clear();
		this.counter = this.childBuilder.sourceLimit;
	}

	private void traverseInternalStructure(Token token, int index) {
		List<Token> structure = token.getInternalStructure();
		this.tm = new TokenManager(structure, this.parent.tm);
		this.counter = token.originalStart;
		this.sourceLimit = token.originalEnd + 1;

		this.parentTokenIndex = index;

		traverse(structure, 0);
	}

	public void processComment(Token commentToken) {
		assert commentToken.isComment();
		if (commentToken.tokenType == TokenNameCOMMENT_LINE) {
			handleSingleLineComment(commentToken, this.tm.indexOf(commentToken));
		} else {
			handleStructuredToken(commentToken, this.tm.indexOf(commentToken));
		}
	}

	public List<TextEdit> getEdits() {
		return this.edits;
	}

	public void setAlignChar(int alignChar) {
		this.alignChar = alignChar;
	}
}