/*******************************************************************************
 * Copyright (c) 2000, 2019 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
 *     Fraunhofer FIRST - extended API and implementation
 *     Technical University Berlin - extended API and implementation
 *     Jesper Steen Moller - Contributions for
 *								bug 404146 - [1.7][compiler] nested try-catch-finally-blocks leads to unrunnable Java byte code
 *     Harry Terkelsen (het@google.com) - Bug 449262 - Allow the use of third-party Java formatters
 *     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
 *     Lars Vogel <Lars.Vogel@vogella.com> - Contributions for
 *     						Bug 473178
 *******************************************************************************/
package org.eclipse.jdt.internal.formatter;

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.TokenNameEOF;
import static org.eclipse.jdt.internal.compiler.parser.TerminalTokens.TokenNameNotAToken;

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

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IModuleDescription;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.IProblem;
import org.eclipse.jdt.core.compiler.InvalidInputException;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.Comment;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.parser.Scanner;
import org.eclipse.jdt.internal.compiler.util.Util;
import org.eclipse.jdt.internal.core.JavaProject;
import org.eclipse.jdt.internal.core.SourceModule;
import org.eclipse.jdt.internal.formatter.linewrap.CommentWrapExecutor;
import org.eclipse.jdt.internal.formatter.linewrap.WrapPreparator;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.Region;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.TextEdit;

public class DefaultCodeFormatter extends CodeFormatter {

	/**
	 * Debug trace
	 */
	public static boolean DEBUG = false;

	private static final int K_COMMENTS_MASK = K_SINGLE_LINE_COMMENT
		| K_MULTI_LINE_COMMENT
		| K_JAVA_DOC;

	// Mask for code formatter kinds
	private static final int K_MASK = K_UNKNOWN
		| K_EXPRESSION
		| K_STATEMENTS
//{ObjectTeams: another root node for parsing/formatting:
		| K_PARAMETER_MAPPING
// SH}
		| K_CLASS_BODY_DECLARATIONS
		| K_COMPILATION_UNIT
		| K_MODULE_INFO
		| K_COMMENTS_MASK;

	private static final Map<Integer, Integer> FORMAT_TO_PARSER_KIND = new HashMap<>();
	static {
		FORMAT_TO_PARSER_KIND.put(K_COMPILATION_UNIT, ASTParser.K_COMPILATION_UNIT);
		FORMAT_TO_PARSER_KIND.put(K_MODULE_INFO, ASTParser.K_COMPILATION_UNIT);
		FORMAT_TO_PARSER_KIND.put(K_CLASS_BODY_DECLARATIONS, ASTParser.K_CLASS_BODY_DECLARATIONS);
		FORMAT_TO_PARSER_KIND.put(K_STATEMENTS, ASTParser.K_STATEMENTS);
		FORMAT_TO_PARSER_KIND.put(K_EXPRESSION, ASTParser.K_EXPRESSION);
	}

	private DefaultCodeFormatterOptions originalOptions;
	private DefaultCodeFormatterOptions workingOptions;

	private Object oldCommentFormatOption;
	private String sourceLevel;
	public boolean previewEnabled;

	private String sourceString;
	char[] sourceArray;
	private List<IRegion> formatRegions;

	private ASTNode astRoot;
	private List<Token> tokens = new ArrayList<>();
	private TokenManager tokenManager;
//{ObjectTeams: flag recovered from option set in org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteFormatter.formatNode(ASTNode, String, int):
	private boolean isOTJCode;
// SH}

	public DefaultCodeFormatter() {
		this(new DefaultCodeFormatterOptions(DefaultCodeFormatterConstants.getJavaConventionsSettings()), null);
	}

	public DefaultCodeFormatter(DefaultCodeFormatterOptions options) {
		this(options, null);
	}

	public DefaultCodeFormatter(Map<String, String> options) {
		this(null, options);
	}

	public DefaultCodeFormatter(DefaultCodeFormatterOptions defaultCodeFormatterOptions, Map<String, String> options) {
		initOptions(defaultCodeFormatterOptions, options);
	}

