/*******************************************************************************
 * Copyright (c) 2007, 2011 Wind River Systems, Inc. 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:
 *     Anton Leherbauer (Wind River Systems) - initial API and implementation
 *     Andrew Gvozdev
 *******************************************************************************/
package org.eclipse.cdt.ui.tests.text;

import org.eclipse.cdt.core.CCorePlugin;
import org.eclipse.cdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.cdt.core.model.ICProject;
import org.eclipse.cdt.core.testplugin.CProjectHelper;
import org.eclipse.cdt.internal.core.model.ext.SourceRange;
import org.eclipse.cdt.internal.ui.editor.CEditor;
import org.eclipse.cdt.ui.testplugin.EditorTestHelper;
import org.eclipse.cdt.ui.testplugin.ResourceTestHelper;
import org.eclipse.cdt.ui.tests.BaseUITestCase;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;

import junit.framework.TestSuite;

/**
 * Tests for the AddBlockCommentAction.
 *
 * @since 5.0
 */
public class AddBlockCommentTest extends BaseUITestCase {
	private ICProject fCProject;

	public static TestSuite suite() {
		return suite(AddBlockCommentTest.class, "_");
	}

	private CEditor fEditor;
	private IDocument fDocument;

	/*
	 * The class describes a position on a line counting in ordinary people way,
	 * starting from 1.
	 */
	static class LinePosition {
		private int line;
		private int position;
		private IDocument fDoc;

		LinePosition(int line, int positionOnLine, IDocument doc) {
			this.line = line;
			this.position = positionOnLine;
			this.fDoc = doc;
		}

		int getOffset() throws BadLocationException {
			return fDoc.getLineOffset(line - 1) + position - 1;
		}
	}

	@Override
	protected void setUp() throws Exception {
		super.setUp();

		final String PROJECT = "BlockComment";
		// Using any existing file just to open CEditor, the content is not used
		final String filename = "/BlockComment/src/sample/Before.cpp";
		fCProject = EditorTestHelper.createCProject(PROJECT, "resources/formatter");
		fCProject.setOption(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, CCorePlugin.TAB);
		fEditor = (CEditor) EditorTestHelper.openInEditor(ResourceTestHelper.findFile(filename), true);
		fDocument = EditorTestHelper.getSourceViewer(fEditor).getDocument();
		// Delete contents
		fDocument.set("");
	}

	@Override
	protected void tearDown() throws Exception {
		EditorTestHelper.closeEditor(fEditor);

		if (fCProject != null)
			CProjectHelper.delete(fCProject);

		super.tearDown();
	}

	/**
	 * Run an action to comment block defined by line positions
	 * and assert that the result matches the expected result.
	 * "Before" and "After" are taken from test comments.
	 *
	 * @param startLinePosition
	 * @param endLinePosition
	 * @throws Exception
	 */
	protected void assertFormatterResult(LinePosition startLinePosition, LinePosition endLinePosition)
			throws Exception {
		StringBuilder[] contents = getContentsForTest(2);
		String before = contents[0].toString();
		String after = contents[1].toString();

		fDocument.set(before);

		SourceRange range = new SourceRange(startLinePosition.getOffset(),
				endLinePosition.getOffset() - startLinePosition.getOffset());
		fEditor.setSelection(range, true);

		IAction commentAction = fEditor.getAction("AddBlockComment");
		assertNotNull("No AddBlockComment action", commentAction);
		commentAction.setEnabled(true);
		commentAction.run();

		String expected = after;
		assertEquals(expected, fDocument.get());
	}

	/**
	 * Run an action to comment block defined by line positions
	 * and assert that the result matches the expected result.
	 * "Before" and "After" are taken from test comments.
	 *
	 * @param startLinePosition
	 * @param endLinePosition
	 * @param before editor contents before the operation
	 * @param after expected editor contents after the operation
	 * @throws Exception
	 */
	protected void assertFormatterResult(LinePosition startLinePosition, LinePosition endLinePosition, String before,
			String after) throws Exception {
		fDocument.set(before);

		SourceRange range = new SourceRange(startLinePosition.getOffset(),
				endLinePosition.getOffset() - startLinePosition.getOffset());
		fEditor.setSelection(range, true);

		IAction commentAction = fEditor.getAction("AddBlockComment");
		assertNotNull("No AddBlockComment action", commentAction);
		commentAction.setEnabled(true);
		commentAction.run();

		String expected = after;
		assertEquals(expected, fDocument.get());
	}

	//int i, j, k;

	//int i, /*j,*/ k;
	public void testCommentPlain() throws Exception {
		LinePosition startSelection = new LinePosition(1, 8, fDocument);
		LinePosition endSelection = new LinePosition(1, 10, fDocument);
		assertFormatterResult(startSelection, endSelection);
	}

	//int i,
	//    j,
	//    k;

	//int /*i,
	//    j,*/
	//    k;
	public void testCommentPartialLines1() throws Exception {
		LinePosition startSelection = new LinePosition(1, 5, fDocument);
		LinePosition endSelection = new LinePosition(2, 7, fDocument);
		assertFormatterResult(startSelection, endSelection);
	}

	//int i,
	//    j,
	//    k;

	//int i,
	///*    j,
	//    k*/;
	public void testCommentPartialLines2() throws Exception {
		LinePosition startSelection = new LinePosition(2, 1, fDocument);
		LinePosition endSelection = new LinePosition(3, 6, fDocument);
		assertFormatterResult(startSelection, endSelection);
	}

	//int i;
	//int j;
	//int k;

