/*******************************************************************************
 * Copyright (c) 2009, 2010 Nokia 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:
 * Nokia - Initial API and implementation
 *******************************************************************************/
package org.eclipse.cdt.debug.edc.debugger.tests;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import junit.framework.Assert;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
import org.eclipse.cdt.debug.edc.internal.services.dsf.Breakpoints;
import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl;
import org.eclipse.cdt.debug.edc.internal.services.dsf.RunControl.ExecutionDMC;
import org.eclipse.cdt.debug.edc.services.EDCServicesTracker;
import org.eclipse.cdt.debug.edc.services.Stack;
import org.eclipse.cdt.debug.edc.tests.EDCTestPlugin;
import org.eclipse.cdt.debug.edc.tests.TestReflectionHelper;
import org.eclipse.cdt.debug.edc.tests.TestUtils;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.Query;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.debug.service.IStack;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.tm.tcf.services.IRunControl;

public class RunControlDMCSubclass extends BaseLaunchTest {

	private static final String bareDMC_id = "testBareDeviceExcecutionDMC"; //$NON-NLS-1$
	private static final String dbg_derived_types_cpp
	  = "C:\\myprog\\BlackFlagWascana\\src\\dbg_derived_types.cpp"; //$NON-NLS-1$
	private static final String unitTestRCExeDMCContextException
	  = "unitTestRunControlExecutionDMCContextException"; //$NON-NLS-1$

	private RunControl runControlService;
	private Breakpoints breakpointsService;
	private IStack stackService;

	@Override
	protected String getExeFileName() {
		// This is the executable built by Cygwin gcc 3.4.4
		// All source files are built from this folder:
		//   "C:\\myprog\\BlackFlagWascana\\src\\"
		// Note we don't need any source file to perform the test.
		//
		// used because the locations of certain line numbers are known,
		// not because there's no hardcoded break
		return "BlackFlagMinGW_NoHardcodedBreak.exe"; //$NON-NLS-1$
	}

	@Override
	protected IStack getStackService() {
		return stackService;
	}

	@Override
	protected boolean getStopAtMain() {
		return true;
	}

	@Before
	public void launch() throws Exception {
		basicLaunch();
		EDCServicesTracker edcTracker
		  = new EDCServicesTracker(EDCDebugger.getBundleContext(), session.getId());
		Assert.assertNotNull(edcTracker);
		runControlService = edcTracker.getService(RunControl.class);
		Assert.assertNotNull(runControlService);
		stackService = edcTracker.getService(Stack.class);
		Assert.assertNotNull(stackService);
		breakpointsService = edcTracker.getService(Breakpoints.class);
		Assert.assertNotNull(breakpointsService);
	}

	@After
	public void shutdown() {
		threadDMC.purgeFromDebugger();
		TestUtils.shutdownDebugSession(launch, session);
		session = null;
	}

	@Test
	public void testBareDeviceExecutionDMC() throws Exception {
		Map<String, Object> bdeDMCProps = new HashMap<String, Object>();
		bdeDMCProps.put(RunControl.PROP_IS_CONTAINER, false);
		bdeDMCProps.put(RunControl.BareDeviceExecutionDMC.PROP_ID, bareDMC_id);
		RunControl.BareDeviceExecutionDMC bdeDMC
		  = runControlService.new BareDeviceExecutionDMC(threadDMC, bdeDMCProps, threadDMC.getTCFContext());
		assertNotNull(bdeDMC);
		assertTrue(bdeDMC.canDetach());

		// 		DMCSuspendedEvent createSuspendedEvent(StateChangeReason reason, Map<String, Object> properties)
		Map<String, Object> cseProps = new HashMap<String, Object>();
		cseProps.put("cseKey1", "cseVal1");
		cseProps.put("cseKey2", "cseVal2");
		RunControl.StateChangeReason scr = RunControl.StateChangeReason.CONTAINER;
		Object[] cseArgs = new Object[] {scr, cseProps};
		Class<?>[] cseArgClasses = new Class<?>[] {scr.getClass(), Map.class};
		RunControl.ContainerSuspendedEvent cse
		  = (RunControl.ContainerSuspendedEvent)TestReflectionHelper
				.objectFromPrivateFunctionWithArgs(bdeDMC, "createSuspendedEvent",
						cseArgs, cseArgClasses);
		assertNotNull(cse);

		Map<String, Object> cseParams = cse.getParams();
		assertNotNull(cseParams);
		Assert.assertEquals(cseProps, cseParams);

		RunControl.IExecutionDMContext[] dmc = cse.getTriggeringContexts();
		assertNotNull(dmc);
		assertEquals(1, dmc.length);
		Assert.assertEquals(bdeDMC, dmc[0]);

		// 		protected DMCResumedEvent createResumedEvent()
		RunControl.ContainerResumedEvent cre
		  = (RunControl.ContainerResumedEvent)TestReflectionHelper
				.objectFromPrivateFunctionWithArgs(bdeDMC, "createResumedEvent", null);
		assertNotNull(cre);

		dmc = cre.getTriggeringContexts();
		assertNotNull(dmc);
		assertEquals(1, dmc.length);
		Assert.assertEquals(bdeDMC, dmc[0]);
	}