	private void initOptions(DefaultCodeFormatterOptions defaultCodeFormatterOptions, Map<String, String> options) {
		if (options != null) {
			this.originalOptions = new DefaultCodeFormatterOptions(options);
			this.workingOptions = new DefaultCodeFormatterOptions(options);
			this.oldCommentFormatOption = getOldCommentFormatOption(options);
			String compilerSource = options.get(CompilerOptions.OPTION_Source);
			this.sourceLevel = compilerSource != null ? compilerSource : CompilerOptions.VERSION_12;
			this.previewEnabled = JavaCore.ENABLED.equals(options.get(JavaCore.COMPILER_PB_ENABLE_PREVIEW_FEATURES));
		} else {
			Map<String, String> settings = DefaultCodeFormatterConstants.getJavaConventionsSettings();
			this.originalOptions = new DefaultCodeFormatterOptions(settings);
			this.workingOptions = new DefaultCodeFormatterOptions(settings);
			this.oldCommentFormatOption = DefaultCodeFormatterConstants.TRUE;
			this.sourceLevel = CompilerOptions.VERSION_12;
		}
		if (defaultCodeFormatterOptions != null) {
			this.originalOptions.set(defaultCodeFormatterOptions.getMap());
			this.workingOptions.set(defaultCodeFormatterOptions.getMap());
		}
//{ObjectTeams: see ASTRewriteFormatter.formatNode(ASTNode, String, int):
		this.isOTJCode = options != null && JavaCore.DISABLED.equals(options.get(JavaCore.COMPILER_OPT_SCOPED_KEYWORDS));
// SH}
	}

	@Deprecated
	private Object getOldCommentFormatOption(Map<String, String> options) {
		return options.get(DefaultCodeFormatterConstants.FORMATTER_COMMENT_FORMAT);
	}

	@Override
	public String createIndentationString(final int indentationLevel) {
		if (indentationLevel < 0) {
			throw new IllegalArgumentException();
		}

		StringBuilder sb = new StringBuilder();
		int indent = indentationLevel * this.originalOptions.indentation_size;
		TextEditsBuilder.appendIndentationString(sb, this.originalOptions.tab_char, this.originalOptions.tab_size,
				indent, 0);
		return sb.toString();
	}

