/*******************************************************************************
 * 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
 *     Lars Vogel <Lars.Vogel@vogella.com> - Contributions for
 *     						Bug 473178
 *******************************************************************************/
package org.eclipse.jdt.internal.formatter.linewrap;

import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_JAVADOC;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameCOMMENT_LINE;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameNotAToken;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameWHITESPACE;
import static org.eclipse.jdt.internal.formatter.CommentsPreparator.COMMENT_LINE_SEPARATOR_LENGTH;

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

import org.eclipse.jdt.internal.formatter.DefaultCodeFormatterOptions;
import org.eclipse.jdt.internal.formatter.Token;
import org.eclipse.jdt.internal.formatter.TokenManager;
import org.eclipse.jdt.internal.formatter.TokenTraverser;
import org.eclipse.jdt.internal.formatter.Token.WrapMode;
import org.eclipse.jdt.internal.formatter.Token.WrapPolicy;

public class CommentWrapExecutor extends TokenTraverser {

	private final TokenManager tm;
	private final DefaultCodeFormatterOptions options;

	private final ArrayList<Token> nlsTags = new ArrayList<>();

	private int lineStartPosition;
	private int lineLimit;
	private boolean simulation;
	private boolean wrapDisabled;
	private boolean newLinesAtBoundries;

	private Token potentialWrapToken, potentialWrapTokenSubstitute;
	private int counterIfWrapped, counterIfWrappedSubstitute;
	private int lineCounter;

	public CommentWrapExecutor(TokenManager tokenManager, DefaultCodeFormatterOptions options) {
		this.tm = tokenManager;
		this.options = options;
	}

	/**
	 * @param commentToken token to wrap
	 * @param startPosition position in line of the beginning of the comment
	 * @param simulate if {@code true}, the properties of internal tokens will not really change. This
	 * mode is useful for checking how much space the comment takes.
	 * @param noWrap if {@code true}, it means that wrapping is disabled for this comment (for example because there's
	 * a NON-NLS tag after it). This method is still useful for checking comment length in that case.
	 * @return position in line at the end of comment
	 */
	public int wrapMultiLineComment(Token commentToken, int startPosition, boolean simulate, boolean noWrap) {
		this.lineCounter = 1;
		this.counter = startPosition;
		commentToken.setIndent(this.tm.toIndent(startPosition, true));
		this.lineStartPosition = commentToken.getIndent();
		this.lineLimit = getLineLimit(startPosition);
		this.simulation = simulate;
		this.wrapDisabled = noWrap;
		this.potentialWrapToken = this.potentialWrapTokenSubstitute = null;
		this.newLinesAtBoundries = commentToken.tokenType == TokenNameCOMMENT_JAVADOC
				? this.options.comment_new_lines_at_javadoc_boundaries
				: this.options.comment_new_lines_at_block_boundaries;

		List<Token> structure = commentToken.getInternalStructure();
		if (structure == null || structure.isEmpty())
			return startPosition + this.tm.getLength(commentToken, startPosition);

		int position = tryToFitInOneLine(structure, startPosition, noWrap);
		if (position > 0)
			return position;

		traverse(structure, 0);
		cleanupIndent(structure);

		if (this.newLinesAtBoundries)
			return this.lineStartPosition + 1 + this.tm.getLength(structure.get(structure.size() - 1), 0);
		return this.counter;
	}

	public int getLinesCount() {
		return this.lineCounter;
	}

	private int tryToFitInOneLine(List<Token> structure, int startPosition, boolean noWrap) {
		int position = startPosition;
		boolean hasWrapPotential = false;
		boolean wasSpaceAfter = false;
		for (int i = 0; i < structure.size(); i++) {
			Token token = structure.get(i);
			if (token.getLineBreaksBefore() > 0 || token.getLineBreaksAfter() > 0) {
				assert !noWrap; // comment already wrapped
				return -1;
			}
			if (!wasSpaceAfter && token.isSpaceBefore())
				position++;
			position += this.tm.getLength(token, position);
			wasSpaceAfter = token.isSpaceAfter();
			if (wasSpaceAfter)
				position++;

			WrapPolicy policy = token.getWrapPolicy();
			if (i > 1 && (policy == null || policy == WrapPolicy.SUBSTITUTE_ONLY))
				hasWrapPotential = true;
		}
		if (position <= this.lineLimit || noWrap || !hasWrapPotential)
			return position;
		return -1;
	}