	//int i;
	///*int j;*/
	//int k;
	public void testCommentExactlyOneLine() throws Exception {
		LinePosition startSelection = new LinePosition(2, 1, fDocument);
		LinePosition endSelection = new LinePosition(3, 1, fDocument);
		assertFormatterResult(startSelection, endSelection);
	}

	//int i;
	//int j;
	//int k;
	//int l;

	//int i;
	///*
	//int j;
	//int k;
	//*/
	//int l;
	public void testCommentTwoOrMoreLines() throws Exception {
		LinePosition startSelection = new LinePosition(2, 1, fDocument);
		LinePosition endSelection = new LinePosition(4, 1, fDocument);
		assertFormatterResult(startSelection, endSelection);
	}

	//const int i;

	///*const*/ int i;
	public void testCommentFirstCharacterInFile() throws Exception {
		LinePosition startSelection = new LinePosition(1, 1, fDocument);
		LinePosition endSelection = new LinePosition(1, 6, fDocument);
		assertFormatterResult(startSelection, endSelection);
	}

	//#include <x>
	//#include <y>

	///*#include <x>*/
	//#include <y>
	public void testCommentPreprocessorFirstLine() throws Exception {
		LinePosition startSelection = new LinePosition(1, 1, fDocument);
		LinePosition endSelection = new LinePosition(1, 6, fDocument);
		assertFormatterResult(startSelection, endSelection);
	}

	//int i; // comment
	//int j;

	//int i; /*// comment*/
	//int j;
	public void testCommentCppComment() throws Exception {
		LinePosition startSelection = new LinePosition(1, 10, fDocument);
		LinePosition endSelection = new LinePosition(1, 12, fDocument);
		assertFormatterResult(startSelection, endSelection);
	}

	//#include <x>
	//#include <y>
	//#include <z>

	//#include <x>
	///*#include <y>*/
	//#include <z>
	public void testCommentSpecialPartition() throws Exception {
		LinePosition startSelection = new LinePosition(2, 1, fDocument);
		LinePosition endSelection = new LinePosition(3, 1, fDocument);
		assertFormatterResult(startSelection, endSelection);
	}

	//#include <x>
	//   #include \
	//      <y>
	//#include <z>

	//#include <x>
	///*
	//   #include \
	//      <y>
	//*/
	//#include <z>
	public void testCommentSpecialPartitionExtra() throws Exception {
		LinePosition startSelection = new LinePosition(2, 8, fDocument);
		LinePosition endSelection = new LinePosition(2, 10, fDocument);
		assertFormatterResult(startSelection, endSelection);
	}

	///*comment*/
	//int i;

	///*comment*/
	//int i;
	public void testCommentCommentNoScrewUp() throws Exception {
		LinePosition startSelection = new LinePosition(1, 1, fDocument);
		LinePosition endSelection = new LinePosition(2, 1, fDocument);
		assertFormatterResult(startSelection, endSelection);
	}

	//int i;
	///*comment*/
	//int j;

	///*int i;
	//comment*/
	//int j;
	public void testCommentMergeUp() throws Exception {
		LinePosition startSelection = new LinePosition(1, 1, fDocument);
		LinePosition endSelection = new LinePosition(2, 5, fDocument);
		assertFormatterResult(startSelection, endSelection);
	}

	//int i;
	///*comment*/
	//int j;

	//int i;
	///*comment
	//int j;*/
	public void testCommentMergeDown() throws Exception {
		LinePosition startSelection = new LinePosition(2, 5, fDocument);
		LinePosition endSelection = new LinePosition(3, 7, fDocument);
		assertFormatterResult(startSelection, endSelection);
	}

	///*comment1*/
	///*comment2*/
	//int i;

	///*comment1
	//comment2*/
	//int i;
	public void testCommentMergeComments() throws Exception {
		LinePosition startSelection = new LinePosition(1, 5, fDocument);
		LinePosition endSelection = new LinePosition(2, 5, fDocument);
		assertFormatterResult(startSelection, endSelection);
	}

	//
	//

	//
	///*
	//
	//*/
	public void testCommentEndOfFileNoLoopingPlease() throws Exception {
		// Don't care much about formatting but no looping please
		LinePosition startSelection = new LinePosition(2, 1, fDocument);
		LinePosition endSelection = new LinePosition(3, 1, fDocument);
		assertFormatterResult(startSelection, endSelection);
	}

	public void testCommentLastCharacterNoEOL() throws Exception {
		String before = "int i;";
		String after = "/*int i;*/";
		LinePosition startSelection = new LinePosition(1, 1, fDocument);
		LinePosition endSelection = new LinePosition(1, 7, fDocument);
		assertFormatterResult(startSelection, endSelection, before, after);
	}

	public void testCommentLastCppCommentNoEOL() throws Exception {
		String before = "//int i;";
		String after = "/*//int i;*/";
		LinePosition startSelection = new LinePosition(1, 3, fDocument);
		LinePosition endSelection = new LinePosition(1, 7, fDocument);
		assertFormatterResult(startSelection, endSelection, before, after);
	}

	public void testMixedEOLs() throws Exception {
		String before = "int i;\r\n" + "int j;\n" + "int k;";
		String after = "/*\r\n" + "int i;\r\n" + "int j;\n" + "*/\n" + "int k;";
		LinePosition startSelection = new LinePosition(1, 1, fDocument);
		LinePosition endSelection = new LinePosition(3, 1, fDocument);
		assertFormatterResult(startSelection, endSelection, before, after);
	}
}
