/*******************************************************************************
 * Copyright (c) 2004, 2012 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *     Martin Karpisek - bug 195840
 *******************************************************************************/
package org.eclipse.ant.tests.ui.editor;

import java.io.File;

import org.eclipse.ant.internal.ui.editor.AntEditor;
import org.eclipse.ant.internal.ui.editor.text.XMLTextHover;
import org.eclipse.ant.tests.ui.editor.performance.EditorTestHelper;
import org.eclipse.ant.tests.ui.testplugin.AbstractAntUITest;
import org.eclipse.ant.tests.ui.testplugin.ProjectCreationDecorator;
import org.eclipse.core.resources.IFile;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.PartInitException;

public class AntEditorTests extends AbstractAntUITest {

	public AntEditorTests(String name) {
		super(name);
	}

	public void testHoverForPath() throws PartInitException, BadLocationException {
		IFile file = getIFile("refid.xml"); //$NON-NLS-1$
		AntEditor editor = (AntEditor) EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		XMLTextHover hover = new XMLTextHover(editor);
		int offset = getOffsetWithinLine(editor, 9, 20);
		IRegion region = hover.getHoverRegion(editor.getViewer(), offset);
		String hoverText = hover.getHoverInfo(editor.getViewer(), region);
		assertNotNull("Expecting a hovertext object", hoverText); //$NON-NLS-1$
		String correctResultRegEx = "<html><body text=\"#.*\" bgcolor=\"#.*\"><h5>Path Elements:</h5><ul><li>.*</html>"; //$NON-NLS-1$
		assertTrue("Expected the following hover text to match regex: " + correctResultRegEx, hoverText.matches(correctResultRegEx)); //$NON-NLS-1$
	}

	public void testHoverForProperty() throws PartInitException, BadLocationException {
		IFile file = getIFile("refid.xml"); //$NON-NLS-1$
		AntEditor editor = (AntEditor) EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		XMLTextHover hover = new XMLTextHover(editor);
		int offset = getOffsetWithinLine(editor, 42, 13);
		IRegion region = hover.getHoverRegion(editor.getViewer(), offset);
		String hoverText = hover.getHoverInfo(editor.getViewer(), region);
		assertNotNull("Expecting a hovertext object", hoverText); //$NON-NLS-1$
		String correctResult = "<p>value with spaces</body></html>"; //$NON-NLS-1$
		assertTrue("Expected the following hover text to end with: " + correctResult, hoverText.endsWith(correctResult)); //$NON-NLS-1$
	}

	public void testPropertyOpenDeclaration() throws PartInitException, BadLocationException {
		IFile file = getIFile("refid.xml"); //$NON-NLS-1$
		AntEditor editor = (AntEditor) EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		int offset = getOffsetWithinLine(editor, 42, 12);
		editor.selectAndReveal(offset, 2);

		editor.openReferenceElement();
		ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
		assertEquals("Selection is not correct", "property", selection.getText()); //$NON-NLS-1$ //$NON-NLS-2$
	}

	public void testPatternSetHover() throws PartInitException, BadLocationException {
		IFile file = getIFile("refid.xml"); //$NON-NLS-1$
		AntEditor editor = (AntEditor) EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		XMLTextHover hover = new XMLTextHover(editor);
		int offset = getOffsetWithinLine(editor, 45, 25);
		IRegion region = hover.getHoverRegion(editor.getViewer(), offset);
		String hoverText = hover.getHoverInfo(editor.getViewer(), region);
		assertNotNull("Expecting a hovertext object", hoverText); //$NON-NLS-1$
		String correctResult = "<h5>Includes:</h5><li>*.xml</li><p><p><h5>Excludes:</h5><li>**/*Test*</li></body></html>"; //$NON-NLS-1$
		assertTrue("Expected the following hover text to end with: " + correctResult + "was: " + hoverText, hoverText.endsWith(correctResult)); //$NON-NLS-1$ //$NON-NLS-2$
	}