	/**
	 * @see org.eclipse.jdt.core.formatter.CodeFormatter#format(int, java.lang.String, int, int, int, java.lang.String)
	 */
	@Override
	public TextEdit format(int kind, String source, int offset, int length, int indentationLevel, String lineSeparator) {
		return format(kind, source, new IRegion[] { new Region(offset, length) }, indentationLevel, lineSeparator);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public TextEdit format(int kind, String source, IRegion[] regions, int indentationLevel, String lineSeparator) {
		if (!regionsSatisfiesPreconditions(regions, source.length())) {
			throw new IllegalArgumentException();
		}
		this.formatRegions = Arrays.asList(regions);

		updateWorkingOptions(indentationLevel, lineSeparator, kind);

		if ((kind & K_COMMENTS_MASK) != 0)
			return formatComments(source, kind & K_COMMENTS_MASK);

		if (prepareFormattedCode(source, kind) == null)
			return this.tokens.isEmpty() ? new MultiTextEdit() : null;

		MultiTextEdit result = new MultiTextEdit();
		TextEditsBuilder resultBuilder = new TextEditsBuilder(this.sourceString, this.formatRegions, this.tokenManager,
				this.workingOptions);
		this.tokenManager.traverse(0, resultBuilder);
		for (TextEdit edit : resultBuilder.getEdits()) {
			result.addChild(edit);
		}
		return result;
	}

	private boolean init(String source, int kind) {

		// this is convenient for debugging (see Token.toString())
		// Token.source = source;

		this.sourceString = source;
		this.sourceArray = source.toCharArray();
		this.tokens.clear();
		this.tokenManager = new TokenManager(this.tokens, source, this.workingOptions);

		tokenizeSource(kind);
		return !this.tokens.isEmpty();
	}

	List<Token> prepareFormattedCode(String source) {
		this.formatRegions = Arrays.asList(new Region(0, source.length()));
		return prepareFormattedCode(source, CodeFormatter.K_UNKNOWN);
	}

	private List<Token> prepareFormattedCode(String source, int kind) {
		if (!init(source, kind))
			return null;

		this.astRoot = parseSourceCode(kind);
		if (this.astRoot == null)
			return null;

		if (kind != CodeFormatter.K_UNKNOWN)
			findHeader();

		prepareSpaces();
		prepareLineBreaks();
		prepareComments();
		prepareWraps(kind);

		return this.tokens;
	}

	private void findHeader() {
		if (this.astRoot instanceof CompilationUnit) {
			CompilationUnit unit = (CompilationUnit) this.astRoot;
			List<TypeDeclaration> types = unit.types();
			ASTNode firstElement = types.isEmpty() ? unit.getPackage() : types.get(0);
			if (firstElement != null) {
				int headerEndIndex = this.tokenManager.firstIndexIn(firstElement, -1);
				this.tokenManager.setHeaderEndIndex(headerEndIndex);
			}
		}
	}

	private TextEdit formatComments(String source, int kind) {
		MultiTextEdit result = new MultiTextEdit();
		if (!init(source, kind))
			return result;

		CommentsPreparator commentsPreparator = new CommentsPreparator(this.tokenManager, this.workingOptions,
				this.sourceLevel);
		CommentWrapExecutor commentWrapper = new CommentWrapExecutor(this.tokenManager, this.workingOptions);
		switch (kind) {
			case K_JAVA_DOC:
				for (Token token : this.tokens) {
					if (token.tokenType == TokenNameCOMMENT_JAVADOC) {
						CompilationUnit cu = (CompilationUnit) parseSourceCode(ASTParser.K_COMPILATION_UNIT);
						Javadoc javadoc = (Javadoc) cu.getCommentList().get(0);
						javadoc.accept(commentsPreparator);
						int startPosition = this.tokenManager.findSourcePositionInLine(token.originalStart);
						commentWrapper.wrapMultiLineComment(token, startPosition, false, false);
					}
				}
				break;
			case K_MULTI_LINE_COMMENT:
				for (int i = 0; i < this.tokens.size(); i++) {
					Token token = this.tokens.get(i);
					if (token.tokenType == TokenNameCOMMENT_BLOCK) {
						commentsPreparator.handleBlockComment(i);
						int startPosition = this.tokenManager.findSourcePositionInLine(token.originalStart);
						commentWrapper.wrapMultiLineComment(token, startPosition, false, false);
					}
				}
				break;
			case K_SINGLE_LINE_COMMENT:
				for (int i = 0; i < this.tokens.size(); i++) {
					Token token = this.tokens.get(i);
					if (token.tokenType == TokenNameCOMMENT_LINE) {
						commentsPreparator.handleLineComment(i);
						if (i >= this.tokens.size() || this.tokens.get(i) != token) {
							// current token has been removed and merged with previous one
							i--;
							token = this.tokens.get(i);
						}
						int startPosition = this.tokenManager.findSourcePositionInLine(token.originalStart);
						commentWrapper.wrapLineComment(token, startPosition);
					}
				}
				break;
			default:
				throw new AssertionError(String.valueOf(kind));
		}

		applyFormatOff();

		TextEditsBuilder resultBuilder = new TextEditsBuilder(source, this.formatRegions, this.tokenManager,
				this.workingOptions);
		resultBuilder.setAlignChar(DefaultCodeFormatterOptions.SPACE);
		for (Token token : this.tokens) {
			List<Token> structure = token.getInternalStructure();
			if (structure != null && !structure.isEmpty())
				resultBuilder.processComment(token);
		}

		for (TextEdit edit : resultBuilder.getEdits()) {
			result.addChild(edit);
		}
		return result;
	}

	private ASTNode parseSourceCode(int kind) {
		kind = kind & K_MASK;
		if (kind != K_UNKNOWN) {
			ASTNode astNode = createParser(kind).createAST(null);
			if (kind == K_COMPILATION_UNIT || kind == K_MODULE_INFO)
				return astNode;
			return hasErrors(astNode) ? null : astNode;
		}

		int[] kindsToTry = { K_COMPILATION_UNIT, K_EXPRESSION, K_CLASS_BODY_DECLARATIONS, K_STATEMENTS, K_MODULE_INFO };
		for (int kindToTry : kindsToTry) {
			ASTNode astNode = createParser(kindToTry).createAST(null);
			if (!hasErrors(astNode)) {
				if (kindToTry == K_MODULE_INFO) 
					tokenizeSource(kindToTry); // run scanner again to get module specific tokens
				return astNode;
			}
		}
		return null;
	}

	private ASTParser createParser(int kind) {
		ASTParser parser = ASTParser.newParser(AST.JLS12);

		if (kind == K_MODULE_INFO) {
			parser.setSource(createDummyModuleInfoCompilationUnit());
		} else {
			parser.setSource(this.sourceArray);
		}
		parser.setKind(FORMAT_TO_PARSER_KIND.get(kind));

		Map<String, String> parserOptions = JavaCore.getOptions();
		parserOptions.put(CompilerOptions.OPTION_Source, this.sourceLevel);
		parserOptions.put(CompilerOptions.OPTION_DocCommentSupport, CompilerOptions.ENABLED);
		parserOptions.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED); //TODO
		parserOptions.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.IGNORE);
//{ObjectTeams:
		parserOptions.put(CompilerOptions.OPTION_PureJavaOnly, this.workingOptions.isPureJava ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
		parserOptions.put(CompilerOptions.OPTION_AllowScopedKeywords, this.workingOptions.scopedKeywords ? CompilerOptions.ENABLED : CompilerOptions.DISABLED);
// SH}
		parser.setCompilerOptions(parserOptions);
		return parser;
	}