	private int getStartingPosition(Token token, boolean isNewLine) {
		int position = this.lineStartPosition + token.getAlign() + (isNewLine ? token.getIndent() : 0);
		if (token.tokenType != TokenNameNotAToken)
			position += COMMENT_LINE_SEPARATOR_LENGTH;
		return position;
	}

	@Override
	protected boolean token(Token token, int index) {
		final int positionIfNewLine = getStartingPosition(token, true);

		int lineBreaksBefore = getLineBreaksBefore();
		if ((index == 1 || getNext() == null) && this.newLinesAtBoundries && lineBreaksBefore == 0) {
			if (!this.simulation)
				token.breakBefore();
			lineBreaksBefore = 1;
		}

		if (lineBreaksBefore > 0) {
			this.lineCounter += lineBreaksBefore;
			this.counter = positionIfNewLine;
			this.potentialWrapToken = this.potentialWrapTokenSubstitute = null;
			this.lineLimit = getLineLimit(this.lineStartPosition);

		}

		boolean canWrap = getNext() != null && lineBreaksBefore == 0 && index > 1 && positionIfNewLine < this.counter;
		if (canWrap) {
			if (token.getWrapPolicy() == null) {
				this.potentialWrapToken = token;
				this.counterIfWrapped = positionIfNewLine;
			} else if (token.getWrapPolicy() == WrapPolicy.SUBSTITUTE_ONLY) {
				this.potentialWrapTokenSubstitute = token;
				this.counterIfWrappedSubstitute = positionIfNewLine;
			}
		}

		if (index > 1 && getNext() != null && (token.getAlign() + token.getIndent()) > 0)
			this.counter = Math.max(this.counter, getStartingPosition(token, getLineBreaksBefore() > 0));
		this.counter += this.tm.getLength(token, this.counter);
		this.counterIfWrapped += this.tm.getLength(token, this.counterIfWrapped);
		this.counterIfWrappedSubstitute += this.tm.getLength(token, this.counterIfWrappedSubstitute);
		if (shouldWrap()) {
			if (this.potentialWrapToken == null) {
				assert this.potentialWrapTokenSubstitute != null;
				this.potentialWrapToken = this.potentialWrapTokenSubstitute;
				this.counterIfWrapped = this.counterIfWrappedSubstitute;
			}
			if (!this.simulation) {
				this.potentialWrapToken.breakBefore();
			}
			this.counter = this.counterIfWrapped;
			this.lineCounter++;
			this.potentialWrapToken = this.potentialWrapTokenSubstitute = null;
			this.lineLimit = getLineLimit(this.lineStartPosition);
		}

		if (isSpaceAfter()) {
			this.counter++;
			this.counterIfWrapped++;
		}

		return true;
	}

	private boolean shouldWrap() {
		if (this.wrapDisabled || this.counter <= this.lineLimit)
			return false;
		if (getLineBreaksAfter() == 0 && getNext() != null && getNext().getWrapPolicy() == WrapPolicy.DISABLE_WRAP) {
			// The next token cannot be wrapped, so there's no need to wrap now.
			// Let's wait and decide when there's more information available.
			return false;
		}
		if (this.potentialWrapToken != null && this.potentialWrapTokenSubstitute != null
				&& this.counterIfWrapped > this.lineLimit && this.counterIfWrappedSubstitute < this.counterIfWrapped) {
			// there is a normal token to wrap, but the line would overflow anyway - better use substitute
			this.potentialWrapToken = null;
		}
		if (this.potentialWrapToken == null && this.potentialWrapTokenSubstitute == null) {
			return false;
		}

		return true;
	}

