/*******************************************************************************
 * Copyright (c) 2000, 2015 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:
 *     Genady Beryozkin, me@genady.org - initial API and implementation
 *     Fabio Zadrozny <fabiofz at gmail dot com> - [typing] HippieCompleteAction is slow  ( Alt+/ ) - https://bugs.eclipse.org/bugs/show_bug.cgi?id=270385
 *******************************************************************************/
package org.eclipse.ui.workbench.texteditor.tests;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.junit.Before;
import org.junit.Test;

import org.eclipse.core.runtime.AssertionFailedException;

import org.eclipse.text.tests.Accessor;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;

import org.eclipse.ui.internal.texteditor.HippieCompletionEngine;

/**
 * Tests for the Hippie completion action of the text editor.
 *
 * @author Genady Beryozkin, me@genady.org
 */
public class HippieCompletionTest {

	IDocument[] documents;
	private HippieCompletionEngine fEngine;

	@Before
	public void setUp() throws Exception {
		documents= new IDocument[5];
		documents[0]= new Document("package ui.TestPackage;\n" +
				"\n" +
				"/**\n" +
				" * This is a testing class that tests the hippie completion engine.\n" +
				" * it has a simple main with a print method\n" +
				" */\n" +
				"public class TestClass1 {\n" +
				"\n" +
				"    public static void main(String[] args) {\n" +
				"        System.out.println(\"I will be printing Hello world!\");\n" +
				"    }\n" +
				"}");
		documents[1]= new Document("This is a simple text file\n" +
				"with some testssome test that is also used in the completion engine tests");

		documents[2]= new Document("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
				"<plugin\n" +
				"   id=\"org.eclipse.ui.workbench.texteditor.tests\"\n" +
				"   name=\"%Plugin.name\"\n" +
				"   version=\"3.1.0\"\n" +
				"   provider-name=\"%Plugin.providerName\">\n" +
				"\n" +
				"   <runtime>\n" +
				"      <library name=\"workbenchtexteditortests.jar\">\n" +
				"         <export name=\"*\"/>\n" +
				"      </library>\n" +
				"   </runtime>\n" +
				"   \n" +
				"   <requires>\n" +
				"      <import plugin=\"org.eclipse.core.runtime.compatibility\"/>\n" +
				"      <import plugin=\"org.junit\"/>\n" +
				"      <import plugin=\"org.eclipse.text.tests\"/>\n" +
				"      <import plugin=\"org.eclipse.jface.text\"/>\n" +
				"      <import plugin=\"org.eclipse.ui.workbench.texteditor\"/>\n" +
				"      <import plugin=\"org.eclipse.ui\"/>\n" +
				"   </requires>\n" +
				"   \n" +
				"</plugin>\n" +
				"");

		documents[3]= new Document("###############################################################################\n" +
				"# Copyright (c) 2000, 2004 IBM Corporation and others.\n" +
				"# All rights reserved. This program and the accompanying materials \n" +
				"# are made available under the terms of the Eclipse Public License v1.0\n" +
				"# which accompanies this distribution, and is available at\n" +
				"# http://www.eclipse.org/legal/epl-v10.html\n" +
				"# \n" +
				"# Contributors:\n" +
				"#     IBM Corporation - initial API and implementation\n" +
				"###############################################################################\n" +
				"bin.includes= plugin.xml,\\\n" +
				"               plugin.properties,\\\n" +
				"               test.xml,\\\n" +
				"               about.html,\\\n" +
				"               *.jar\n" +
				"\n" +
				"src.includes= about.html\n" +
				"               \n" +
				"source.workbenchtexteditortests.jar= src/\n" +
				"");
		documents[4]= new Document("/**\n" +
				" * This class tests the hippie completion functionality.\n" +
				" * \u05D4\u05DE\u05D7\u05DC\u05E7\u05D4 \u05D4\u05D6\u05D5 \u05D1\u05D5\u05D3\u05E7\u05EA \u05D0\u05EA \u05DE\u05E0\u05D2\u05E0\u05D5\u05DF \u05D4\u05D4\u05E9\u05DC\u05DE\u05D5\u05EA\n" +
				" * This is an arabic word - \u0647\u0630\u0627 \u0643\u0644\u0645\u0629 \u0639\u0631\u0628\u064A\u0651\u0629\n" +
				" * Eclipse is the best IDE - Eclipse \u044D\u0442\u043E \u0441\u0430\u043C\u044B\u0439 \u043B\u0443\u0447\u0448\u0438\u0439 IDE.\n" +
				" */\n" +
				"\n" +
				"public class HippieTester2 {\n" +
				"\n" +
				"\tpublic static void main(String[] args) {\n" +
					"\t\tchar \u05DE\u05D7= '9';\n" +   // hebrew text
				"\t\tString $arabic\u20ACDigits= \"\u0661\u0662\u0663\u0664\u0665\u0666" + // Euro symbol in variable name, arabic digits from 1 to 6
									"\u2021\u0667\u0668\u0669\u0660\";\n" + // double dagger, arabic digits 7-0
				"\t\tString $arabic\u20AAWord= \"\u0628\u064E\u0627\u0628\u0650\";\n" + // shekel (israeli) currency symbol + arabic word
				"\t\tString \u0628\u0627\u0628= \"\u044D\u0442\";\n" + // arabic var, russian string
				"\t\tint \u20A31= 3;\n" + // frank currency symbol
				"\t\tint \u00A3\u0661\u0662\u0663= \u20A31 + \u05DE\u05D7;\n" + // pound, arabic digits 1-3, partial hebrew word
				"\t\tint a\u0300\u0301b= 18;\n" + // combining diactritical marks
				"\t\t}\n" +
				"\t\t\n" +
				"\tpublic void \u05D4\u05D4\u05E9(int \u0441\u0430\u043C) {\n" + // hebrew word prexif, russian word prefix
				"\t\tString \u043B\u0443\u0447\u0448= \"\u05D1\u05D5\u05D3\u05E7\";\n" +
				"\t\tchar \u20AA129;\n" + // shekel (israeli) currency
				"\t}\n" +
				"}");

		fEngine= new HippieCompletionEngine();
	}

