/*******************************************************************************
 * Copyright (c) 2014, 2017 Mateusz Matela and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * 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);
		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) {
		int position = this.lineStartPosition + token.getAlign() + token.getIndent();
		if (token.tokenType != TokenNameNotAToken)
			position += COMMENT_LINE_SEPARATOR_LENGTH;
		return position;
	}

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

		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 isFormattedCode = token.getWrapPolicy() != null
					&& token.getWrapPolicy() != WrapPolicy.SUBSTITUTE_ONLY;
			if (!isFormattedCode && token.getAlign() == 0 && !this.simulation) {
				// Indents are reserved for code inside <pre>.
				// Indentation of javadoc tags can be achieved with align
				token.setAlign(token.getIndent());
				token.setIndent(0);
			}
		}

		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;
			}
		}

		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();
				// Indents are reserved for code inside <pre>.
				// Indentation of javadoc tags can be achieved with align
				this.potentialWrapToken.setAlign(this.potentialWrapToken.getIndent());
				this.potentialWrapToken.setIndent(0);
			}
			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;
	}

	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;
	}
}