	@Test
	public void testExecutionDMCStepOut() throws Exception {
		waitRunToLine(runControlService, dbg_derived_types_cpp, 57);

		// set this so it stops someplace, even if it's after the expected step out point
		setTempBreakpoint(breakpointsService, dbg_derived_types_cpp, 288);

		// 	public abstract class ExectionDMC { protected void stepOut(RequestMonitor) }

		final Class<?>[] stepOutArgClasses = new Class<?>[] {RequestMonitor.class};
		Query<IStatus> query = new Query<IStatus>() {
			@Override
			protected void execute(final DataRequestMonitor<IStatus> drm) {
				ExecutionDMC exeDMC = DMContexts.getAncestorOfType(threadDMC, ExecutionDMC.class);
				Object[] stepOutArgs = new Object[] {drm};
				try {
					TestReflectionHelper.objectFromPrivateFunctionWithArgs(
							exeDMC, ExecutionDMC.class, "stepOut", stepOutArgs, stepOutArgClasses);
				} catch (InvocationTargetException ite) {
					Throwable t = ite.getTargetException(); 
					if ((t instanceof AssertionError)
						&& t.getMessage().equals(RunControl.STEP_RETURN_NOT_SUPPORTED)) {
						drm.setData(new Status(IStatus.INFO, EDCDebugger.PLUGIN_ID,
							RunControl.STEP_RETURN_NOT_SUPPORTED));
					} else {
						drm.setStatus(new Status(IStatus.ERROR, EDCTestPlugin.PLUGIN_ID,
								"InvocationTargetException thrown invoking ExecutionDMC#stepOut() : "//$NON-NLS-1$
								+ ite.getLocalizedMessage()));
					}
					drm.done();
				} catch (Exception e) {
					drm.setStatus(new Status(IStatus.ERROR, EDCTestPlugin.PLUGIN_ID,
							"exception thrown invoking ExecutionDMC#stepOut() : "//$NON-NLS-1$
							+ e.getLocalizedMessage()));
					drm.done();
				}
			}
		};

		try {
			session.getExecutor().execute(query);
		} catch (Exception e) {
			Assert.fail(e.getLocalizedMessage());
		}

		IStatus status = query.get(5, TimeUnit.SECONDS);
		if (status != null) {
			assertTrue(status.getSeverity() == IStatus.INFO);
			assertEquals(RunControl.STEP_RETURN_NOT_SUPPORTED, status.getMessage());
		} else {
			updateSuspendedFrame(200);
			assertControlIsAt("dbg_derived_types.cpp", "dbg_derived_types", 286);
		}
	}

	@Test
	public void testRootDMC() {
		RunControl.RootExecutionDMC rootDMC = runControlService.getRootDMC();
		assertNotNull(rootDMC);
		assertNull(rootDMC.getSymbolDMContext());
		assertFalse(rootDMC.canDetach());
		assertFalse(rootDMC.canStep());
	}

	@Test
	public void testThreadDMC() {
		assertFalse(threadDMC.canDetach());
		ExecutionDMC exeDMC = null;
		try {
			// first arg is a map of properties, but we expect an immediate assert
			exeDMC = threadDMC.contextAdded(null, threadDMC.getTCFContext());
		} catch (AssertionError ae) {
			// this is expected
		}
		assertNull(exeDMC);
	}

	@Test
	public void unitTestRunControlGetModelData() throws Exception {
		Query<Boolean> query = new Query<Boolean>() {
			@Override
			protected void execute(final DataRequestMonitor<Boolean> drm) {
				runControlService.getModelData(threadDMC, drm);
			}
		};

		session.getExecutor().execute(query);

		query.get(2, TimeUnit.SECONDS);
		assertTrue(query.isDone());
	}

