package org.eclipse.cdt.debug.edc.tests;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutionException;

import org.eclipse.cdt.debug.edc.debugger.tests.SimpleDebuggerTest;
import org.eclipse.cdt.debug.edc.internal.scripting.EDC;
import org.eclipse.cdt.debug.edc.internal.scripting.Launcher;
import org.eclipse.cdt.debug.edc.internal.scripting.StackFrame;
import org.eclipse.cdt.debug.edc.services.IEDCExpression;
import org.eclipse.cdt.debug.edc.symbols.IEDCSymbolReader;
import org.eclipse.cdt.debug.edc.symbols.IFunctionScope;
import org.eclipse.debug.core.model.IBreakpoint;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;

@SuppressWarnings("restriction")
public class Scripting extends SimpleDebuggerTest {

	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		new Thread(new Runnable() {
			
			public void run() {
				try {
					Map<String, Object> events = EDC.listenForEvents("Test");
					Assert.assertTrue(!events.isEmpty());
				} catch (InterruptedException e) {}
			}
		}).start();
		new StackFrame();
		new Launcher();
	}

	@AfterClass
	public static void tearDownAfterClass() throws Exception {
	}

	@Before
	public void setUp() throws Exception {
	}

	@After
	public void tearDown() throws Exception {
	}

	@Test
	public void testGetSessions() {
		String[] sessions = EDC.getSessions();
		Assert.assertEquals(1, sessions.length);
	}

	@Test
	public void testGetContexts() throws Exception {
		Map<String, Object>[] contexts = EDC.getContexts(session.getId());
		Assert.assertEquals(2, contexts.length);
	}

	@Test
	public void testGetSuspendedContexts() throws Exception {
		Map<String, Object>[] contexts = EDC.getSuspendedContexts(session.getId());
		Assert.assertEquals(2, contexts.length);
	}

	@Test
	public void testGetSuspendedThreads() throws Exception {
		Map<String, Object>[] threads = EDC.getSuspendedThreads(session.getId());
		Assert.assertEquals(1, threads.length);
	}

	@Test
	public void testGetDsfServicesTracker() {
		Assert.assertNotNull(EDC.getDsfServicesTracker(session.getId()));
	}

	@Test
	public void testGetBreakpoints() {
		IBreakpoint[] breakpoints = EDC.getBreakpoints();
		Assert.assertEquals(0, breakpoints.length);
	}

	@Test
	public void testGetFunctionAtAddress() throws Exception {
		IFunctionScope function = EDC.getFunctionAtAddress(session.getId(), "405ae0");
		Assert.assertEquals("dbg_variables_local", function.getName());
	}

	@Test
	public void testGetSymbolReader() throws Exception {
		String res_folder = EDCTestPlugin.projectRelativePath("resources/SymbolFiles/BlackFlag_gcce.sym");
		IEDCSymbolReader reader = EDC.getSymbolReader(res_folder);
		Assert.assertNotNull(reader);
	}

	@Test
	public void testCreateAddressBreakpoint() throws Exception {
		IBreakpoint breakpoint = EDC.createAddressBreakpoint(0x405ae0, "");
		Assert.assertNotNull(breakpoint);
	}

	@Test
	public void testCreateFunctionBreakpoint() throws Exception {
		IBreakpoint breakpoint = EDC.createFunctionBreakpoint(null, "", "Test", 0, "");
		Assert.assertNotNull(breakpoint);
	}

	@Test
	public void testCreateLineBreakpoint() throws Exception {
		IBreakpoint breakpoint = EDC.createLineBreakpoint(null, "Test", 0, "");
		Assert.assertNotNull(breakpoint);
	}

	@Test
	public void testCreateExpression() throws Exception {
		IEDCExpression expression = EDC.createExpression(session.getId(), frame, "lint");
		Assert.assertNotNull(expression);
	}

	@Test
	public void testSetBreakpoints() throws Exception {
		List<Map<String, Object>> breakpoints = new ArrayList<Map<String,Object>>();
		EDC.setBreakpoints(breakpoints);
	}

	@Test
	public void testGetVariables() throws Exception, ExecutionException {
		List<Map<String, Object>> variables = EDC.getVariables(session.getId(), threadDMC.getID(), 0);
		Assert.assertEquals(9, variables.size());
	}

	@Test
	public void testGetStackFrames() throws Exception, InterruptedException {
		List<Map<String, Object>> frames = EDC.getStackFrames(session.getId(), threadDMC.getID());
		Assert.assertEquals(6, frames.size());
	}

	@Test
	public void testTerminate() {
		EDC.terminate(session.getId(), threadDMC.getID());
	}

	@Test
	public void testResume() {
		EDC.resume(session.getId(), threadDMC.getID());
	}

	@Override
	public String getAlbumName() {
		return "ExpressionsBasic.dsa";
	}

}
