/*******************************************************************************
 * Copyright (c) 2014 Ericsson 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:
 *     Marc Khouzam (Ericsson) - initial API and implementation
 *******************************************************************************/
package org.eclipse.cdt.examples.dsf.gdb.service;

import java.util.Hashtable;

import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateDataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.ImmediateRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.debug.service.command.CommandCache;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService.ICommandControlDMContext;
import org.eclipse.cdt.dsf.gdb.IGdbDebugConstants;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
import org.eclipse.cdt.dsf.mi.service.command.CommandFactory;
import org.eclipse.cdt.dsf.mi.service.command.output.MIGDBVersionInfo;
import org.eclipse.cdt.dsf.service.AbstractDsfService;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.examples.dsf.gdb.GDBExamplePlugin;
import org.eclipse.cdt.examples.dsf.gdb.service.command.GdbExtendedCommandFactory_6_8;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.IStatusHandler;
import org.osgi.framework.BundleContext;

@SuppressWarnings("restriction")
public class GDBExtendedService extends AbstractDsfService implements IGDBExtendedFunctions {

	private IMICommandControl fCommandControl;
	private CommandFactory fCommandFactory;
	private CommandCache fVersionCache;

    public GDBExtendedService(DsfSession session) {
    	super(session);
    }

    @Override
    public void initialize(final RequestMonitor rm) {
    	super.initialize(new ImmediateRequestMonitor(rm) {
    		@Override
    		protected void handleSuccess() {
    			doInitialize(rm);
			}
		});
	}

	private void doInitialize(RequestMonitor rm) {
		fCommandControl = getServicesTracker().getService(IMICommandControl.class);
		fCommandFactory = fCommandControl.getCommandFactory();

		fVersionCache = new CommandCache(getSession(), fCommandControl);
		fVersionCache.setContextAvailable(fCommandControl.getContext(), true);

		register(new String[] { IGDBExtendedFunctions.class.getName() },
				 new Hashtable<String, String>());

		rm.done();
	}


	@Override
	public void shutdown(RequestMonitor rm) {
		unregister();
		super.shutdown(rm);
	}

	@Override
	protected BundleContext getBundleContext() {
		return GDBExamplePlugin.getBundleContext();
	}

	@Override
	public void notify(ICommandControlDMContext ctx, String str, RequestMonitor rm) {
		IStatus status = new Status(
				IStatus.INFO,
				/* XXX: Need to use GdbPlugin so that we can use GdbStatusHandler to display popup */
				GdbPlugin.getUniqueIdentifier(),
				IGdbDebugConstants.STATUS_HANDLER_CODE,
				str,
				null);
		IStatusHandler statusHandler = DebugPlugin.getDefault().getStatusHandler(status);
		if (statusHandler != null) {
			try {
				statusHandler.handleStatus(status, null);
			}
			catch(CoreException e) {
				GDBExamplePlugin.getDefault().getLog().log(e.getStatus());
			}
		}
		rm.done();
	}

	@Override
	public void getVersion(ICommandControlDMContext ctx, final DataRequestMonitor<String> rm) {
		if (fCommandFactory instanceof GdbExtendedCommandFactory_6_8) {
			GdbExtendedCommandFactory_6_8 factory = (GdbExtendedCommandFactory_6_8)fCommandFactory;

			// Use the cache to avoid having to go to GDB more than once for a value
			// that does not change.  No need to even clear the cache since the GDB version will never change.
			fVersionCache.execute(factory.createCLIGDBVersion(ctx),
					new ImmediateDataRequestMonitor<MIGDBVersionInfo>(rm) {
				@Override
				protected void handleSuccess() {
					rm.done(getData().getVersion());
				}
			});
		} else {
			rm.done(new Status(IStatus.ERROR, GDBExamplePlugin.PLUGIN_ID,
					NOT_SUPPORTED, "Not supported", null)); //$NON-NLS-1$
		}
	}

	@Override
	public void canGetVersion(ICommandControlDMContext ctx, DataRequestMonitor<Boolean> rm) {
		rm.done(fCommandFactory instanceof GdbExtendedCommandFactory_6_8);
	}
}

@@ -843,32 +843,104 @@
 RequestMonitor;%0A
+import org.eclipse.cdt.dsf.debug.service.IRunControl.ISuspendedDMEvent;%0A
 import org.eclip
@@ -986,16 +986,16 @@
 dCache;%0A
-
 import o
@@ -1431,16 +1431,75 @@
 ervice;%0A
+import org.eclipse.cdt.dsf.service.DsfServiceEventHandler;%0A
 import o
@@ -2816,18 +2816,83 @@
 true);%0A%0A
-%09%09
+        getSession().addServiceEventListener(this, null);%0A%0A        
 register
@@ -3076,16 +3076,71 @@
 ster();%0A
+        getSession().removeServiceEventListener(this);%0A
 %09%09super.
@@ -4691,20 +4691,301 @@
 -1$%0A%09%09%7D%0A
-
 %09%7D%0A%0A
+    @DsfServiceEventHandler %0A    public void eventDispatched(ISuspendedDMEvent e) %7B%0A    %09// For the purpose of the example, to learn events and to know when%0A    %09// you can clear the cache, clear the cache unnecessarily on suspend%0A    %09// events%0A    %09fVersionCache.reset();%0A    %7D%0A%0A
 %09@Overri

Clear version cache on suspend events