/*******************************************************************************
 * Copyright (c) Mar 12, 2016 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
 *******************************************************************************/
package org.eclipse.jdt.debug.tests.variables;

import org.eclipse.debug.core.model.IValue;
import org.eclipse.debug.ui.IValueDetailListener;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.core.IJavaValue;
import org.eclipse.jdt.debug.core.IJavaVariable;
import org.eclipse.jdt.debug.tests.AbstractDebugTest;
import org.eclipse.jdt.internal.debug.ui.DetailFormatter;
import org.eclipse.jdt.internal.debug.ui.JavaDetailFormattersManager;

/**
 * Tests detail formatters
 * 
 * @since 3.8.100
 */
public class DetailFormatterTests extends AbstractDebugTest {
	
	class TestListener implements IValueDetailListener {
		IValue value;
		String result;
		
		@Override
		public void detailComputed(IValue value, String result) {
			this.value = value;
			this.result = result;
		}
		
		void reset() {
			value = null;
			result = null;
		}
	}
	
	TestListener fListener = new TestListener();
	
	/**
	 * @param name
	 */
	public DetailFormatterTests(String name) {
		super(name);
	}

	@Override
	protected IJavaProject getProjectContext() {
		return get15Project();
	}
	
	@Override
	protected void tearDown() throws Exception {
		fListener.reset();
		super.tearDown();
	}
	