	@Test
	public void testSearchBackwards1() {
		try {
			List<String> list= fEngine.getCompletionsBackwards(documents[0],
					"pri", documents[0].get().indexOf("println") + 10);
			assertEquals(list.size(), 2);
			assertEquals(list.get(0), "ntln");
			assertEquals(list.get(1), "nt");

			list= fEngine.getCompletionsBackwards(documents[0],
					"pri", documents[0].getLength());
			assertEquals(list.size(), 3);
			assertEquals(list.get(0), "nting");
			assertEquals(list.get(1), "ntln");
			assertEquals(list.get(2), "nt");

			list= fEngine.getCompletionsBackwards(documents[0],
					"pri", documents[0].get().indexOf("println") + 1);
			assertEquals(list.size(), 1);
            assertEquals(list.get(0), "nt");

			list= fEngine.getCompletionsBackwards(documents[0],
					"pa", 2);
			assertEquals(list.size(), 0);

		} catch (BadLocationException e) {
			assertTrue("Got out of document bounds", false);
		}
	}

	@Test
	public void testSearchBackwards2() {
		try {
			List<String> list= fEngine.getCompletionsBackwards(documents[2],
					"plugi", documents[2].getLength());
			assertEquals(8, list.size());
			list= fEngine.makeUnique(list);
			assertEquals(1, list.size());
			assertEquals("n", list.get(0));

			list= fEngine.getCompletionsBackwards(documents[2],
					"plugin", documents[2].getLength());
			assertEquals(0, list.size()); // empty completions discarded

		} catch (BadLocationException e) {
			assertTrue("Got out of document bounds", false);
		}
	}

