/*******************************************************************************
 * Copyright (c) 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.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.eclipse.cdt.core.IAddress;
import org.eclipse.cdt.debug.edc.internal.EDCDebugger;
import org.eclipse.cdt.debug.edc.internal.services.dsf.Modules;
import org.eclipse.cdt.debug.edc.internal.services.dsf.Modules.ModuleDMC;
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.IEDCDMContext;
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.debug.service.IModules;
import org.eclipse.cdt.dsf.debug.service.IModules.IModuleDMContext;
import org.eclipse.cdt.dsf.debug.service.IModules.LineInfo;
import org.eclipse.cdt.utils.Addr32;
import org.junit.AfterClass;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

/**
 * Test that we can recover expressions from stack frames other than the TOS
 */
public class ModulesTest {

	private static final String MODULE_PATH = "C:\\sources\\runtime-New_configuration\\Bug10716\\frame2.exe";//$NON-NLS-1$
	private static final String MODULE_NAME = "frame2.exe";//$NON-NLS-1$

	private static final String MODULE_START = "4194304";//$NON-NLS-N$
	private static final long   MODULE_SIZE = 27648;

	private static final String ADDRESS_RANGE_CHECK = "[0x00400000,0x00406c00)";//$NON-NLS-1$

	private static final String LINE_ADDRESSES_FINAL_CHECK
	  = "EDCLineAddresses [lineNumber=12345, addresses=(0x00400000 0x00400001 0x00400002 0x00400003 0x00400000 0x00400001 0x00400002 0x00400003 )]";//$NON-NLS-1$

	private static SimpleDebuggerTest snapshot;

	private static Modules modulesService;

	private static ExecutionDMC moduleUnloadedExecutionDMC;
	private static ModuleDMC moduleUnloadedModuleDMC;

//	private static class TestModulesDsfService extends AbstractDsfService {			
//
//		public TestModulesDsfService(DsfSession session) {
//			super(session);
//		}
//
//		@Override
//		protected BundleContext getBundleContext() {
//			return EDCTestPlugin.getBundleContext();
//		}
//
//		@Override
//		public void initialize(final RequestMonitor rm) {
//			// - Collect references for the services we interact with
//			// - Register to interesting events
//			// - Obtain the list of platform breakpoints   
//			// - Register the service for interested parties
//			super.initialize(
//				new RequestMonitor(getExecutor(), rm) { 
//		    		@Override
//					protected void handleSuccess() {
//						doInitialize(rm);
//					}});
//		}
//
//		/**
//		 * Asynchronous service initialization 
//		 * 
//		 * @param requestMonitor
//		 */
//		private void doInitialize(RequestMonitor rm) {	
//	        // Register this service
//			register(new String[] { TestModulesDsfService.class.getName() },
//					 new Hashtable<String, String>());
//			rm.done();
//		}
//
//		@Override
//		public void shutdown(final RequestMonitor rm) {
//			unregister();
//			super.shutdown(rm);
//		}
//
//		@SuppressWarnings("unused")
//		@DsfServiceEventHandler
//		public void testEventHandler_moduleUnloaded(ModuleUnloadedDMEvent e) {
//			// An existing module (including main exe) is unloaded. Uninstall
//			// breakpoints for it.
//			ModuleUnloadedEvent event = (ModuleUnloadedEvent) e;
//			synchronized (moduleUnloadedExecutionDMC) {
//				moduleUnloadedExecutionDMC = (ExecutionDMC)event.getExecutionDMC();
//				moduleUnloadedModuleDMC = (ModuleDMC) e.getUnloadedModuleContext();
//			}
//		}
//	}
//	private static TestModulesDsfService testModulesDsfService;