	public void testBadPatternSetHover() throws PartInitException, BadLocationException {
		IFile file = getIFile("refid.xml"); //$NON-NLS-1$
		AntEditor editor = (AntEditor) EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		XMLTextHover hover = new XMLTextHover(editor);
		int offset = getOffsetWithinLine(editor, 46, 25);
		IRegion region = hover.getHoverRegion(editor.getViewer(), offset);
		String hoverText = hover.getHoverInfo(editor.getViewer(), region);
		assertNotNull("Expecting a hovertext object", hoverText); //$NON-NLS-1$
		String correctResult = "Ant UI Tests" + File.separatorChar + "buildfiles" + File.separatorChar + "nothere not found."; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		assertTrue("Expected the following hover text to ends with: " + correctResult, hoverText.endsWith(correctResult)); //$NON-NLS-1$
	}

	public void testFileSetHover() throws PartInitException, BadLocationException {
		IFile file = getIFile("refid.xml"); //$NON-NLS-1$
		AntEditor editor = (AntEditor) EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		XMLTextHover hover = new XMLTextHover(editor);
		int offset = getOffsetWithinLine(editor, 44, 20);
		IRegion region = hover.getHoverRegion(editor.getViewer(), offset);
		String hoverText = hover.getHoverInfo(editor.getViewer(), region);
		assertNotNull("Expecting a hovertext object", hoverText); //$NON-NLS-1$
		assertTrue("Expected to see '<h5>Includes:</h5><li>include</li>'", hoverText.indexOf("<h5>Includes:</h5><li>include</li>") > -1); //$NON-NLS-1$ //$NON-NLS-2$
		assertTrue("Expected to see '<h5>Excludes:</h5><li>exclude</li>'", hoverText.indexOf("<h5>Excludes:</h5><li>exclude</li>") > -1); //$NON-NLS-1$ //$NON-NLS-2$
		String text = "<li>**" + File.separator + "SCCS" + File.separator + "**</li>"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		assertTrue("Expected to see '<li>**/SCCS/**</li>'", hoverText.indexOf(text) > -1); //$NON-NLS-1$
		text = "<li>**" + File.separator + ".DS_Store</li>"; //$NON-NLS-1$ //$NON-NLS-2$
		assertTrue("Expected to see '<li>**/.DS_Store</li>'", hoverText.indexOf(text) > -1); //$NON-NLS-1$
		text = "<li>**" + File.separator + ".bzrignore</li>"; //$NON-NLS-1$ //$NON-NLS-2$
		assertTrue("Expected to see '<li>**/.bzrignore</li>'", hoverText.indexOf(text) > -1); //$NON-NLS-1$
		text = "<li>**" + File.separator + ".gitattributes</li>"; //$NON-NLS-1$ //$NON-NLS-2$
		assertTrue("Expected to see '<li>**/.gitattributes</li>'", hoverText.indexOf(text) > -1); //$NON-NLS-1$
		text = "<li>**" + File.separator + ".hgtags</li>"; //$NON-NLS-1$ //$NON-NLS-2$
		assertTrue("Expected to see '<li>**/.hgtags</li>'", hoverText.indexOf(text) > -1); //$NON-NLS-1$
	}

	public void testTaskdefOpenDeclaration() throws PartInitException, BadLocationException {
		IFile file = getIFile("taskdef.xml"); //$NON-NLS-1$
		AntEditor editor = (AntEditor) EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		int offset = getOffsetWithinLine(editor, 9, 3);
		editor.selectAndReveal(offset, 0);

		editor.openReferenceElement();
		ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
		assertEquals("Selection is not correct", "taskdef", selection.getText()); //$NON-NLS-1$ //$NON-NLS-2$

		offset = getOffsetWithinLine(editor, 9, 10);
		editor.selectAndReveal(offset, 3);

		editor.openReferenceElement();
		selection = (ITextSelection) editor.getSelectionProvider().getSelection();
		assertEquals("Selection is not correct", "taskdef", selection.getText()); //$NON-NLS-1$ //$NON-NLS-2$
	}