	@Test
    public void testSearchBackwards3() {
        try {
        	List<String> list= fEngine.getCompletionsBackwards(documents[1],
                    "test", documents[1].getLength());
            assertEquals("Number of backwards suggestions does not match", 2, list.size());
            list= fEngine.getCompletionsBackwards(documents[1],
                    "tests", documents[1].getLength());
            assertEquals("Number of backwards suggestions does not match", 1, list.size());

            list= fEngine.getCompletionsBackwards(documents[1],
                    "test", documents[1].getLength() - 1);
            assertEquals("Number of backwards suggestions does not match", 1, list.size());
        } catch (BadLocationException e) {
            assertTrue("Got out of document bounds", false);
        }
    }

	@Test
	public void testSearch() {
		ArrayList<IDocument> docsList= new ArrayList<>(Arrays.asList(this.documents));
		List<String> result= createSuggestions("te", docsList);
		assertEquals("Number of completions does not match", 15, result.size());
		result= fEngine.makeUnique(result);
		assertEquals("Number of completions does not match", 7, result.size());

		result= createSuggestions("Plug", docsList);
		assertEquals("Number of completions does not match", 2, result.size());

		result= createSuggestions("p", docsList);
		assertEquals("Number of completions does not match", 23, result.size());
		result= fEngine.makeUnique(result);
		assertEquals("Number of completions does not match", 10, result.size());
		assertEquals("Incorrect completion", "ackage", result.get(0));
		assertEquals("Incorrect completion", "rint", result.get(1));
		assertEquals("Incorrect completion", "ublic", result.get(2));
		assertEquals("Incorrect completion", "rintln", result.get(3));
		assertEquals("Incorrect completion", "rinting", result.get(4));
		assertEquals("Incorrect completion", "lugin", result.get(5));
		assertEquals("Incorrect completion", "rovider", result.get(6));
		assertEquals("Incorrect completion", "roviderName", result.get(7));
		assertEquals("Incorrect completion", "rogram", result.get(8));
		assertEquals("Incorrect completion", "roperties", result.get(9));
	}

	@Test
	public void testSearch2() {
		ArrayList<IDocument> docsList= new ArrayList<>(Arrays.asList(this.documents));
		List<String> result= createSuggestions("printe", docsList);
		assertEquals("Number of completions does not match", 0, result.size());

		result= createSuggestions("s", docsList);
		assertEquals("Number of completions does not match", 8, result.size());

		result= createSuggestions("pack", documents[0]);
		assertEquals("Number of completions does not match", 1, result.size());
	}

	@Test
	public void testForwardSearch() {
		try {
			List<String> result= fEngine.getCompletionsForward(documents[0],
					"cl", documents[0].get().indexOf("cl"), true);
			assertEquals(2, result.size());

			result= fEngine.getCompletionsForward(documents[0],
					"cl", documents[0].get().indexOf("cl") + 1, true);
			assertEquals(1, result.size());

			result= fEngine.getCompletionsForward(documents[1],
					"Thi", 0, true);
			assertEquals(1, result.size());

			result= fEngine.getCompletionsForward(documents[1],
					"Thi", 1, true);
			assertEquals(0, result.size());
		} catch (BadLocationException e) {
			assertTrue("Got out of document bounds", false);
		}
	}

	@Test
	public void testForwardSearchInternational() {
		List<String> result;
		try {
			result= fEngine.getCompletionsForward(documents[4],
					"$", documents[4].get().indexOf('$'), true);
			assertEquals(2, result.size());
			assertEquals("arabic\u20AAWord", result.get(0));
			assertEquals("arabic\u20ACDigits", result.get(1));

			result= fEngine.getCompletionsForward(documents[4],
					"$", documents[4].get().indexOf('$'), false);
			assertEquals(2, result.size());
			assertEquals("arabic\u20ACDigits", result.get(0));
			assertEquals("arabic\u20AAWord", result.get(1));

			result= fEngine.getCompletionsForward(documents[4],
					"$", documents[4].get().indexOf('$') + 1, true);
			assertEquals(1, result.size());
			assertEquals("arabic\u20AAWord", result.get(0));
		} catch (BadLocationException e) {
			assertTrue("Got out of document bounds", false);
		}
	}