	/**
	 * Tests a detail formatter made from a large compound expression
	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028
	 * @throws Exception
	 */
	public void testCompoundDetails1() throws Exception {
		IJavaThread thread = null;
		DetailFormatter formatter = null;
		JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
		try {
			String typename = "a.b.c.bug403028";
			createLineBreakpoint(10, typename);
			thread = launchToBreakpoint(typename);
			assertNotNull("The program did not suspend", thread);
			String snippet = "StringBuffer buf = new StringBuffer();\n"
					+ "buf.append(\"{\");\n"
					+ "Iterator i = this.entrySet().iterator();\n"
					+ "boolean hasNext = i.hasNext();\n"
					+ "while (hasNext) {\n"
					+ "    Entry e = (Entry) (i.next());\n"
					+ "    Object key = e.getKey();\n"
					+ "    Object value = e.getValue();\n"
					+ "    buf.append((key == this ?  \"(this Map)\" : key) + \"=\" + \n"
					+ "            (value == this ? \"(this Map)\": value));\n"
					+ "    hasNext = i.hasNext();\n"
					+ "    if (hasNext)\n"
					+ "        buf.append(\"\n,\");\n"
					+ "}\n"
					+ "buf.append(\"}\");\n"
					+ "return buf.toString();";
			formatter = new DetailFormatter("java.util.HashMap", snippet, true);
			jdfm.setAssociatedDetailFormatter(formatter);
			IJavaVariable var = thread.findVariable("map");
			assertNotNull("the variable 'map' must exist in the frame", var);
			jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
			long timeout = System.currentTimeMillis()+5000;
			while(fListener.value == null && System.currentTimeMillis() < timeout) {
				Thread.sleep(100);
			}
			assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
			assertTrue("The map should be an instance of java.util.LinkedHashMap", 
					Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap"));
			assertNotNull("The computed value of the detail should not be null", fListener.result);
		}
		finally {
			jdfm.removeAssociatedDetailFormatter(formatter);
			terminateAndRemove(thread);
			removeAllBreakpoints();
		}
	}
	
	/**
	 * Tests a detail formatter made from a small compound expression
	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028
	 * @throws Exception
	 */
	public void testCompoundDetails2() throws Exception {
		IJavaThread thread = null;
		DetailFormatter formatter = null;
		JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
		try {
			String typename = "a.b.c.bug403028";
			createLineBreakpoint(10, typename);
			thread = launchToBreakpoint(typename);
			assertNotNull("The program did not suspend", thread);
			String snippet = "StringBuffer buf = new StringBuffer();\n"
					+ "buf.append(this);\n"
					+ "return buf.toString();";
			formatter = new DetailFormatter("java.util.HashMap", snippet, true);
			jdfm.setAssociatedDetailFormatter(formatter);
			IJavaVariable var = thread.findVariable("map");
			assertNotNull("the variable 'map' must exist in the frame", var);
			jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
			long timeout = System.currentTimeMillis()+5000;
			while(fListener.value == null && System.currentTimeMillis() < timeout) {
				Thread.sleep(100);
			}
			assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
			assertTrue("The map should be an instance of java.util.LinkedHashMap", 
					Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap"));
			assertNotNull("The computed value of the detail should not be null", fListener.result);
		}
		finally {
			jdfm.removeAssociatedDetailFormatter(formatter);
			terminateAndRemove(thread);
			removeAllBreakpoints();
		}
	}
	
	/**
	 * Tests a detail formatter made from a small compound expression
	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028
	 * @throws Exception
	 */
	public void testSimpleDetails1() throws Exception {
		IJavaThread thread = null;
		DetailFormatter formatter = null;
		JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
		try {
			String typename = "a.b.c.bug403028";
			createLineBreakpoint(10, typename);
			thread = launchToBreakpoint(typename);
			assertNotNull("The program did not suspend", thread);
			String snippet = "return toString();";
			formatter = new DetailFormatter("java.util.HashMap", snippet, true);
			jdfm.setAssociatedDetailFormatter(formatter);
			IJavaVariable var = thread.findVariable("map");
			assertNotNull("the variable 'map' must exist in the frame", var);
			jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
			long timeout = System.currentTimeMillis()+5000;
			while(fListener.value == null && System.currentTimeMillis() < timeout) {
				Thread.sleep(100);
			}
			assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
			assertTrue("The map should be an instance of java.util.LinkedHashMap", 
					Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap"));
			assertNotNull("The computed value of the detail should not be null", fListener.result);
		}
		finally {
			jdfm.removeAssociatedDetailFormatter(formatter);
			terminateAndRemove(thread);
			removeAllBreakpoints();
		}
	}
	
	/**
	 * Tests a detail formatter made from a small compound expression
	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028
	 * @throws Exception
	 */
	public void testSimpleDetails2() throws Exception {
		IJavaThread thread = null;
		DetailFormatter formatter = null;
		JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
		try {
			String typename = "a.b.c.bug403028";
			createLineBreakpoint(10, typename);
			thread = launchToBreakpoint(typename);
			assertNotNull("The program did not suspend", thread);
			String snippet = "return \"map test detail formatter [\" + toString() + \"]\";";
			formatter = new DetailFormatter("java.util.HashMap", snippet, true);
			jdfm.setAssociatedDetailFormatter(formatter);
			IJavaVariable var = thread.findVariable("map");
			assertNotNull("the variable 'map' must exist in the frame", var);
			jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
			long timeout = System.currentTimeMillis()+5000;
			while(fListener.value == null && System.currentTimeMillis() < timeout) {
				Thread.sleep(100);
			}
			assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
			assertTrue("The map should be an instance of java.util.LinkedHashMap", 
					Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap"));
			assertNotNull("The computed value of the detail should not be null", fListener.result);
		}
		finally {
			jdfm.removeAssociatedDetailFormatter(formatter);
			terminateAndRemove(thread);
			removeAllBreakpoints();
		}
	}
	
	/**
	 * Tests a detail formatter made from an infix expression
	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028
	 * @throws Exception
	 */
	public void testInfixDetails1() throws Exception {
		IJavaThread thread = null;
		DetailFormatter formatter = null;
		JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
		try {
			String typename = "a.b.c.bug403028";
			createLineBreakpoint(10, typename);
			thread = launchToBreakpoint(typename);
			assertNotNull("The program did not suspend", thread);
			String snippet = "return (true && true || !(false&&true) || !(true==true||true!=true&&true));";
			formatter = new DetailFormatter("java.util.HashMap", snippet, true);
			jdfm.setAssociatedDetailFormatter(formatter);
			IJavaVariable var = thread.findVariable("map");
			assertNotNull("the variable 'map' must exist in the frame", var);
			jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
			long timeout = System.currentTimeMillis()+5000;
			while(fListener.value == null && System.currentTimeMillis() < timeout) {
				Thread.sleep(100);
			}
			assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
			assertTrue("The map should be an instance of java.util.LinkedHashMap", 
					Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap"));
			assertNotNull("The computed value of the detail should not be null", fListener.result);
			assertTrue("The returned value from (true && true || !(false&&true) || !(true==true||true!=true&&true)) should be true", 
					Boolean.parseBoolean(fListener.result));
		}
		finally {
			jdfm.removeAssociatedDetailFormatter(formatter);
			terminateAndRemove(thread);
			removeAllBreakpoints();
		}
	}
	
	/**
	 * Tests a detail formatter made from an infix expression
	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028
	 * @throws Exception
	 */
	public void testInfixDetails2() throws Exception {
		IJavaThread thread = null;
		DetailFormatter formatter = null;
		JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
		try {
			String typename = "a.b.c.bug403028";
			createLineBreakpoint(10, typename);
			thread = launchToBreakpoint(typename);
			assertNotNull("The program did not suspend", thread);
			String snippet = "return !true;";
			formatter = new DetailFormatter("java.util.HashMap", snippet, true);
			jdfm.setAssociatedDetailFormatter(formatter);
			IJavaVariable var = thread.findVariable("map");
			assertNotNull("the variable 'map' must exist in the frame", var);
			jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
			long timeout = System.currentTimeMillis()+5000;
			while(fListener.value == null && System.currentTimeMillis() < timeout) {
				Thread.sleep(100);
			}
			assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
			assertTrue("The map should be an instance of java.util.LinkedHashMap", 
					Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap"));
			assertNotNull("The computed value of the detail should not be null", fListener.result);
			assertFalse("The returned value from !true should be false", Boolean.parseBoolean(fListener.result));
		}
		finally {
			jdfm.removeAssociatedDetailFormatter(formatter);
			terminateAndRemove(thread);
			removeAllBreakpoints();
		}
	}
	
	/**
	 * Tests a detail formatter made from an infix expression
	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=403028
	 * @throws Exception
	 */
	public void testInfixDetails3() throws Exception {
		IJavaThread thread = null;
		DetailFormatter formatter = null;
		JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
		try {
			String typename = "a.b.c.bug403028";
			createLineBreakpoint(10, typename);
			thread = launchToBreakpoint(typename);
			assertNotNull("The program did not suspend", thread);
			String snippet = "return !(true==true||true!=true&&true);";
			formatter = new DetailFormatter("java.util.HashMap", snippet, true);
			jdfm.setAssociatedDetailFormatter(formatter);
			IJavaVariable var = thread.findVariable("map");
			assertNotNull("the variable 'map' must exist in the frame", var);
			jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
			long timeout = System.currentTimeMillis()+5000;
			while(fListener.value == null && System.currentTimeMillis() < timeout) {
				Thread.sleep(100);
			}
			assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
			assertTrue("The map should be an instance of java.util.LinkedHashMap", 
					Signature.getTypeErasure(fListener.value.getReferenceTypeName()).equals("java.util.LinkedHashMap"));
			assertNotNull("The computed value of the detail should not be null", fListener.result);
			assertFalse("The returned value from !(true==true||true!=true&&true) should be false", Boolean.parseBoolean(fListener.result));
		}
		finally {
			jdfm.removeAssociatedDetailFormatter(formatter);
			terminateAndRemove(thread);
			removeAllBreakpoints();
		}
	}

	/**
	 * Tests a detail formatter made from an collection with no type arguments
	 * 
	 * @see https://bugs.eclipse.org/bugs/show_bug.cgi?id=484686
	 * @throws Exception
	 */
	public void testHoverWithNoTypeArguments() throws Exception {
		IJavaThread thread = null;
		DetailFormatter formatter = null;
		JavaDetailFormattersManager jdfm = JavaDetailFormattersManager.getDefault();
		try {
			String typename = "a.b.c.bug484686";
			createLineBreakpoint(8, typename);
			thread = launchToBreakpoint(typename);
			assertNotNull("The program did not suspend", thread);
			String snippet = "StringBuilder sb = new StringBuilder();\n" + "for (Object obj : this) { \n" + "sb.append(obj).append(\"\\n\"); }\n"
					+ "return sb.toString();";
			formatter = new DetailFormatter("java.util.Collection", snippet, true);
			jdfm.setAssociatedDetailFormatter(formatter);
			IJavaVariable var = thread.findVariable("coll");
			assertNotNull("the variable 'coll' must exist in the frame", var);
			jdfm.computeValueDetail((IJavaValue) var.getValue(), thread, fListener);
			long timeout = System.currentTimeMillis() + 5000;
			while (fListener.value == null && System.currentTimeMillis() < timeout) {
				Thread.sleep(100);
			}
			assertNotNull("The IValue of the detailComputed callback cannot be null", fListener.value);
			assertNotNull("The computed value of the detail should not be null", fListener.result);
		}
		finally {
			jdfm.removeAssociatedDetailFormatter(formatter);
			terminateAndRemove(thread);
			removeAllBreakpoints();
		}
	}
}