	private ICompilationUnit createDummyModuleInfoCompilationUnit() {
		IJavaProject dummyProject = new JavaProject() {
			@Override
			public Map<String, String> getOptions(boolean inheritJavaCoreOptions) {
				return new HashMap<>();
			}

			@Override
			public IModuleDescription getModuleDescription() throws JavaModelException {
				return new SourceModule(this, ""); //$NON-NLS-1$
			}
		};
		return new org.eclipse.jdt.internal.core.CompilationUnit(null, TypeConstants.MODULE_INFO_FILE_NAME_STRING,
				null) {
			@Override
			public char[] getContents() {
				return DefaultCodeFormatter.this.sourceArray;
			}

			@Override
			public IJavaProject getJavaProject() {
				return dummyProject;
			}
		};
	}

	private boolean hasErrors(ASTNode astNode) {
		CompilationUnit root = (CompilationUnit) astNode.getRoot();
		for (IProblem problem : root.getProblems()) {
			if (problem.isError())
				return true;
		}
		return false;
	}

	private void tokenizeSource(int kind) {
		this.tokens.clear();
		Scanner scanner = new Scanner(true, false, false/* nls */, CompilerOptions.versionToJdkLevel(this.sourceLevel),
				null/* taskTags */, null/* taskPriorities */, false/* taskCaseSensitive */, this.previewEnabled);
//{ObjectTeams: allow scoped keywords:
		scanner.parsePureJavaOnly = this.workingOptions.isPureJava;
		scanner.parseOTJonly = this.isOTJCode;
// SH}
		scanner.setSource(this.sourceArray);
		scanner.fakeInModule = (kind & K_MODULE_INFO) != 0;
		while (true) {
			try {
				int tokenType = scanner.getNextToken();
				if (tokenType == TokenNameEOF)
					break;
				Token token = Token.fromCurrent(scanner, tokenType);
				this.tokens.add(token);
			} catch (InvalidInputException e) {
				Token token = Token.fromCurrent(scanner, TokenNameNotAToken);
				this.tokens.add(token);
			}
		}
	}

	private void prepareSpaces() {
		SpacePreparator spacePreparator = new SpacePreparator(this.tokenManager, this.workingOptions);
		this.astRoot.accept(spacePreparator);
		spacePreparator.finishUp();
	}

	private void prepareLineBreaks() {
		LineBreaksPreparator breaksPreparator = new LineBreaksPreparator(this.tokenManager, this.workingOptions);
		this.astRoot.accept(breaksPreparator);
		breaksPreparator.finishUp();
		this.astRoot.accept(new OneLineEnforcer(this.tokenManager, this.workingOptions));
	}