	@Test
	public void testPrefix() {
		try {
			String prefix= fEngine.getPrefixString(documents[0],
					documents[0].get().indexOf("testing") + 3);
			assertEquals(prefix, "tes");

			prefix= fEngine.getPrefixString(documents[0],
					documents[0].get().indexOf("public") + 4);
			assertEquals(prefix, "publ");

			prefix= fEngine.getPrefixString(documents[0],
					documents[0].get().indexOf("println") + 7);
			assertEquals(prefix, "println");

			prefix= fEngine.getPrefixString(documents[0],
					documents[0].get().indexOf("println") + 8);
			assertEquals(prefix, null);

			prefix= fEngine.getPrefixString(documents[1], 3);
			assertEquals(prefix, "Thi");

			prefix= fEngine.getPrefixString(documents[1], 0);
			assertEquals(prefix, null);

			prefix= fEngine.getPrefixString(documents[1], documents[1].getLength());
			assertEquals(prefix, "tests");

			prefix= fEngine.getPrefixString(documents[3],
					documents[3].get().indexOf("Copyright") - 2);
			assertEquals(prefix, null);

			prefix= fEngine.getPrefixString(documents[4],
					documents[4].get().indexOf("IDE") + 2);
			assertEquals(prefix, "ID");

			prefix= fEngine.getPrefixString(documents[4],
					documents[4].get().indexOf("$arabic\u20ACDigits") + 8);
			assertEquals(prefix, "$arabic\u20AC");

			prefix= fEngine.getPrefixString(documents[4],
					documents[4].get().indexOf("$arabic\u20AAWord") + 8);
			assertEquals(prefix, "$arabic\u20AA");

			prefix= fEngine.getPrefixString(documents[4],
					documents[4].get().indexOf("\u00A3\u0661\u0662\u0663") + 3);
			assertEquals(prefix, "\u00A3\u0661\u0662");

			prefix= fEngine.getPrefixString(documents[4],
					documents[4].get().indexOf("a\u0300\u0301b") + 3);
			assertEquals(prefix, "a\u0300\u0301");

			prefix= fEngine.getPrefixString(documents[4],
					documents[4].get().indexOf("\u0667\u0668\u0669\u0660") + 2);
			assertEquals(prefix, "\u0667\u0668");

		} catch (BadLocationException e) {
			assertTrue("Got out of document bounds", false);
		}
	}

	@Test
	public void testInternational() {
		IDocument intlDoc= documents[4];

		List<String> result= createSuggestions("\u05D4", intlDoc); // hebrew letter heh
		assertEquals("Number of completions does not match", 4, result.size());
		assertEquals(result.get(0), "\u05DE\u05D7\u05DC\u05E7\u05D4");
		assertEquals(result.get(1), "\u05D6\u05D5");
		assertEquals(result.get(2), "\u05D4\u05E9\u05DC\u05DE\u05D5\u05EA");
		assertEquals(result.get(3), "\u05D4\u05E9");

		result= createSuggestions("\u0661", intlDoc); // arabic digit "1"
		assertEquals("Number of completions does not match", 1, result.size());
		assertEquals(result.get(0), "\u0662\u0663\u0664\u0665\u0666");

		result= createSuggestions("\u0628\u064E", intlDoc); // arabic letter bah and fatha
		assertEquals("Number of completions does not match", 1, result.size());
		assertEquals(result.get(0), "\u0627\u0628\u0650");
		result= createSuggestions("\u0628", intlDoc); // arabic letter bah
		assertEquals("Number of completions does not match", 2, result.size());
		assertEquals(result.get(0), "\u064E\u0627\u0628\u0650");
		assertEquals(result.get(1), "\u0627\u0628");

		result= createSuggestions("$ara", intlDoc);
		assertEquals("Number of completions does not match", 2, result.size());
		assertEquals(result.get(0), "bic\u20ACDigits");
		assertEquals(result.get(1), "bic\u20AAWord");

		result= createSuggestions("\u0441\u0430", intlDoc); // russian letters "s" and "a"
		assertEquals("Number of completions does not match", 2, result.size());
		assertEquals(result.get(0), "\u043C\u044B\u0439");
		assertEquals(result.get(1), "\u043C");

		result= createSuggestions("\u05D1\u05D5", intlDoc); // hebrew letters bet and vav
		assertEquals("Number of completions does not match", 2, result.size());
		assertEquals(result.get(0), "\u05D3\u05E7\u05EA");
		assertEquals(result.get(1), "\u05D3\u05E7");

		result= createSuggestions("a", intlDoc);
		assertEquals("Number of completions does not match", 4, result.size());
		assertEquals(result.get(0), "n");
		assertEquals(result.get(1), "rabic");
		assertEquals(result.get(2), "rgs");
		assertEquals(result.get(3), "\u0300\u0301b");

		result= createSuggestions("\u20AA", intlDoc);  // israeli currency (shekel)
		assertEquals("Number of completions does not match", 1, result.size());
		assertEquals(result.get(0), "129");

		result= createSuggestions("\u20A3", intlDoc);  // french currency (frank)
		assertEquals("Number of completions does not match", 2, result.size());
		assertEquals(result.get(0), "1");
		assertEquals(result.get(1), "1");

		result= createSuggestions("\u044D", intlDoc);  // russial letter "hard e"
		assertEquals("Number of completions does not match", 2, result.size());
		assertEquals(result.get(0), "\u0442\u043E");
		assertEquals(result.get(1), "\u0442");

		result= createSuggestions("\u00A3", intlDoc);  // pound currency sign
		assertEquals("Number of completions does not match", 1, result.size());
		assertEquals(result.get(0), "\u0661\u0662\u0663");

		result= createSuggestions("\u00A5", intlDoc);  // yen currency sign
		assertEquals("Number of completions does not match", 0, result.size());
	}