	@BeforeClass
	public static void loadSnapshot() throws Exception {
		snapshot = new SimpleDebuggerTest() {
			@Override
			public String getAlbumName() {
				return "RegisterFrameTests.dsa";//$NON-NLS-1$
			}
		};
		snapshot.launchAndWaitForSuspendedContext();

//		testModulesDsfService = new TestModulesDsfService(snapshot.session);
//		Query<Boolean> query = new Query<Boolean>() {
//			@Override
//			protected void execute(final DataRequestMonitor<Boolean> rm) {
//				testModulesDsfService.initialize(rm);
//			}
//		};
//		snapshot.session.getExecutor().execute(query);
//
//		query.get(3, TimeUnit.SECONDS);
//		Assert.assertTrue(query.isDone());

		EDCServicesTracker edcTracker
		  = new EDCServicesTracker(EDCDebugger.getBundleContext(), snapshot.session.getId());
		Assert.assertNotNull(edcTracker);
		modulesService = edcTracker.getService(Modules.class);
	}

	@AfterClass
	public static void shutdown() throws Exception {
		TestUtils.shutdownDebugSession(snapshot.launch, snapshot.session);

//		Query<Boolean> query = new Query<Boolean>() {
//			@Override
//			protected void execute(final DataRequestMonitor<Boolean> drm) {
//				testModulesDsfService.shutdown(drm);
//			}
//		};
//		snapshot.session.getExecutor().execute(query);
//
//		query.get(3, TimeUnit.SECONDS);
		snapshot = null;
//		Assert.assertTrue(query.isDone());
	}

	@Test
	public void coverageCalcLineInfo() throws Exception {
		Query<LineInfo[]> query = new Query<LineInfo[]>() {
			@Override
			protected void execute(final DataRequestMonitor<LineInfo[]> drm) {
				// TODO Modules.calcLineInfo() is currently auto-generated stub
				modulesService.calcLineInfo(snapshot.threadDMC.getSymbolDMContext(),
						(IAddress)null, drm);
				drm.done();
			}
		};

		snapshot.session.getExecutor().execute(query);

		query.get(1, TimeUnit.SECONDS);
		Assert.assertTrue(query.isDone());
	}

	@Test
	public void testGetFile() throws Exception {
		IModules.ISymbolDMContext symbolDMC = snapshot.threadDMC.getSymbolDMContext();
		Assert.assertNotNull(symbolDMC);
		ModuleDMC moduleDMC = modulesService.getModuleByName(symbolDMC, MODULE_NAME);
		Assert.assertNotNull(moduleDMC);

		Assert.assertEquals(MODULE_NAME, moduleDMC.getFile());
	}

	@Test
	public void testGetModuleData() throws Exception {
		final IModules.ISymbolDMContext symbolDMC = snapshot.threadDMC.getSymbolDMContext();
		Assert.assertNotNull(symbolDMC);
		final ModuleDMC moduleDMC = modulesService.getModuleByName(symbolDMC, MODULE_NAME);
		Assert.assertNotNull(moduleDMC);

		Query<IModules.IModuleDMData> query = new Query<IModules.IModuleDMData>() {
			@Override
			protected void execute(final DataRequestMonitor<IModules.IModuleDMData> drm) {
				modulesService.getModuleData(moduleDMC, drm);
			}
		};

		snapshot.session.getExecutor().execute(query);

		IModules.IModuleDMData moduleDMData = query.get(1, TimeUnit.SECONDS);
		Assert.assertTrue(query.isDone());
		Assert.assertNotNull(moduleDMData);
		Assert.assertEquals(MODULE_START, moduleDMData.getBaseAddress());
		Assert.assertEquals(MODULE_PATH, moduleDMData.getFile());
		Assert.assertEquals(MODULE_NAME, moduleDMData.getName());
		Assert.assertEquals(MODULE_SIZE, moduleDMData.getSize());
		
		// TODO this is not properly complete in Modules.ModuleDMData
		Assert.assertEquals(0, moduleDMData.getTimeStamp());

		// TODO Modules.ModuleDMData should return BaseAddress + size
		Assert.assertEquals(MODULE_START, moduleDMData.getToAddress());

		Assert.assertTrue(moduleDMData.isSymbolsLoaded());
	}