	private void prepareComments() {
		CommentsPreparator commentsPreparator = new CommentsPreparator(this.tokenManager, this.workingOptions,
				this.sourceLevel);
		List<Comment> comments = ((CompilationUnit) this.astRoot.getRoot()).getCommentList();
		for (Comment comment : comments) {
			comment.accept(commentsPreparator);
		}
		commentsPreparator.finishUp();
	}

	private void prepareWraps(int kind) {
		WrapPreparator wrapPreparator = new WrapPreparator(this.tokenManager, this.workingOptions, kind);
		this.astRoot.accept(wrapPreparator);
		applyFormatOff();
		wrapPreparator.finishUp(this.astRoot, this.formatRegions);
	}

	private void applyFormatOff() {
		for (Token[] offPair : this.tokenManager.getDisableFormatTokenPairs()) {
			final int offStart = offPair[0].originalStart;
			final int offEnd = offPair[1].originalEnd;

			offPair[0].setWrapPolicy(null);
			offPair[0]
					.setIndent(Math.min(offPair[0].getIndent(), this.tokenManager.findSourcePositionInLine(offStart)));

			final List<IRegion> result = new ArrayList<>();
			for (IRegion region : this.formatRegions) {
				final int start = region.getOffset(), end = region.getOffset() + region.getLength() - 1;
				if (offEnd < start || end < offStart) {
					result.add(region);
				} else if (offStart <= start && end <= offEnd) {
					// whole region off
				} else {
					if (start < offStart)
						result.add(new Region(start, offStart - start));
					if (offEnd < end)
						result.add(new Region(offEnd + 1, end - offEnd));
				}
			}
			this.formatRegions = result;
		}
	}

	/**
	 * True if
	 * <li>1. All regions are within maxLength
	 * <li>2. regions are sorted
	 * <li>3. regions are not overlapping
	 */
	private boolean regionsSatisfiesPreconditions(IRegion[] regions, int maxLength) {
		int regionsLength = regions == null ? 0 : regions.length;
		if (regionsLength == 0) {
			return false;
		}

		IRegion first = regions[0];
		if (first.getOffset() < 0 || first.getLength() < 0 || first.getOffset() + first.getLength() > maxLength) {
			return false;
		}

		int lastOffset = first.getOffset() + first.getLength() - 1;
		for (int i = 1; i < regionsLength; i++) {
			IRegion current = regions[i];
			if (lastOffset > current.getOffset()) {
				return false;
			}

			if (current.getOffset() < 0 || current.getLength() < 0
					|| current.getOffset() + current.getLength() > maxLength) {
				return false;
			}

			lastOffset = current.getOffset() + current.getLength() - 1;
		}

		return true;
	}

	private void updateWorkingOptions(int indentationLevel, String lineSeparator, int kind) {
		this.workingOptions.line_separator = lineSeparator != null ? lineSeparator
				: this.originalOptions.line_separator;
		if (this.workingOptions.line_separator == null)
			this.workingOptions.line_separator = Util.LINE_SEPARATOR;

		this.workingOptions.initial_indentation_level = indentationLevel;

		this.workingOptions.comment_format_javadoc_comment = this.originalOptions.comment_format_javadoc_comment
				&& canFormatComment(kind, K_JAVA_DOC);
		this.workingOptions.comment_format_block_comment = this.originalOptions.comment_format_block_comment
				&& canFormatComment(kind, K_MULTI_LINE_COMMENT);
		this.workingOptions.comment_format_line_comment = this.originalOptions.comment_format_line_comment
				&& canFormatComment(kind, K_SINGLE_LINE_COMMENT);
	}

	private boolean canFormatComment(int kind, int commentKind) {
		if ((kind & F_INCLUDE_COMMENTS) != 0)
			return true;
		if (DefaultCodeFormatterConstants.FALSE.equals(this.oldCommentFormatOption))
			return false;
		if ((kind & K_MASK) == commentKind)
			return true;
		if (kind == K_UNKNOWN && DefaultCodeFormatterConstants.TRUE.equals(this.oldCommentFormatOption))
			return true;
		return false;
	}

	@Override
	public void setOptions(Map<String, String> options) {
		initOptions(null, options);
	}
}