	@Test
	public void testInternationalBackwards() {
		IDocument intlDoc= documents[4];
		try {
			List<String> list= fEngine.getCompletionsBackwards(intlDoc,
					"\u043B\u0443", intlDoc.get().indexOf("129"));
			assertEquals(2, list.size());
			assertEquals(list.get(0), "\u0447\u0448");
			assertEquals(list.get(1), "\u0447\u0448\u0438\u0439");

			list= fEngine.getCompletionsBackwards(intlDoc,
					"\u05DE", intlDoc.get().lastIndexOf('+'));
			assertEquals(2, list.size());
			assertEquals(list.get(0), "\u05D7");
			assertEquals(list.get(1), "\u05E0\u05D2\u05E0\u05D5\u05DF");

			list= fEngine.getCompletionsBackwards(intlDoc,
					"\u0667", intlDoc.get().indexOf("\u2021\u0667") + 1);
			assertEquals(0, list.size());

			list= fEngine.getCompletionsBackwards(intlDoc,
					"\u0628", intlDoc.get().lastIndexOf("\u0628"));
			assertEquals(1, list.size());
			assertEquals(list.get(0), "\u064E\u0627\u0628\u0650");

		} catch (BadLocationException e) {
			assertTrue("Got out of document bounds", false);
		}
	}

	private Accessor createAccessor(Iterator<String> suggestions, int startOffset) {
		return new Accessor("org.eclipse.ui.texteditor.HippieCompleteAction$CompletionState",
				getClass().getClassLoader(), new Class[] { Iterator.class, int.class }, new
				Object[] { suggestions, Integer.valueOf(startOffset) });
	}

	private String next(Accessor state) {
		return (String)state.invoke("next", new Object[] {});
	}


