/*******************************************************************************
 * Copyright (c) 2014, 2019 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
 *     Mateusz Matela <mateusz.matela@gmail.com> - [formatter] follow up bug for comments - https://bugs.eclipse.org/458208
 *     Mateusz Matela <mateusz.matela@gmail.com> - NPE in WrapExecutor during Java text formatting  - https://bugs.eclipse.org/465669
 *******************************************************************************/
package org.eclipse.jdt.internal.formatter.linewrap;

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.TokenNameCOMMENT_LINE;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameTextBlock;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameWHITESPACE;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;

import org.eclipse.jdt.internal.compiler.parser.ScannerHelper;
import org.eclipse.jdt.internal.formatter.DefaultCodeFormatterOptions;
import org.eclipse.jdt.internal.formatter.DefaultCodeFormatterOptions.Alignment;
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 WrapExecutor {

	private static class WrapInfo {
		public int wrapTokenIndex;
		public int indent;

		public WrapInfo(int wrapIndex, int indent) {
			this.wrapTokenIndex = wrapIndex;
			this.indent = indent;
		}

		public WrapInfo() {
			// empty constructor
		}

		@Override
		public int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + this.indent;
			result = prime * result + this.wrapTokenIndex;
			return result;
		}

		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (getClass() != obj.getClass())
				return false;
			WrapInfo other = (WrapInfo) obj;
			if (this.indent != other.indent)
				return false;
			if (this.wrapTokenIndex != other.wrapTokenIndex)
				return false;
			return true;
		}

	}

	private static class WrapResult {

		public static final WrapResult NO_WRAP_NEEDED = new WrapResult(0, 0, null);

		/** Penalty for used wraps */
		public final double penalty;
		/** Penalty for exceeding line limit and extra lines in comments */
		public final int extraPenalty;
		/**
		 * Contains information about the next wrap in the result or <code>null</code> if this is the last wrap.
		 * Can be used as a key in {@link WrapExecutor#wrapSearchResults} to retrieve the next wraps.
		 */
		public final WrapInfo nextWrap;

		WrapResult(double penalty, int extraPenalty, WrapInfo nextWrap) {
			this.penalty = penalty;
			this.extraPenalty = extraPenalty;
			this.nextWrap = nextWrap;
		}
	}

	private class LineAnalyzer extends TokenTraverser {

		private final TokenManager tm2 = WrapExecutor.this.tm;
		private final CommentWrapExecutor commentWrapper;
		private int lineIndent;
		int firstPotentialWrap;
		int activeTopPriorityWrap;
		int minStructureDepth;
		int extraLines;
		int lineWidthExtent;
		boolean isNextLineWrapped;
		final List<Integer> extraLinesPerComment = new ArrayList<Integer>();
		final List<Integer> topPriorityGroupStarts = new ArrayList<Integer>();
		private int currentTopPriorityGroupEnd;
		private boolean isNLSTagInLine;

		public LineAnalyzer(TokenManager tokenManager, DefaultCodeFormatterOptions options) {
			this.commentWrapper = new CommentWrapExecutor(tokenManager, options);
		}

		/**
		 * @return index of the last token in line
		 */
		public int analyzeLine(int startIndex, int indent) {
			Token startToken = this.tm2.get(startIndex);
			assert startToken.getLineBreaksBefore() > 0;
			this.counter = this.tm2.toIndent(indent, startToken.isWrappable());
			this.lineIndent = indent;
			this.firstPotentialWrap = -1;
			this.activeTopPriorityWrap = -1;
			this.minStructureDepth = Integer.MAX_VALUE;
			this.extraLines = 0;
			this.lineWidthExtent = 0;
			this.isNextLineWrapped = false;
			this.extraLinesPerComment.clear();
			this.topPriorityGroupStarts.clear();
			this.currentTopPriorityGroupEnd = -1;
			this.isNLSTagInLine = false;
			int lastIndex = this.tm2.traverse(startIndex, this);
			return lastIndex + (this.isNextLineWrapped ? 1 : 0);
		}

		@Override
		protected boolean token(Token token, int index) {
			setIndent(token, this.lineIndent);

			if (token.hasNLSTag())
				this.isNLSTagInLine = true;

			if (token.isWrappable()) {
				WrapPolicy wrapPolicy = token.getWrapPolicy();
				if (wrapPolicy.wrapMode == WrapMode.TOP_PRIORITY && getLineBreaksBefore() == 0
						&& index > this.currentTopPriorityGroupEnd) {
					if (isActiveTopPriorityWrap(index, wrapPolicy)) {
						this.activeTopPriorityWrap = index;
					} else {
						this.topPriorityGroupStarts.add(index);
						this.currentTopPriorityGroupEnd = wrapPolicy.groupEndIndex;
					}
					if (this.firstPotentialWrap < 0)
						this.firstPotentialWrap = index;
				} else if (this.firstPotentialWrap < 0 && getWrapIndent(token) < this.counter) {
					this.firstPotentialWrap = index;
				}
				this.minStructureDepth = Math.min(this.minStructureDepth, wrapPolicy.structureDepth);
			}

			if (token.getAlign() > 0) {
				this.counter = token.getAlign();
			} else if (isSpaceBefore() && getLineBreaksBefore() == 0 && index > 0
					&& token.tokenType != TokenNameCOMMENT_LINE) {
				this.counter++;
			}

			if (token.tokenType == TokenNameTextBlock) {
				List<Token> lines = token.getInternalStructure();
				if (lines == null) {
					this.counter = this.tm2.getLength(token, 0);
				} else {
					this.lineWidthExtent = Math.max(this.lineWidthExtent,
							this.counter + this.tm2.getLength(lines.get(0), this.counter));
					this.counter = this.lineIndent + lines.get(1).getIndent();
					lines.stream().skip(1).forEach(e -> this.lineWidthExtent = Math.max(this.lineWidthExtent,
							this.counter + this.tm2.getLength(e, this.counter)));
					this.counter += this.tm2.getLength(lines.get(lines.size() - 1), this.counter);
				}
			} else if (!token.isComment()) {
				this.counter += this.tm2.getLength(token, this.counter);
			} else if (token.tokenType != TokenNameCOMMENT_LINE) {
				this.counter = this.commentWrapper.wrapMultiLineComment(token, this.counter, true, this.isNLSTagInLine);
				this.extraLines += this.commentWrapper.getLinesCount() - 1;
				this.extraLinesPerComment.add(this.commentWrapper.getLinesCount() - 1);
			}

			this.lineWidthExtent = Math.max(this.lineWidthExtent, this.counter);
			if (this.lineWidthExtent > WrapExecutor.this.options.page_width && this.firstPotentialWrap >= 0) {
				return false;
			}

			if (getNext() != null && getNext().isWrappable() && getLineBreaksAfter() > 0) {
				this.isNextLineWrapped = true;
				if (this.firstPotentialWrap < 0)
					this.firstPotentialWrap = index + 1;
				return false; 
			}

			boolean isLineEnd = getLineBreaksAfter() > 0 || getNext() == null || (getNext().isNextLineOnWrap()
					&& this.tm2.get(this.tm2.findFirstTokenInLine(index)).isWrappable());
			return !isLineEnd;
		}

		private boolean isActiveTopPriorityWrap(int index, WrapPolicy wrapPolicy) {
			if (this.activeTopPriorityWrap >= 0)
				return false;

			for (int i = index - 1; i > wrapPolicy.wrapParentIndex; i--) {
				Token token = this.tm2.get(i);
				if (token.isWrappable() && token.getWrapPolicy().wrapParentIndex == wrapPolicy.wrapParentIndex
					&& (token.getLineBreaksBefore() > 0 || this.tm2.get(i - 1).getLineBreaksAfter() > 0)) {
						return true;
				}
			}
			return false;
		}
	}

	private class WrapsApplier extends TokenTraverser {

		private ArrayDeque<Token> stack = new ArrayDeque<>();
		private int initialIndent;
		private int currentIndent;
		private WrapInfo nextWrap;

		public WrapsApplier() {
			// nothing to do
		}

		@Override
		protected boolean token(Token token, int index) {
			if (index == 0 || getLineBreaksBefore() > 0) {
				newLine(token, index);
			} else if ((this.nextWrap != null && index == this.nextWrap.wrapTokenIndex)
					|| checkForceWrap(token, index, this.currentIndent)
					|| (token.isNextLineOnWrap() && WrapExecutor.this.tm
							.get(WrapExecutor.this.tm.findFirstTokenInLine(index)).isWrappable())) {
				token.breakBefore();
				newLine(token, index);
			} else {
				setIndent(token, this.currentIndent);
			}
			return true;
		}

		private void newLine(Token token, int index) {
			while (!this.stack.isEmpty() && index > this.stack.peek().getWrapPolicy().groupEndIndex)
				this.stack.pop();
			if (token.getWrapPolicy() != null) {
				setIndent(token, getWrapIndent(token));
				handleOnColumnIndent(index, token.getWrapPolicy());
				this.stack.push(token);
			} else if (this.stack.isEmpty()) {
				this.initialIndent = token.getIndent();
				WrapExecutor.this.wrapSearchResults.clear();
			}

			this.currentIndent = this.stack.isEmpty() ? this.initialIndent : this.stack.peek().getIndent();
			setIndent(token, this.currentIndent);
			this.nextWrap = findWrapsCached(index, this.currentIndent).nextWrap;
		}
	}

	private class NLSTagHandler extends TokenTraverser {
		private final ArrayList<Token> nlsTags = new ArrayList<Token>();

		public NLSTagHandler() {
			// nothing to do
		}

		@Override
		protected boolean token(final Token token, final int index) {
			if (token.hasNLSTag())
				this.nlsTags.add(token.getNLSTag());

			if (getLineBreaksAfter() > 0 || getNext() == null) {
				// make sure there's a line comment with all necessary NLS tags
				Token lineComment = token;
				if (token.tokenType != TokenNameCOMMENT_LINE) {
					if (this.nlsTags.isEmpty())
						return true;
					lineComment = new Token(token.originalEnd + 1, token.originalEnd + 1, TokenNameCOMMENT_LINE);
					lineComment.breakAfter();
					lineComment.spaceBefore();
					lineComment.setAlign(WrapExecutor.this.tm.getNLSAlign(index));
					lineComment.setInternalStructure(new ArrayList<Token>());
					WrapExecutor.this.tm.insert(index + 1, lineComment);
					structureChanged();
					return true; // will fill the line comment structure in next step
				}

				List<Token> structure = lineComment.getInternalStructure();
				if (structure == null) {
					if (this.nlsTags.isEmpty())
						return true;
					structure = new ArrayList<Token>();
					structure.add(lineComment);
					lineComment.setInternalStructure(structure);
				}

				boolean isPrefixMissing = false;
				for (int i = 0; i < structure.size(); i++) {
					Token fragment = structure.get(i);
					// remove NLS tags that are not associated with this line
					// (these have been added on wrapped lines earlier)
					if (fragment.hasNLSTag()) {
						if (!this.nlsTags.remove(fragment)) {
							if (i == 0)
								isPrefixMissing = true;
							structure.remove(i--);
						} else {
							isPrefixMissing = false;
						}
					} else if (isPrefixMissing) {
						// remove trailing whitespace
						int pos = fragment.originalStart;
						while (pos <= fragment.originalEnd
								&& ScannerHelper.isWhitespace(WrapExecutor.this.tm.charAt(pos)))
							pos++;
						if (pos > fragment.originalEnd) {
							structure.remove(i--);
							continue;
						}
						if (pos > fragment.originalStart) {
							fragment = new Token(pos, fragment.originalEnd, TokenNameCOMMENT_LINE);
							structure.set(i, fragment);
						}

						String fragmentString = WrapExecutor.this.tm.toString(fragment);
						if (!fragmentString.startsWith("//")) { //$NON-NLS-1$
							// forge a prefix
							Token prefix = new Token(lineComment.originalStart, lineComment.originalStart + 1,
									TokenNameCOMMENT_LINE);
							prefix.spaceBefore();
							structure.add(i, prefix);
						}
						isPrefixMissing = false;
					}
				}
				// add all remaining tags in this line
				// (these are currently in a future line comment but will be removed)
				structure.addAll(this.nlsTags);

				if (structure.isEmpty()
						|| (structure.size() == 1 && structure.get(0).tokenType == TokenNameWHITESPACE)) {
					// all the tags have been moved to other lines
					WrapExecutor.this.tm.remove(index);
					structureChanged();
				}

				this.nlsTags.clear();
			}
			return true;
		}
	}

	private final static int[] EMPTY_ARRAY = {};

	final HashMap<WrapInfo, WrapResult> wrapSearchResults = new HashMap<WrapInfo, WrapResult>();
	private final ArrayDeque<WrapInfo> wrapSearchStack = new ArrayDeque<>();

	private final LineAnalyzer lineAnalyzer;

	final TokenManager tm;
	final DefaultCodeFormatterOptions options;

	private final WrapInfo wrapInfoTemp = new WrapInfo();

	public WrapExecutor(TokenManager tokenManager, DefaultCodeFormatterOptions options) {
		this.tm = tokenManager;
		this.options = options;
		this.lineAnalyzer = new LineAnalyzer(tokenManager, options);
	}

	public void executeWraps() {
		this.tm.traverse(0, new WrapsApplier());
		this.tm.traverse(0, new NLSTagHandler());
	}

	WrapResult findWrapsCached(final int startTokenIndex, final int indent) {
		this.wrapInfoTemp.wrapTokenIndex = startTokenIndex;
		this.wrapInfoTemp.indent = indent;
		WrapResult wrapResult = this.wrapSearchResults.get(this.wrapInfoTemp);

		// pre-existing result may be based on different wrapping of earlier tokens and therefore be wrong
		WrapResult wr = wrapResult;
		boolean cacheMissAllowed = true;
		int lookupLimit = 50;
		while (wr != null && wr.nextWrap != null && lookupLimit --> 0) {
			WrapInfo wi = wr.nextWrap;
			Token token = this.tm.get(wi.wrapTokenIndex);
			if (token.getWrapPolicy().wrapParentIndex < startTokenIndex && getWrapIndent(token) != wi.indent) {
				wrapResult = null;
				cacheMissAllowed = false;
				break;
			}
			wr = this.wrapSearchResults.get(wi);
		}

		if (wrapResult != null)
			return wrapResult;

		this.wrapSearchStack.push(new WrapInfo(startTokenIndex, indent));
		if (this.wrapSearchStack.size() > 1 && cacheMissAllowed)
			return null; // cache miss, need to find wraps later in main stack processing

		ArrayList<WrapInfo> reverseStackTemp = new ArrayList<>();
		// run main stack processing
		while (true) {
			final WrapInfo item = this.wrapSearchStack.peek();
			Token token = this.tm.get(item.wrapTokenIndex);
			token.setWrapped(true);
			wrapResult = findWraps(item.wrapTokenIndex, item.indent);

			assert (wrapResult == null) == (this.wrapSearchStack.peek() != item);
			if (wrapResult != null) {
				token.setWrapped(false);
				this.wrapSearchStack.pop();
				this.wrapSearchResults.put(item, wrapResult);
				assert wrapResult.nextWrap == null || this.wrapSearchResults.get(wrapResult.nextWrap) != null; 
				if (item.wrapTokenIndex == startTokenIndex && item.indent == indent)
					break;
			} else {
				// reverse order of new items
				while (this.wrapSearchStack.peek() != item)
					reverseStackTemp.add(this.wrapSearchStack.pop());
				for (WrapInfo item2 : reverseStackTemp)
					this.wrapSearchStack.push(item2);
				reverseStackTemp.clear();
			}
		}
		assert wrapResult != null;
		return wrapResult;
	}

	/**
	 * The main algorithm that looks for optimal places to wrap.
	 * Calls itself recursively to get results for wrapped sub-lines.  
	 */
	private WrapResult findWraps(int wrapTokenIndex, int indent) {
		final int lastIndex = this.lineAnalyzer.analyzeLine(wrapTokenIndex, indent);
		final boolean nextLineWrapped = this.lineAnalyzer.isNextLineWrapped;
		int lineOverflow = Math.max(0, this.lineAnalyzer.lineWidthExtent - this.options.page_width);
		final boolean wrapRequired = lineOverflow > 0 || nextLineWrapped;
		int extraLines = this.lineAnalyzer.extraLines;
		final int firstPotentialWrap = this.lineAnalyzer.firstPotentialWrap;
		final int activeTopPriorityWrap = this.lineAnalyzer.activeTopPriorityWrap;

		final int[] extraLinesPerComment = toArray(this.lineAnalyzer.extraLinesPerComment);
		int commentIndex = extraLinesPerComment.length;

		final int[] topPriorityGroupStarts = toArray(this.lineAnalyzer.topPriorityGroupStarts);
		int topPriorityIndex = topPriorityGroupStarts.length - 1;
		int nearestGroupEnd = topPriorityIndex == -1 ? 0
				: this.tm.get(topPriorityGroupStarts[topPriorityIndex]).getWrapPolicy().groupEndIndex;

		double bestTotalPenalty = getWrapPenalty(wrapTokenIndex, indent, lastIndex + 1, -1, WrapResult.NO_WRAP_NEEDED);
		int bestExtraPenalty = lineOverflow + extraLines;
		int bestNextWrap = -1;
		int bestIndent = 0;
		boolean cacheMiss = false;

		if (!wrapRequired && activeTopPriorityWrap < 0
				&& (!this.options.join_wrapped_lines || !this.options.wrap_outer_expressions_when_nested)) {
			return new WrapResult(bestTotalPenalty, bestExtraPenalty, null);
		}

		// optimization: if there's a possible wrap at depth lower than line start, ignore the rest
		int depthLimit = Integer.MAX_VALUE;
		Token token = this.tm.get(wrapTokenIndex);
		if (token.isWrappable() && this.options.wrap_outer_expressions_when_nested && activeTopPriorityWrap < 0) {
			int currentDepth = token.getWrapPolicy().structureDepth;
			if (this.lineAnalyzer.minStructureDepth < currentDepth)
				depthLimit = currentDepth;
		}
		// optimization: turns out there's no point checking multiple wraps with the same policy 
		LinkedHashSet<WrapPolicy> policiesTried = new LinkedHashSet<>();

		for (int i = lastIndex; firstPotentialWrap >= 0 && i >= firstPotentialWrap; i--) {
			token = this.tm.get(i);
			if (commentIndex > 0
					&& (token.tokenType == TokenNameCOMMENT_BLOCK || token.tokenType == TokenNameCOMMENT_JAVADOC)) {
				extraLines -= extraLinesPerComment[--commentIndex];
				if (extraLinesPerComment[commentIndex] > 0)
					policiesTried.clear();
			}
			if (topPriorityIndex >= 0 && i <= nearestGroupEnd) {
				if (i > topPriorityGroupStarts[topPriorityIndex])
					continue;
				assert i == topPriorityGroupStarts[topPriorityIndex];
				topPriorityIndex--;
				nearestGroupEnd = topPriorityIndex == -1 ? 0
						: this.tm.get(topPriorityGroupStarts[topPriorityIndex]).getWrapPolicy().groupEndIndex;
			}

			WrapPolicy wrapPolicy = token.getWrapPolicy();
			if (!token.isWrappable()
					|| (activeTopPriorityWrap >= 0 && i != activeTopPriorityWrap)
					|| policiesTried.contains(wrapPolicy)
					|| wrapPolicy.structureDepth >= depthLimit)
				continue;
			policiesTried.add(wrapPolicy);

			int nextWrapIndent = getWrapIndent(token);
			WrapResult nextWrapResult = findWrapsCached(i, nextWrapIndent);
			cacheMiss |= nextWrapResult == null;
			if (cacheMiss)
				continue;

			double totalPenalty = getWrapPenalty(wrapTokenIndex, indent, i, nextWrapIndent, nextWrapResult);
			int totalExtraPenalty = nextWrapResult.extraPenalty + extraLines;
			if (lineOverflow > 0) {
				int position = this.tm.getPositionInLine(i - 1);
				position += this.tm.getLength(this.tm.get(i - 1), position);
				lineOverflow = position - this.options.page_width;
				totalExtraPenalty += Math.max(0, lineOverflow);
			}
			boolean isBetter = totalExtraPenalty < bestExtraPenalty
					|| i == activeTopPriorityWrap
					|| (bestNextWrap < 0 && wrapRequired);
			if (!isBetter && totalExtraPenalty == bestExtraPenalty)
				isBetter = totalPenalty < bestTotalPenalty || bestTotalPenalty == Double.MAX_VALUE;
			if (isBetter) {
				bestTotalPenalty = totalPenalty;
				bestExtraPenalty = totalExtraPenalty;
				bestNextWrap = i;
				bestIndent = nextWrapIndent;

				if (!this.options.wrap_outer_expressions_when_nested || i == activeTopPriorityWrap || nextLineWrapped)
					break;
			}
		}
		if (cacheMiss)
			return null;

		return new WrapResult(bestTotalPenalty, bestExtraPenalty,
				bestNextWrap == -1 ? null : new WrapInfo(bestNextWrap, bestIndent));
	}

	private double getWrapPenalty(int lineStartIndex, int lineIndent, int wrapIndex, int wrapIndent,
			WrapResult wrapResult) {
		WrapPolicy wrapPolicy = null;
		Token wrapToken = null;
		if (wrapIndex < this.tm.size()) {
			wrapToken = this.tm.get(wrapIndex);
			wrapPolicy = wrapToken.getWrapPolicy();
			if (wrapIndent < 0)
				wrapIndent = getWrapIndent(this.tm.get(wrapIndex));
		}

		double penalty = wrapToken != null && wrapToken.isWrappable() ? getPenalty(wrapPolicy) : 0;

		// First parameter in method invocation has higher penalty to make wrapping more similar to the old formatter.
		// This can lead to an undesired effect like this (should wrap aaaaaa and bbbbbb, not .bar):
		// foo.foo
		// 		.bar(aaaaaa,
		// 				bbbbbbb);
		if (wrapIndent > lineIndent)
			penalty *= 1 + 3.0 / 16;

		// Avoid ugly formations like this (bar2 should be wrapped):
		// foooooo(bar1(aaaaaa,
		// 		bbb), bar2(aaa,
		// 				bbbbbb)
		// Assuming lineStartIndex is at bbb, look for unwrapped bar2 and if found,
		// add more penalty than if it was wrapped.
		Token lineStartToken = this.tm.get(lineStartIndex);
		WrapPolicy lineStartWrapPolicy = lineStartToken.getWrapPolicy();
		if (wrapToken != null && wrapToken.isWrappable() && lineStartToken.isWrappable()) {
			for (int i = lineStartIndex + 1; i < wrapIndex; i++) {
				WrapPolicy intermediatePolicy = this.tm.get(i).getWrapPolicy();
				if (intermediatePolicy != null
						&& intermediatePolicy.structureDepth < lineStartWrapPolicy.structureDepth
						&& intermediatePolicy.structureDepth < wrapPolicy.structureDepth) {
					penalty += getPenalty(intermediatePolicy) * 1.25;
				}
			}
		}

		// In the previous example, bar1 should be wrapped too, to emphasize that bar1 and bar2 are the same level.
		// Assuming wrapIndex is at bar1, check if there is a higher depth wrap (bbb) followed by
		// a wrap of the same parent (bar2). If so, then bar1 must be wrapped (so give it negative penalty).
		// Update: Actually, every token that is followed by a higher level depth wrap should be also wrapped,
		// as long as this next wrap is not the last in line and the token is not the first in its wrap group.
		WrapInfo nextWrap = wrapResult.nextWrap;
		boolean checkDepth = wrapToken != null && wrapToken.isWrappable()
				&& (lineStartWrapPolicy == null || wrapPolicy.structureDepth >= lineStartWrapPolicy.structureDepth);
		double penaltyDiff = 0;
		while (checkDepth && nextWrap != null) {
			WrapPolicy nextPolicy = this.tm.get(nextWrap.wrapTokenIndex).getWrapPolicy();
			if (nextPolicy.wrapParentIndex == wrapPolicy.wrapParentIndex
					|| (penaltyDiff != 0 && !wrapPolicy.isFirstInGroup)) {
				penalty -= penaltyDiff * (1 + 1.0 / 64);
				break;
			}
			if (nextPolicy.structureDepth <= wrapPolicy.structureDepth)
				break;
			penaltyDiff = Math.max(penaltyDiff, getPenalty(nextPolicy));
			nextWrap = this.wrapSearchResults.get(nextWrap).nextWrap;
		}

		return penalty + wrapResult.penalty;
	}

	private double getPenalty(WrapPolicy policy) {
		return Math.exp(policy.structureDepth) * policy.penaltyMultiplier;
	}

	boolean checkForceWrap(Token token, int index, int currentIndent) {
		// A token that will have smaller indent when wrapped than the current line indent,
		// should be wrapped because it's a low depth token following some complex wraps of higher depth.
		// This rule could not be implemented in getWrapPenalty() because a token's wrap indent may depend
		// on wraps in previous lines, which are not determined yet when the token's penalty is calculated.
		if (!token.isWrappable() || !this.options.wrap_outer_expressions_when_nested
				|| getWrapIndent(token) >= currentIndent)
			return false;
		WrapPolicy lineStartPolicy = this.tm.get(this.tm.findFirstTokenInLine(index, false, true)).getWrapPolicy();
		return lineStartPolicy != null && lineStartPolicy.wrapMode != WrapMode.BLOCK_INDENT;
	}

	private int[] toArray(List<Integer> list) {
		if (list.isEmpty())
			return EMPTY_ARRAY;
		int[] result = new int[list.size()];
		int i = 0;
		for (int item : list) {
			result[i++] = item;
		}
		return result;
	}

	void handleOnColumnIndent(int tokenIndex, WrapPolicy wrapPolicy) {
		if (wrapPolicy != null && wrapPolicy.indentOnColumn && !wrapPolicy.isFirstInGroup
				&& this.options.tab_char == DefaultCodeFormatterOptions.TAB
				&& !this.options.use_tabs_only_for_leading_indentations) {
			// special case: first wrap in a group should be aligned on column even if it's not wrapped
			for (int i = tokenIndex - 1; i >= 0; i--) {
				Token token = this.tm.get(i);
				WrapPolicy wrapPolicy2 = token.getWrapPolicy();
				if (wrapPolicy2 != null && wrapPolicy2.isFirstInGroup
						&& wrapPolicy2.wrapParentIndex == wrapPolicy.wrapParentIndex) {
					token.setAlign(getWrapIndent(token));
					break;
				}
			}
		}
	}

	int getWrapIndent(Token token) {
		WrapPolicy policy = token.getWrapPolicy();
		if (policy == null)
			return token.getIndent();
		if (policy == WrapPolicy.FORCE_FIRST_COLUMN)
			return 0;

		Token wrapParent = this.tm.get(policy.wrapParentIndex);
		int wrapIndent = wrapParent.getIndent();
		if (policy.indentOnColumn) {
			wrapIndent = this.tm.getPositionInLine(policy.wrapParentIndex);
			wrapIndent += this.tm.getLength(wrapParent, wrapIndent);
			Token next = this.tm.get(policy.wrapParentIndex + 1);
			if (wrapParent.isSpaceAfter() || (next.isSpaceBefore() && !next.isComment()))
				wrapIndent++;
		}
		wrapIndent += policy.extraIndent;
		return this.tm.toIndent(wrapIndent, true);
	}

	void setIndent(Token token, int indent) {
		token.setIndent(indent);

		List<Token> structure = token.getInternalStructure();
		if (token.tokenType == TokenNameTextBlock && structure != null) {
			int lineIndent;
			int indentOption = this.options.text_block_indentation;
			if (indentOption == Alignment.M_INDENT_BY_ONE) {
				lineIndent = 1 * this.options.indentation_size;
			} else if (indentOption == Alignment.M_INDENT_DEFAULT) {
				lineIndent = this.options.continuation_indentation * this.options.indentation_size;
			} else if (indentOption == Alignment.M_INDENT_ON_COLUMN) {
				lineIndent = this.tm.toIndent(this.tm.getPositionInLine(this.tm.indexOf(token)), true) - indent;
			} else {
				assert false;
				lineIndent = 0;
			}
			structure.stream().skip(1).forEach(t -> t.setIndent(lineIndent));
		}
	}
}