	public void testMacroDefOpenDeclaration() throws PartInitException, BadLocationException {
		IFile file = getIFile("macrodef.xml"); //$NON-NLS-1$
		AntEditor editor = (AntEditor) EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		int offset = getOffsetWithinLine(editor, 12, 9);
		editor.selectAndReveal(offset, 0);

		editor.openReferenceElement();
		ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
		assertEquals("Selection is not correct", "macrodef", selection.getText()); //$NON-NLS-1$ //$NON-NLS-2$

		offset = getOffsetWithinLine(editor, 14, 9);
		editor.selectAndReveal(offset, 1);

		editor.openReferenceElement();
		selection = (ITextSelection) editor.getSelectionProvider().getSelection();
		assertEquals("Selection is not correct", "macrodef", selection.getText()); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * from bug 98853
	 */
	public void testMacroDefOpenDeclarationWithURI() throws PartInitException, BadLocationException {
		IFile file = getIFile("98853.xml"); //$NON-NLS-1$
		AntEditor editor = (AntEditor) EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		int offset = getOffsetWithinLine(editor, 17, 9);
		editor.selectAndReveal(offset, 0);

		editor.openReferenceElement();
		ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
		assertEquals("Selection is not correct:", "macrodef", selection.getText()); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Bug 95061
	 */
	public void testSelfClosingTagOpenDeclaration() throws PartInitException, BadLocationException {
		IFile file = getIFile("macrodef.xml"); //$NON-NLS-1$
		AntEditor editor = (AntEditor) EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		int offset = getOffsetWithinLine(editor, 18, 10);
		editor.selectAndReveal(offset, 0);

		editor.openReferenceElement();
		ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
		assertEquals("Selection is not correct", "macrodef", selection.getText()); //$NON-NLS-1$ //$NON-NLS-2$
	}

	public void testMacroDefAttributeOpenDeclaration() throws PartInitException, BadLocationException {
		IFile file = getIFile("macrodef.xml"); //$NON-NLS-1$
		AntEditor editor = (AntEditor) EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		int offset = getOffsetWithinLine(editor, 12, 16);
		editor.selectAndReveal(offset, 1);

		editor.openReferenceElement();
		ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
		assertEquals("Selection is not correct", "attribute", selection.getText()); //$NON-NLS-1$ //$NON-NLS-2$
	}

	public void testRefOpenDeclaration() throws PartInitException, BadLocationException {
		IFile file = getIFile("refid.xml"); //$NON-NLS-1$
		AntEditor editor = (AntEditor) EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		int offset = getOffsetWithinLine(editor, 9, 20);
		editor.selectAndReveal(offset, 2);

		editor.openReferenceElement();
		ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
		assertEquals("Selection is not correct", "path", selection.getText()); //$NON-NLS-1$ //$NON-NLS-2$
	}

	public void testTargetOpenDeclaration() throws PartInitException, BadLocationException {
		IFile file = getIFile("refid.xml"); //$NON-NLS-1$
		AntEditor editor = (AntEditor) EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		int offset = getOffsetWithinLine(editor, 0, 18);
		editor.selectAndReveal(offset, 1);

		editor.openReferenceElement();
		ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
		assertEquals("Selection is not correct", "target", selection.getText()); //$NON-NLS-1$ //$NON-NLS-2$
	}

	public void testExtensionPointOpenDeclaration() throws PartInitException, BadLocationException {
		IFile file = getIFile("antextpoint.xml"); //$NON-NLS-1$
		AntEditor editor = (AntEditor) EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		int offset = getOffsetWithinLine(editor, 0, 18);
		editor.selectAndReveal(offset, 4);

		editor.openReferenceElement();
		ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
		assertEquals("Selection is not correct", "extension-point", selection.getText()); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Tests that the augment task can open in the Ant editor
	 * 
	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=377075
	 * @throws Exception
	 */
	public void testAugmentOpenInEditor() throws Exception {
		IFile file = getIFile("bug377075.ent"); //$NON-NLS-1$
		IEditorPart part = EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		assertTrue("The opened editor must be the AntEditor", part instanceof AntEditor); //$NON-NLS-1$
	}

	/**
	 * Tests that the augment task can be shown and has the correct additions
	 * 
	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=377075
	 * @throws Exception
	 */
	public void testAugmentOpenAndSelect() throws Exception {
		IFile file = getIFile("bug377075.ent"); //$NON-NLS-1$
		IEditorPart part = EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		assertTrue("The opened editor must be the AntEditor", part instanceof AntEditor); //$NON-NLS-1$
		AntEditor editor = (AntEditor) part;
		int offset = getOffsetWithinLine(editor, 5, 3);
		editor.selectAndReveal(offset, 7); // should have 'augment' selected
		ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
		assertEquals("Selection is not correct", "augment", selection.getText()); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Tests that the element augmented by the augment task properly displays the augmented elements when hovering
	 * 
	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=377075
	 * @throws Exception
	 */
	public void testAugmentOpenSelectHover() throws Exception {
		IFile file = getIFile("bug377075.ent"); //$NON-NLS-1$
		IEditorPart part = EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		assertTrue("The opened editor must be the AntEditor", part instanceof AntEditor); //$NON-NLS-1$
		AntEditor editor = (AntEditor) part;
		int offset = getOffsetWithinLine(editor, 1, 11);
		editor.selectAndReveal(offset, 5); // select the 'path1' id for the path element
		ITextSelection selection = (ITextSelection) editor.getSelectionProvider().getSelection();
		assertEquals("Selection is not correct", "path1", selection.getText()); //$NON-NLS-1$ //$NON-NLS-2$
		XMLTextHover hover = new XMLTextHover(editor);
		IRegion region = hover.getHoverRegion(editor.getViewer(), offset);
		assertNotNull("The selected region for the augmented element cannot be null", region); //$NON-NLS-1$
		String text = hover.getHoverInfo(editor.getViewer(), region);
		assertNotNull("The hover text for the path element must not be null", text); //$NON-NLS-1$
		assertTrue("The hover text must contain the augmented element 'foo'", text.indexOf("foo") > -1); //$NON-NLS-1$ //$NON-NLS-2$
	}

	/**
	 * Tests that the Ant editor is resilient to using an Augment task that references an unknown id
	 * 
	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=396219
	 * @throws Exception
	 */
	public void testAugmentMissingId() throws Exception {
		IFile file = getIFile("bug396219.ent"); //$NON-NLS-1$
		IEditorPart part = EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		assertTrue("The opened editor must be the AntEditor", part instanceof AntEditor); //$NON-NLS-1$
	}

	public void testHoverRegionWithSpaces() throws PartInitException, BadLocationException {
		IFile file = getIFile("refid.xml"); //$NON-NLS-1$
		AntEditor editor = (AntEditor) EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
		XMLTextHover hover = new XMLTextHover(editor);
		// in the middle of the "compile" target of the depends attribute
		int offset = getOffsetWithinLine(editor, 22, 39);
		IRegion region = hover.getHoverRegion(editor.getViewer(), offset);

		assertNotNull(region);
		IDocument doc = editor.getDocumentProvider().getDocument(editor.getEditorInput());
		String text = doc.get(region.getOffset(), region.getLength());
		assertTrue("Region incorrect. Expected length of 7 and text of \"compile\", length was " + region.getLength() + " and text was " + text, region.getLength() == 7 && "compile".equals(text)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
	}

	public void testOpenImport() throws PartInitException {
		IFile file = getIFile("import.xml"); //$NON-NLS-1$
		AntEditor editor = (AntEditor) EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$

		IDocument doc = editor.getDocumentProvider().getDocument(editor.getEditorInput());

		assertNotNull("Should have a document", doc); //$NON-NLS-1$
	}

	/**
	 * bug 195840 Import a XML file with BOM character in ant editor fails Runs on 1.5 vms or newer.
	 */
	public void testOpenImportWithByteOrderMark() throws PartInitException {
		if (ProjectCreationDecorator.isJ2SE15Compatible()) {
			IFile file = getIFile("importWithByteOrderMark.xml"); //$NON-NLS-1$
			AntEditor editor = (AntEditor) EditorTestHelper.openInEditor(file, "org.eclipse.ant.ui.internal.editor.AntEditor", true); //$NON-NLS-1$
			assertNotNull("Should have imported target", editor.getAntModel().getTargetNode("build")); //$NON-NLS-1$ //$NON-NLS-2$
		}
	}

	private int getOffsetWithinLine(AntEditor editor, int lineNumber, int offsetInLine) throws BadLocationException {
		IDocument document = editor.getDocumentProvider().getDocument(editor.getEditorInput());
		int offset = document.getLineOffset(lineNumber) + offsetInLine;
		return offset;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see junit.framework.TestCase#tearDown()
	 */
	@Override
	protected void tearDown() throws Exception {
		EditorTestHelper.closeAllEditors();
		super.tearDown();
	}
}