	@Test
	public void testModulesEDCAddressRange() throws Exception {
		IAddress start = new Addr32(MODULE_START);
		IAddress end = start.add(MODULE_SIZE);
		Modules.EDCAddressRange range = new Modules.EDCAddressRange(start, end);
		Assert.assertNotNull(range);

		Assert.assertEquals(start, range.getStartAddress());

		Assert.assertEquals(end, range.getEndAddress());

		Assert.assertTrue(range.contains(start));
		Assert.assertTrue(range.contains(start.add(1)));
		Assert.assertTrue(range.contains(end.add(-1)));
		Assert.assertFalse(range.contains(end));

		Assert.assertEquals(ADDRESS_RANGE_CHECK, range.toString());

		range.setStartAddress(end);
		range.setEndAddress(end.add(1));
		Assert.assertTrue(range.contains(end));
	}

	@Test
	public void testModulesEDCLineAddresses() throws Exception {
		IAddress start = new Addr32(MODULE_START);
		IAddress[] addrs = new IAddress[] {start.add(1), start.add(2), start.add(3) };
		List<IAddress> addrList = new ArrayList<IAddress>(addrs.length);
		addrList.add(start);
		for (IAddress addr : addrs) {
			addrList.add(addr);
		}

		Modules.EDCLineAddresses rangeConstructed = new Modules.EDCLineAddresses(12345, start);
		Modules.EDCLineAddresses rangeFull = new Modules.EDCLineAddresses(12345, addrList);
		
		Assert.assertNotNull(rangeConstructed);
		Assert.assertNotNull(rangeFull);

		Assert.assertEquals(1, rangeConstructed.getAddress().length);
		Assert.assertEquals(4, rangeFull.getAddress().length);

		Assert.assertEquals(12345, rangeConstructed.getLineNumber());
		Assert.assertEquals(12345, rangeFull.getLineNumber());	

		rangeConstructed.addAddress(addrs);
		Assert.assertEquals(rangeFull.toString(), rangeConstructed.toString());

		rangeConstructed.addAddress(addrList);
		Assert.assertEquals(LINE_ADDRESSES_FINAL_CHECK, rangeConstructed.toString());
	}

	// the following test needs to be last
	@Test
	public void testModuleUnloaded() throws Exception {
		Assert.assertNull(moduleUnloadedExecutionDMC);
		Assert.assertNull(moduleUnloadedModuleDMC);
		final IModules.ISymbolDMContext symbolDMC
		  = snapshot.threadDMC.getSymbolDMContext();
		Query<IModuleDMContext[]> query = new Query<IModuleDMContext[]>() {
			@Override
			protected void execute(final DataRequestMonitor<IModuleDMContext[]> drm) {
				modulesService.getModules(symbolDMC, drm);
			}
		};

		snapshot.session.getExecutor().execute(query);

		IModules.IModuleDMContext before[] = query.get(1, TimeUnit.SECONDS);
		Assert.assertTrue(query.isDone());
		Assert.assertTrue(before != null && before.length != 0);

		Map<String, Object> moduleProps = new HashMap<String, Object> ();
		moduleProps.put(IEDCDMContext.PROP_ID, "152");
		modulesService.moduleUnloaded(symbolDMC, snapshot.threadDMC, moduleProps);

		query = new Query<IModuleDMContext[]>() {
			@Override
			protected void execute(final DataRequestMonitor<IModuleDMContext[]> drm) {
				modulesService.getModules(symbolDMC, drm);
			}
		};

		snapshot.session.getExecutor().execute(query);

		IModules.IModuleDMContext after[] = query.get(1, TimeUnit.SECONDS);
		Assert.assertTrue(query.isDone());
		Assert.assertTrue(after == null || after.length == before.length - 1);

//		synchronized (moduleUnloadedExecutionDMC) {
//			Assert.assertNotNull(moduleUnloadedExecutionDMC);
//			Assert.assertNotNull(moduleUnloadedModuleDMC);			
//		}
		
	}
	// the preceding test needs to be last
}