	/*
	 * Getting completions lazily
	 */
	@Test
	public void testCompletionState() throws Exception {
		ArrayList<String> list= new ArrayList<>();
		Accessor state= null;

		try {
			state= createAccessor(list.iterator(), 0);
			fail("Having no items is not valid (at least the empty completion must be there)");
		} catch (AssertionFailedException ex) {
		}

		list.add("");
		state= createAccessor(list.iterator(), 0);
		assertTrue(state.getBoolean("hasOnly1EmptySuggestion"));
		for (int i= 0; i < 3; i++) {
			assertEquals("", next(state));
		}

		list.add("");
		state= createAccessor(list.iterator(), 0);
		assertTrue(state.getBoolean("hasOnly1EmptySuggestion"));
		for (int i= 0; i < 3; i++) {
			assertEquals("", next(state));
		}


		//only empty and aaaa
		list.add(0, "aaaa");
		state= createAccessor(list.iterator(), 0);
		assertFalse(state.getBoolean("hasOnly1EmptySuggestion"));

		for (int i= 0; i < 3; i++) {
			assertEquals("aaaa", next(state));
			assertEquals("", next(state));
		}

		//empty, aaaa and bbbb
		list.add(1, "bbbb");
		state= createAccessor(list.iterator(), 0);
		assertFalse(state.getBoolean("hasOnly1EmptySuggestion"));

		for (int i= 0; i < 3; i++) {
			assertEquals("aaaa", next(state));
			assertEquals("bbbb", next(state));
			assertEquals("", next(state));
		}


		//empty, aaaa and 2 from 'bbbb' (should make unique)
		list.add(2, "bbbb");
		state= createAccessor(list.iterator(), 0);
		assertFalse(state.getBoolean("hasOnly1EmptySuggestion"));

		for (int i= 0; i < 3; i++) {
			assertEquals("aaaa", next(state));
			assertEquals("bbbb", next(state));
			assertEquals("", next(state));
		}
	}

	/*
	 * Getting completions lazily
	 */
	@Test
	public void testIteration() throws Exception {
		//Check only with current document
		IDocument openDocument= new Document("" +
				"bar\n" +
				"bar1\n" +
				"bar2\n" +
				"");

		Iterator<String> suggestions= fEngine.getMultipleDocumentsIterator(openDocument, new ArrayList<IDocument>(), "bar", 3);
		assertEquals("1", suggestions.next());
		assertEquals("2", suggestions.next());
		assertEquals("", suggestions.next());
		assertFalse(suggestions.hasNext());


		//Check with 2 documents
		List<IDocument> otherDocuments= new ArrayList<>();
		otherDocuments.add(new Document("" +
				"bar3\n" +
				"bar4\n" +
				""));

		suggestions= fEngine.getMultipleDocumentsIterator(openDocument, otherDocuments, "bar", 3);
		assertEquals("1", suggestions.next());
		assertEquals("2", suggestions.next());
		assertEquals("3", suggestions.next());
		assertEquals("4", suggestions.next());
		assertEquals("", suggestions.next());
		assertFalse(suggestions.hasNext());


		//Check with duplicates (duplicates are gotten at this level -- they're removed later -- at the CompletionState)
		suggestions= fEngine.getMultipleDocumentsIterator(openDocument, otherDocuments, "bar", 3);
		otherDocuments.add(new Document());
		otherDocuments.add(new Document("" +
				"bar3\n" +
				"bar4\n" +
				""));
		assertEquals("1", suggestions.next());
		assertEquals("2", suggestions.next());
		assertEquals("3", suggestions.next());
		assertEquals("4", suggestions.next());
		assertEquals("3", suggestions.next());
		assertEquals("4", suggestions.next());
		assertEquals("", suggestions.next());
		assertFalse(suggestions.hasNext());

		//Check with current document with only backward matches
		openDocument= new Document("" +
				"bar0 bar1 bar" +
				"");

		suggestions= fEngine.getMultipleDocumentsIterator(openDocument, new ArrayList<IDocument>(), "bar", openDocument.getLength());
		assertEquals("1", suggestions.next());
		assertEquals("0", suggestions.next());
		assertEquals("", suggestions.next());
		assertFalse(suggestions.hasNext());

	}

	private List<String> createSuggestions(String prefix, IDocument doc) {
		return createSuggestions(prefix, Arrays.asList(new IDocument[]{doc}));
	}

	private List<String> createSuggestions(String prefix, List<IDocument> docsList) {
		ArrayList<String> results= new ArrayList<>();
		for (Iterator<IDocument> i= docsList.iterator(); i.hasNext();) {
			IDocument doc= i.next();
			try {
				results.addAll(fEngine.getCompletionsForward(doc, prefix, 0, false));
			} catch (BadLocationException e) {
				assertTrue("No exception should be thrown here", false);
			}
		}
		return results;
	}

}
