/*******************************************************************************
 * 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());

		// TODO Modules.ModuleDMData.isSymbolsLoaded() always returns false right now
		Assert.assertFalse(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
}