	private void cleanupIndent(List<Token> structure) {
		if (this.simulation)
			return;
		new TokenTraverser() {
			@Override
			protected boolean token(Token token, int index) {
				if (token.tokenType == TokenNameCOMMENT_JAVADOC && token.getInternalStructure() == null) {
					if (getLineBreaksBefore() > 0)
						token.setAlign(token.getAlign() + token.getIndent());
					token.setIndent(0);
				}
				return true;
			}
		}.traverse(structure, 0);
	}

	public void wrapLineComment(Token commentToken, int startPosition) {
		List<Token> structure = commentToken.getInternalStructure();
		if (structure == null || structure.isEmpty())
			return;
		int commentIndex = this.tm.indexOf(commentToken);
		boolean isHeader = this.tm.isInHeader(commentIndex);
		boolean formattingEnabled = (this.options.comment_format_line_comment && !isHeader)
				|| (this.options.comment_format_header && isHeader);
		if (!formattingEnabled)
			return;

		int position = startPosition;
		startPosition = this.tm.toIndent(startPosition, true);
		int indent = startPosition;
		int limit = getLineLimit(position);

		for (Token token : structure) {
			if (token.hasNLSTag()) {
				this.nlsTags.add(token);
				position += token.countChars() + (token.isSpaceBefore() ? 1 : 0);
			}
		}

		Token whitespace = null;
		Token prefix = structure.get(0);
		if (prefix.tokenType == TokenNameWHITESPACE) {
			whitespace = new Token(prefix);
			whitespace.breakBefore();
			whitespace.setIndent(indent);
			whitespace.setWrapPolicy(new WrapPolicy(WrapMode.WHERE_NECESSARY, commentIndex, 0));
			prefix = structure.get(1);
			assert prefix.tokenType == TokenNameCOMMENT_LINE;
		}
		int prefixEnd = commentToken.originalStart + 1;
		if (!prefix.hasNLSTag())
			prefixEnd = Math.max(prefixEnd, prefix.originalEnd); // comments can start with more than 2 slashes
		prefix = new Token(commentToken.originalStart, prefixEnd, TokenNameCOMMENT_LINE);
		if (whitespace == null) {
			prefix.breakBefore();
			prefix.setWrapPolicy(new WrapPolicy(WrapMode.WHERE_NECESSARY, commentIndex, 0));
		}

		int lineStartIndex = whitespace == null ? 0 : 1;
		for (int i = 0; i < structure.size(); i++) {
			Token token = structure.get(i);
			token.setIndent(indent);
			if (token.hasNLSTag()) {
				this.nlsTags.remove(token);
				continue;
			}
			if (token.isSpaceBefore())
				position++;
			if (token.getLineBreaksBefore() > 0) {
				position = startPosition;
				limit = getLineLimit(position);
				lineStartIndex = whitespace == null ? i : i + 1;
				if (whitespace != null && token != whitespace) {
					token.clearLineBreaksBefore();
					structure.add(i, whitespace);
					token = whitespace;
				}
			}
			position += this.tm.getLength(token, position);
			if (token.tokenType == TokenNameWHITESPACE)
				limit = getLineLimit(position);
			if (position > limit && i > lineStartIndex + 1) {
				structure.add(i, prefix);
				if (whitespace != null)
					structure.add(i, whitespace);

				structure.removeAll(this.nlsTags);
				structure.addAll(i, this.nlsTags);
				i = i + this.nlsTags.size() - 1;
				this.nlsTags.clear();
			}
		}
		this.nlsTags.clear();
	}

	private int getLineLimit(int startPosition) {
		final int commentLength = this.options.comment_line_length;
		if (!this.options.comment_count_line_length_from_starting_position)
			return commentLength;
		final int pageWidth = this.options.page_width;
		int lineLength = startPosition + commentLength;
		if (lineLength > pageWidth && commentLength <= pageWidth)
			lineLength = pageWidth;
		return lineLength;
	}
}