	@Test
	public void unitTestRunControlStepIntoOneInstruction() throws Exception {
		waitRunToLine(runControlService, dbg_derived_types_cpp, 285);

		// 	private void stepOverOneInstruction(ExecutionDMC, IAddress, RequestMonitor)

		final Class<?>[] stepIntoArgClasses = new Class<?>[] {ExecutionDMC.class, RequestMonitor.class};
		Query<IStatus> query = new Query<IStatus>() {
			@Override
			protected void execute(final DataRequestMonitor<IStatus> drm) {
				Object[] stepIntoArgs = new Object[] {threadDMC, drm};
				try {
					TestReflectionHelper.objectFromPrivateFunctionWithArgs(
							runControlService, "stepIntoOneInstruction", stepIntoArgs, stepIntoArgClasses);
				} catch (Exception e) {
					drm.setStatus(new Status(IStatus.ERROR, EDCTestPlugin.PLUGIN_ID,
							"exception thrown invoking RunControl#stepIntoOneInstruction()"//$NON-NLS-1$
							+ e.getLocalizedMessage()));
					drm.done();
				}
			}
		};

		session.getExecutor().execute(query);

		query.get(5, TimeUnit.SECONDS);
		assertTrue(query.isDone());

		updateSuspendedFrame(200);
		assertControlIsAt("dbg_derived_types.cpp", "structs", 40);
	}

	@Test
	public void unitTestRunControlStepOverOneInstruction() throws Exception {
		waitRunToLine(runControlService, dbg_derived_types_cpp, 285);

		final IAddress line285Addr = waitGetLineAddress(dbg_derived_types_cpp, 285);
		final Class<?>[] stepOverArgClasses = new Class<?>[] {ExecutionDMC.class, IAddress.class, RequestMonitor.class};
		// 	private void stepOverOneInstruction(ExecutionDMC, IAddress pcAddress, RequestMonitor)
		Query<Boolean> query = new Query<Boolean>() {
			@Override
			protected void execute(final DataRequestMonitor<Boolean> drm) {
				Object[] stepOverArgs = new Object[] {threadDMC, line285Addr, drm};
				try {
					TestReflectionHelper.objectFromPrivateFunctionWithArgs(
							runControlService, "stepOverOneInstruction", stepOverArgs, stepOverArgClasses);
				} catch (Exception e) {
					drm.setStatus(new Status(IStatus.ERROR, EDCTestPlugin.PLUGIN_ID,
							"exception thrown invoking RunControl#stepOverOneInstruction()"//$NON-NLS-1$
							+ e.getLocalizedMessage()));
					drm.done();
				}
			}
		};

		session.getExecutor().execute(query);

		query.get(5, TimeUnit.SECONDS);
		assertTrue(query.isDone());

		updateSuspendedFrame(100);
		assertControlIsAt("dbg_derived_types.cpp", "dbg_derived_types", 286);
	}

	@Test 
	public void coverageRunControlGetSteppingStartTime() {
		long steppingStartTime = RunControl.getSteppingStartTime();
		if (RunControl.timeStepping()) {
			
		} else {
			assertEquals(0, steppingStartTime);
		}
	}

	@Test 
	public void coverageRunControlRunListener() throws Exception {
		IRunControl.RunControlListener runListener
		  = (IRunControl.RunControlListener)
		  		TestReflectionHelper.getPrivateField("runListener", runControlService);

		assertNotNull(runListener);

		// the following will also test ExecutionDMC#contextException()
		runListener.contextException(threadDMC.getID(), unitTestRCExeDMCContextException);
		Thread.sleep(400);	// wait a little for the exception to propagate
		String propMessage = (String)threadDMC.getProperty(RunControl.PROP_MESSAGE);
		assertEquals(unitTestRCExeDMCContextException, propMessage);

		// the next 3 are empty and expected to do nothing
		runListener.containerResumed(null);
		runListener.containerSuspended(null, null, null, null, null);
		runListener.contextChanged(null);

		// resume our thread
		assertTrue(threadDMC.isSuspended());
		runListener.contextResumed(threadDMC.getID());
		Thread.sleep(400);	// wait a little for it to get re-started
		assertFalse(threadDMC.isSuspended());
	}

}
