/*******************************************************************************
 * Copyright (c) 2006, 2018 Wind River Systems and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     Wind River Systems - initial API and implementation
 *     Ericsson 		  - Modified for handling of multiple stacks and threads
 *     Nokia - create and use backend service.
 *     Onur Akdemir (TUBITAK BILGEM-ITI) - Multi-process debugging (Bug 237306)
 *     Marc Khouzam (Ericsson) - New method to properly created ErrorThread (Bug 350837)
 *     Jason Litton (Sage Electronic Engineering, LLC) - Use Dynamic Tracing option (Bug 379169)
 *     Jonah Graham (Kichwa Coders) - Bug 317173 - cleanup warnings
 *     John Dallaway - Decode line breaks in status message (Bug 539455)
 *******************************************************************************/
package org.eclipse.cdt.dsf.mi.service.command;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.RejectedExecutionException;

import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
import org.eclipse.cdt.dsf.concurrent.DataRequestMonitor;
import org.eclipse.cdt.dsf.concurrent.DsfRunnable;
import org.eclipse.cdt.dsf.concurrent.RequestMonitor;
import org.eclipse.cdt.dsf.datamodel.AbstractDMEvent;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.ICachingService;
import org.eclipse.cdt.dsf.debug.service.IRunControl;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.debug.service.command.ICommand;
import org.eclipse.cdt.dsf.debug.service.command.ICommandControlService;
import org.eclipse.cdt.dsf.debug.service.command.ICommandListener;
import org.eclipse.cdt.dsf.debug.service.command.ICommandResult;
import org.eclipse.cdt.dsf.debug.service.command.ICommandToken;
import org.eclipse.cdt.dsf.debug.service.command.IEventListener;
import org.eclipse.cdt.dsf.gdb.IGdbDebugPreferenceConstants;
import org.eclipse.cdt.dsf.gdb.internal.GdbDebugOptions;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.mi.service.IMICommandControl;
import org.eclipse.cdt.dsf.mi.service.IMIContainerDMContext;
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
import org.eclipse.cdt.dsf.mi.service.command.commands.MICommand;
import org.eclipse.cdt.dsf.mi.service.command.commands.RawCommand;
import org.eclipse.cdt.dsf.mi.service.command.output.MIConst;
import org.eclipse.cdt.dsf.mi.service.command.output.MIInfo;
import org.eclipse.cdt.dsf.mi.service.command.output.MIList;
import org.eclipse.cdt.dsf.mi.service.command.output.MIOOBRecord;
import org.eclipse.cdt.dsf.mi.service.command.output.MIOutput;
import org.eclipse.cdt.dsf.mi.service.command.output.MIParser;
import org.eclipse.cdt.dsf.mi.service.command.output.MIResult;
import org.eclipse.cdt.dsf.mi.service.command.output.MIResultRecord;
import org.eclipse.cdt.dsf.mi.service.command.output.MIStreamRecord;
import org.eclipse.cdt.dsf.mi.service.command.output.MIValue;
import org.eclipse.cdt.dsf.service.AbstractDsfService;
import org.eclipse.cdt.dsf.service.DsfServicesTracker;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.osgi.util.NLS;

import com.ibm.icu.text.MessageFormat;

/**
 * Base implementation of an MI control service.  It provides basic handling
 * of input/output channels, and processing of the commands.
 * <p>
 * Extending classes need to implement the initialize() and shutdown() methods.
 */
public abstract class AbstractMIControl extends AbstractDsfService implements IMICommandControl {
	private static final String MI_TRACE_IDENTIFIER = "[MI]"; //$NON-NLS-1$
	private static final int NUMBER_CONCURRENT_COMMANDS = 3;
	private static final int DEVELOPMENT_TRACE_LIMIT_CHARS = 5000;

	/*
	 *  Thread control variables for the transmit and receive threads.
	 */

	private TxThread fTxThread;
	private RxThread fRxThread;
	private ErrorThread fErrorThread;

	// MI did not always support the --thread/--frame options
	// This boolean is used to know if we should use -thread-select and -stack-select-frame instead
	private boolean fUseThreadAndFrameOptions;
	// currentStackLevel and currentThreadId are only necessary when
	// we must use -thread-select and -stack-select-frame
	private int fCurrentStackLevel = -1;
	private String fCurrentThreadId = null;

	// boolean for --thread-group option which helps to handle multiple inferior behavior.
	// Since GDB.7.1
	private boolean fUseThreadGroupOption;

	private final BlockingQueue<CommandHandle> fTxCommands = new LinkedBlockingQueue<>();
	private final Map<Integer, CommandHandle> fRxCommands = Collections
			.synchronizedMap(new HashMap<Integer, CommandHandle>());

	/**
	 * Handle that's inserted into the TX commands queue to signal
	 * that the TX thread should shut down.
	 */
	private final CommandHandle fTerminatorHandle = new CommandHandle(null, null);

	/*
	 *   Various listener control variables used to keep track of listeners who want to monitor
	 *   what the control object is doing.
	 */

	private final List<ICommandListener> fCommandProcessors = new ArrayList<>();
	private final List<IEventListener> fEventProcessors = new ArrayList<>();

	/**
	 *   Current command which have not been handed off to the backend yet.
	 */

	private final List<CommandHandle> fCommandQueue = new ArrayList<>();

	/**
	 * Flag indicating that the command control has stopped processing commands.
	 */
	private boolean fStoppedCommandProcessing = false;

	/**
	 * An output stream that MI communication should be output to.
	 * It serves for debugging. Can be <code>null</code> to disable tracing.
	 */
	private OutputStream fTracingStream = null;

	private CommandFactory fCommandFactory;

	/**
	 * Event indicating that the back end process has started.
	 */
	private static class RefreshAllDMEvent extends AbstractDMEvent<ICommandControlDMContext>
			implements ICommandControlRefreshAllDMEvent {
		public RefreshAllDMEvent(ICommandControlDMContext context) {
			super(context);
		}
	}

	public AbstractMIControl(DsfSession session) {
		this(session, false, false, new CommandFactory());
	}

	/**
	 * @since 3.0
	 */
	public AbstractMIControl(DsfSession session, boolean useThreadAndFrameOptions, CommandFactory factory) {
		this(session, false, useThreadAndFrameOptions, factory);
	}

	/**
	 * @since 4.0
	 */
	public AbstractMIControl(DsfSession session, boolean useThreadGroupOption, boolean useThreadAndFrameOptions,
			CommandFactory factory) {
		super(session);

		// If we use the --thread-group option, we should automatically use the --thread/--frame option
		// since the --thread-group was added to GDB later than the --thread/--frame option
		assert useThreadGroupOption ? useThreadAndFrameOptions : true;

		fUseThreadGroupOption = useThreadGroupOption;
		fUseThreadAndFrameOptions = useThreadAndFrameOptions;
		if (fUseThreadGroupOption) {
			// If we use --thread-group option, we should automatically use the --thread option
			fUseThreadAndFrameOptions = true;
		}
		fCommandFactory = factory;
	}

	/**
	 * Set the tracing stream for the MI communication.  If this method is never
	 * called, tracing will be off, by default.
	 *
	 * @param tracingStream The stream to use.  Can be <code>null</code>
	 * to disable tracing.
	 * @since 2.0
	 */
	protected synchronized void setMITracingStream(OutputStream tracingStream) {
		fTracingStream = tracingStream;
	}

	/**
	 * Returns the MI tracing stream.
	 */
	private synchronized OutputStream getMITracingStream() {
		return fTracingStream;
	}

	/**
	 * @since 3.0
	 */
	protected void setUseThreadAndFrameOptions(boolean shouldUse) {
		fUseThreadAndFrameOptions = shouldUse;
	}

	/**
	 * @since 4.0
	 */
	protected void setUseThreadGroupOptions(boolean shouldUse) {
		fUseThreadGroupOption = shouldUse;
		if (shouldUse) {
			fUseThreadAndFrameOptions = true;
		}
	}

	/**
	 * @since 3.0
	 */
	@Override
	public CommandFactory getCommandFactory() {
		return fCommandFactory;
	}

	/**
	 * Starts the threads that process the debugger input/output channels.
	 * To be invoked by the initialization routine of the extending class.
	 *
	 * This version of the method will not start a thread for the error stream.
	 *
	 * @param inStream
	 * @param outStream
	 */
	protected void startCommandProcessing(InputStream inStream, OutputStream outStream) {
		startCommandProcessing(inStream, outStream, null);
	}

	/**
	 * Starts the threads that process the debugger input/output/error channels.
	 * To be invoked by the initialization routine of the extending class.
	 *
	 *
	 * @param inStream
	 * @param outStream
	 * @param errorStream
	 * @since 4.1
	 */
	protected void startCommandProcessing(InputStream inStream, OutputStream outStream, InputStream errorStream) {

		fTxThread = new TxThread(outStream);
		fRxThread = new RxThread(inStream);

		if (errorStream != null) {
			fErrorThread = new ErrorThread(errorStream);
		}

		fTxThread.start();
		fRxThread.start();
		if (fErrorThread != null) {
			fErrorThread.start();
		}
	}

	/**
	 *  Stops the threads that process the debugger input/output channels, and notifies the
	 *  results of the outstanding commands. To be invoked by the shutdown routine of the
	 *  extending class.
	 *
	 * @param inStream
	 * @param outStream
	 */

	private Status genStatus(String str) {
		return new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE, str, null);
	}

	protected void stopCommandProcessing() {
		// Guard against calling this multiple times (e.g. as a result of a
		// user request and an event from the back end).
		if (fStoppedCommandProcessing)
			return;
		fStoppedCommandProcessing = true;

		/*
		 *  First go through the commands which have been queueud and not yet sent to the backend.
		 */
		for (CommandHandle commandHandle : fCommandQueue) {
			if (commandHandle.getRequestMonitor() == null)
				continue;
			commandHandle.getRequestMonitor().setStatus(genStatus("Connection is shut down")); //$NON-NLS-1$
			commandHandle.getRequestMonitor().done();
		}
		fCommandQueue.clear();

		/*
		 *  Now go through the commands which are outstanding in that they have been sent to the backend.
		 */
		cancelRxCommands();

		/*
		 *  Now handle any requests which have not been transmitted, but weconsider them handed off.
		 */
		List<CommandHandle> txCommands = new ArrayList<>();
		fTxCommands.drainTo(txCommands);
		for (CommandHandle commandHandle : txCommands) {
			if (commandHandle.getRequestMonitor() == null)
				continue;
			commandHandle.getRequestMonitor().setStatus(genStatus("Connection is shut down")); //$NON-NLS-1$
			commandHandle.getRequestMonitor().done();
		}

		// Queue a null value to tell the send thread to shut down.
		fTxCommands.add(fTerminatorHandle);
	}

	private synchronized void cancelRxCommands() {
		for (CommandHandle commandHandle : fRxCommands.values()) {
			if (commandHandle.getRequestMonitor() == null)
				continue;
			commandHandle.getRequestMonitor().setStatus(genStatus("Connection is shut down")); //$NON-NLS-1$
			commandHandle.getRequestMonitor().done();
		}
		fRxCommands.clear();
	}

	/**
	 * Queues the given MI command to be sent to the debugger back end.
	 *
	 * @param command Command to be executed.  This parameter must be an
	 * instance of DsfMICommand, otherwise a ClassCastException will be
	 * thrown.
	 * @param rm Request completion monitor
	 *
	 * @see org.eclipse.cdt.dsf.debug.service.command.ICommandControl#addCommand(org.eclipse.cdt.dsf.debug.service.command.ICommand, org.eclipse.cdt.dsf.concurrent.RequestMonitor)
	 */

	@Override
	public <V extends ICommandResult> ICommandToken queueCommand(final ICommand<V> command, DataRequestMonitor<V> rm) {

		// Cast the command to MI Command type.  This will cause a cast exception to be
		// thrown if the client did not give an MI command as an argument.
		@SuppressWarnings("unchecked")
		MICommand<MIInfo> miCommand = (MICommand<MIInfo>) command;

		// Cast the return token to match the result type of MI Command.  This is checking
		// against an erased type so it should never throw any exceptions.
		@SuppressWarnings("unchecked")
		DataRequestMonitor<MIInfo> miDone = (DataRequestMonitor<MIInfo>) rm;

		final CommandHandle handle = new CommandHandle(miCommand, miDone);

		// If the command control stopped processing commands, just return an error immediately.
		if (fStoppedCommandProcessing) {
			rm.setStatus(genStatus("Connection is shut down")); //$NON-NLS-1$
			rm.done();
		} else {
			/*
			 *  We only allow three outstanding commands to be on the wire to the backend
			 *  at any one time. This allows for coalescing as well as canceling
			 *  existing commands on a state change. So we add it to the waiting list and let
			 *  the user know they can now work with this item if need be.
			 */
			fCommandQueue.add(handle);
			processCommandQueued(handle);

			if (fRxCommands.size() < NUMBER_CONCURRENT_COMMANDS) {
				// In a separate dispatch cycle.  This allows command listeners
				// to respond to the command queued event.
				getExecutor().execute(new DsfRunnable() {
					@Override
					public void run() {
						processNextQueuedCommand();
					}
				});
			}
		}

		return handle;
	}

	private void processNextQueuedCommand() {
		if (!fCommandQueue.isEmpty()) {
			final CommandHandle handle = fCommandQueue.remove(0);
			if (handle != null) {
				processCommandSent(handle);

				// Older debuggers didn't support the --thread/--frame options
				// Also, not all commands support those options (e.g., CLI commands)
				if (!fUseThreadAndFrameOptions || !handle.getCommand().supportsThreadAndFrameOptions()) {
					// Without the --thread/--frame, we need to send the proper
					// -thread-select and -stack-frame-select before sending the command

					final IDMContext targetContext = handle.fCommand.getContext();
					final String targetThread = handle.getThreadId();
					final int targetFrame = handle.getStackFrameId();

					// The thread-select and frame-select make sense only if the thread is stopped.
					IRunControl runControl = getServicesTracker().getService(IRunControl.class);
					IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(targetContext,
							IMIExecutionDMContext.class);
					if (runControl != null && execDmc != null && runControl.isSuspended(execDmc)) {
						// Before the command is sent, Check the Thread Id and send it to
						// the queue only if the id has been changed. Also, don't send a threadId of 0,
						// because that id is only used internally for single-threaded programs
						if (targetThread != null && !targetThread.equals("0") //$NON-NLS-1$
								&& !targetThread.equals(fCurrentThreadId)) {
							fCurrentThreadId = targetThread;
							resetCurrentStackLevel();
							CommandHandle cmdHandle = new CommandHandle((MICommand<MIInfo>) getCommandFactory()
									.createMIThreadSelect(targetContext, targetThread), null);
							cmdHandle.generateTokenId();
							fTxCommands.add(cmdHandle);
						}

						// Before the command is sent, Check the Stack level and send it to
						// the queue only if the level has been changed.
						if (targetFrame >= 0 && targetFrame != fCurrentStackLevel) {
							fCurrentStackLevel = targetFrame;
							CommandHandle cmdHandle = new CommandHandle((MICommand<MIInfo>) getCommandFactory()
									.createMIStackSelectFrame(targetContext, targetFrame), null);
							cmdHandle.generateTokenId();
							fTxCommands.add(cmdHandle);
						}
					}
				}

				if (!(handle.getCommand() instanceof RawCommand)) {
					// Only generate a token id if the command is not a RawCommand
					// RawCommands are sent to GDB without an answer expected, so we don't
					// need a token id.  In fact, GDB will fail if we send one in this case.
					handle.generateTokenId();
				}
				fTxCommands.add(handle);
			}
		}
	}

	/*
	 *   This is the command which allows the user to retract a previously issued command. The
	 *   state of the command  is that it is in the waiting queue  and has not yet been handed
	 *   to the backend yet.
	 *
	 * (non-Javadoc)
	 * @see org.eclipse.cdt.dsf.mi.service.command.IDebuggerControl#removeCommand(org.eclipse.cdt.dsf.mi.service.command.commands.ICommand)
	 */
	@Override
	public void removeCommand(ICommandToken token) {

		synchronized (fCommandQueue) {

			for (CommandHandle handle : fCommandQueue) {
				if (handle.equals(token)) {
					fCommandQueue.remove(handle);

					final CommandHandle finalHandle = handle;
					getExecutor().execute(new DsfRunnable() {
						@Override
						public void run() {
							processCommandRemoved(finalHandle);
						}
					});
					break;
				}
			}
		}
	}

	/*
	 *  Allows a user ( typically a cache manager ) to sign up a listener to monitor command queue
	 *  activity.
	 *
	 * (non-Javadoc)
	 * @see org.eclipse.cdt.dsf.mi.service.command.IDebuggerControl#addCommandListener(org.eclipse.cdt.dsf.mi.service.command.IDebuggerControl.ICommandListener)
	 */
	@Override
	public void addCommandListener(ICommandListener processor) {
		fCommandProcessors.add(processor);
	}

	/*
	 *  Allows a user ( typically a cache manager ) to remove a monitoring listener.
	 * (non-Javadoc)
	 * @see org.eclipse.cdt.dsf.mi.service.command.IDebuggerControl#removeCommandListener(org.eclipse.cdt.dsf.mi.service.command.IDebuggerControl.ICommandListener)
	 */
	@Override
	public void removeCommandListener(ICommandListener processor) {
		fCommandProcessors.remove(processor);
	}

	/*
	 *  Allows a user to sign up to a listener which handles out of band messages ( events ).
	 *
	 * (non-Javadoc)
	 * @see org.eclipse.cdt.dsf.mi.service.command.IDebuggerControl#addEventListener(org.eclipse.cdt.dsf.mi.service.command.IDebuggerControl.IEventListener)
	 */
	@Override
	public void addEventListener(IEventListener processor) {
		fEventProcessors.add(processor);
	}

	/*
	 *  Allows a user to remove a event monitoring listener.
	 *
	 * (non-Javadoc)
	 * @see org.eclipse.cdt.dsf.mi.service.command.IDebuggerControl#removeEventListener(org.eclipse.cdt.dsf.mi.service.command.IDebuggerControl.IEventListener)
	 */
	@Override
	public void removeEventListener(IEventListener processor) {
		fEventProcessors.remove(processor);
	}

	/** @deprecated Replaced with {@link ICommandControlService#getContext()} */
	@Deprecated
	abstract public MIControlDMContext getControlDMContext();

	/**
	 * @since 1.1
	 */
	@Override
	public boolean isActive() {
		return !fStoppedCommandProcessing;
	}

	/*
	 *  These are the service routines which perform the various callouts back to the listeners.
	 */

	private void processCommandQueued(CommandHandle commandHandle) {
		for (ICommandListener processor : fCommandProcessors) {
			processor.commandQueued(commandHandle);
		}
	}

	private void processCommandRemoved(CommandHandle commandHandle) {
		for (ICommandListener processor : fCommandProcessors) {
			processor.commandRemoved(commandHandle);
		}
	}

	private void processCommandSent(CommandHandle commandHandle) {
		for (ICommandListener processor : fCommandProcessors) {
			processor.commandSent(commandHandle);
		}
	}

	private void processCommandDone(CommandHandle commandHandle, ICommandResult result) {
		/*
		 *  Tell the listeners we have completed this one.
		 */
		for (ICommandListener processor : fCommandProcessors) {
			processor.commandDone(commandHandle, result);
		}
	}

	private void processEvent(MIOutput output) {
		for (IEventListener processor : fEventProcessors) {
			processor.eventReceived(output);
		}
	}

	/*
	 * A global counter for all command, the token will be use to identify uniquely a command.
	 * Unless the value wraps around which is unlikely.
	 */
	private int fTokenIdCounter = 0;

	private int getNewTokenId() {
		int count = ++fTokenIdCounter;
		// If we ever wrap around.
		if (count <= 0) {
			count = fTokenIdCounter = 1;
		}
		return count;
	}

	/**
	 * Write the str containing an MI message to the tracing stream.
	 * The str will generally have a newline already if toGdb is true,
	 * and will need a newline if toGdb is false.
	 * @param toGdb true if MI is to GDB, false if from GDB
	 * @param str string containing MI message
	 * @since 5.6
	 */
	protected void writeToTracingStream(boolean toGdb, final String str) {
		if (getMITracingStream() != null) {
			try {
				String message = GdbPlugin.getDebugTime() + " " + str + (toGdb ? "" : "\n"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				IEclipsePreferences node = InstanceScope.INSTANCE.getNode(GdbPlugin.PLUGIN_ID);
				boolean limitEnabled = node.getBoolean(IGdbDebugPreferenceConstants.PREF_MAX_MI_OUTPUT_LINES_ENABLE,
						IGdbDebugPreferenceConstants.MAX_MI_OUTPUT_LINES_ENABLE_DEFAULT);
				int initialMaxLines = IGdbDebugPreferenceConstants.MAX_MI_OUTPUT_LINES_DEFAULT;
				try {
					initialMaxLines = node.getInt(IGdbDebugPreferenceConstants.PREF_MAX_MI_OUTPUT_LINES,
							IGdbDebugPreferenceConstants.MAX_MI_OUTPUT_LINES_DEFAULT);
				} catch (NumberFormatException e) {
				}
				int linecounter = initialMaxLines;

				while (message.length() > 100 && (!limitEnabled || linecounter-- > 0)) {
					String partial = message.substring(0, 100);
					message = message.substring(100);
					getMITracingStream().write(partial.getBytes());
					getMITracingStream().write("\\\n".getBytes()); //$NON-NLS-1$
				}
				if (linecounter <= 0) {
					String messageTruncatedInfo = NLS.bind(Messages.AbstractMIControl_message_truncated,
							initialMaxLines);
					getMITracingStream().write(messageTruncatedInfo.getBytes());
				} else {
					getMITracingStream().write(message.getBytes());
				}
			} catch (IOException e) {
				// The tracing stream could be closed at any time
				// since the user can set a preference to turn off
				// this tracing.
				setMITracingStream(null);
			}
		}
	}
	/*
	 *  Support class which creates a convenient wrapper for holding all information about an
	 *  individual request.
	 */

	private class CommandHandle implements ICommandToken {

		private MICommand<MIInfo> fCommand;
		private DataRequestMonitor<MIInfo> fRequestMonitor;
		private int fTokenId;

		CommandHandle(MICommand<MIInfo> c, DataRequestMonitor<MIInfo> d) {
			fCommand = c;
			fRequestMonitor = d;
			fTokenId = -1; // Only initialize to a real value when needed
		}

		@Override
		public MICommand<MIInfo> getCommand() {
			return fCommand;
		}

		public DataRequestMonitor<MIInfo> getRequestMonitor() {
			return fRequestMonitor;
		}

		// This method allows us to generate the token Id when we area actually going to use
		// it.  It is meant to help order the token ids based on when commands will actually
		// be sent
		public void generateTokenId() {
			fTokenId = getNewTokenId();
		}

		public Integer getTokenId() {
			return fTokenId;
		}

		public int getStackFrameId() {
			IFrameDMContext frameCtx = DMContexts.getAncestorOfType(fCommand.getContext(), IFrameDMContext.class);
			if (frameCtx != null)
				return frameCtx.getLevel();
			return -1;
		}

		public String getThreadId() {
			IMIExecutionDMContext execCtx = DMContexts.getAncestorOfType(fCommand.getContext(),
					IMIExecutionDMContext.class);
			if (execCtx != null)
				return execCtx.getThreadId();
			return null;
		}

		public String getGroupId() {
			IMIContainerDMContext containerCtx = DMContexts.getAncestorOfType(fCommand.getContext(),
					IMIContainerDMContext.class);
			if (containerCtx != null)
				return containerCtx.getGroupId();
			return null;
		}

		@Override
		public String toString() {
			return Integer.toString(fTokenId) + fCommand;
		}
	}

	/*
	 *  This is the transmitter thread. When a command is given to this thread it has been
	 *  considered to be sent, even if it has not actually been sent yet.  This assumption
	 *  makes it easier from state management.  Whomever fill this pipeline handles all of
	 *  the required state notification ( callbacks ). This thread simply physically gives
	 *  the message to the backend.
	 */

	private class TxThread extends Thread {

		final private OutputStream fOutputStream;

		public TxThread(OutputStream outStream) {
			super("MI TX Thread"); //$NON-NLS-1$
			fOutputStream = outStream;
		}

		@Override
		public void run() {
			while (true) {
				CommandHandle commandHandle = null;

				try {
					commandHandle = fTxCommands.take();
				} catch (InterruptedException e) {
					break; // Shutting down.
				}

				if (commandHandle == fTerminatorHandle) {
					// There is a small possibility that a new command was inserted
					// in the fRxCommands map after we cleared that map.
					// Just to be safe, clear it again.
					// We do this to avoid synchronizing the handling of fRxCommands
					// because this is more efficient, as it happens only once at shutdown.
					cancelRxCommands();
					break; // Null command is an indicator that we're shutting down.
				}

				/*
				 *  We note that this is an outstanding request at this point.
				 */
				if (!(commandHandle.getCommand() instanceof RawCommand)) {
					// RawCommands will not get an answer, so we cannot put them in the receive queue.
					fRxCommands.put(commandHandle.getTokenId(), commandHandle);
				}

				/*
				 *   Construct the new command and push this command out the pipeline.
				 */

				final String str;
				if (commandHandle.getCommand() instanceof RawCommand) {
					// RawCommands CANNOT have a token id: GDB would read it as part of the RawCommand!
					str = commandHandle.getCommand().constructCommand();
				} else if (fUseThreadGroupOption) {
					// Implies that fUseThreadAndFrameOptions == true
					str = commandHandle.getTokenId() + commandHandle.getCommand().constructCommand(
							commandHandle.getGroupId(), commandHandle.getThreadId(), commandHandle.getStackFrameId());
				} else if (fUseThreadAndFrameOptions) {
					str = commandHandle.getTokenId() + commandHandle.getCommand()
							.constructCommand(commandHandle.getThreadId(), commandHandle.getStackFrameId());
				} else {
					str = commandHandle.getTokenId() + commandHandle.getCommand().constructCommand();
				}

				try {
					if (fOutputStream != null) {

						if (GdbDebugOptions.DEBUG) {
							GdbDebugOptions.trace(
									String.format("%s %s  %s", GdbPlugin.getDebugTime(), MI_TRACE_IDENTIFIER, str)); //$NON-NLS-1$
						}
						writeToTracingStream(true, str);

						fOutputStream.write(str.getBytes());
						fOutputStream.flush();
					}
				} catch (IOException e) {
					// Shutdown thread in case of IO error.
					break;
				}
			}
			// Must close the stream here to avoid leaking
			// Bug 345164 and Bug 339379
			try {
				if (fOutputStream != null)
					fOutputStream.close();
			} catch (IOException e) {
			}
		}
	}

	private class RxThread extends Thread {
		private final InputStream fInputStream;
		private final MIParser fMiParser = new MIParser();

		/**
		 * List of out of band records since the last result record. Out of band
		 * records are required for processing the results of CLI commands.
		 */
		private final List<MIOOBRecord> fAccumulatedOOBRecords = new LinkedList<>();

		/**
		 * List of stream records since the last result record, not including
		 * the record currently being processed (if it's a stream one). This is
		 * a subset of {@link #fAccumulatedOOBRecords}, as a stream record is a
		 * particular type of OOB record.
		 */
		private final List<MIStreamRecord> fAccumulatedStreamRecords = new LinkedList<>();

		public RxThread(InputStream inputStream) {
			super("MI RX Thread"); //$NON-NLS-1$
			fInputStream = inputStream;
		}

		@Override
		public void run() {
			BufferedReader reader = new BufferedReader(new InputStreamReader(fInputStream));
			try {
				String line;
				while ((line = reader.readLine()) != null) {
					if (line.length() != 0) {
						// Write Gdb response to sysout or file
						if (GdbDebugOptions.DEBUG) {
							if (line.length() < DEVELOPMENT_TRACE_LIMIT_CHARS) {
								GdbDebugOptions.trace(String.format("%s %s  %s\n", GdbPlugin.getDebugTime(), //$NON-NLS-1$
										MI_TRACE_IDENTIFIER, line));
							} else {
								// "-list-thread-groups --available" give a very large output that is not very useful but that makes
								// looking at the traces much more difficult.  Don't show the full output in the traces.
								// If we really need to see that output, it will still be in the 'gdb traces'.
								GdbDebugOptions.trace(String.format("%s %s  %s\n", GdbPlugin.getDebugTime(), //$NON-NLS-1$
										MI_TRACE_IDENTIFIER, line.substring(0, DEVELOPMENT_TRACE_LIMIT_CHARS)
												+ " [remaining output truncated. Refer to 'gdb traces' if full output needed.]")); //$NON-NLS-1$
							}
						}

						writeToTracingStream(false, line);
						processMIOutput(line);
					}
				}
			} catch (IOException e) {
				// Socket is shut down.
			} catch (RejectedExecutionException e) {
				// Dispatch thread is down.
			}
			// Must close the stream here to avoid leaking and
			// to give enough time to read all the data
			// Bug 345164 and Bug 339379
			try {
				fInputStream.close();
			} catch (IOException e) {
			}
		}

		private MIResult findResultRecord(MIResult[] results, String variable) {
			for (int i = 0; i < results.length; i++) {
				if (variable.equals(results[i].getVariable())) {
					return results[i];
				}
			}
			return null;
		}

		private String getStatusString(MICommand<MIInfo> origCommand, MIOutput response) {

			// Attempt to extract a message from the result record:
			String message = null;
			String[] parameters = null;
			if (response != null && response.getMIResultRecord() != null) {
				MIResult[] results = response.getMIResultRecord().getMIResults();

				// Extract the parameters
				MIResult paramsRes = findResultRecord(results, "parameters"); //$NON-NLS-1$
				if (paramsRes != null && paramsRes.getMIValue() instanceof MIList) {
					MIValue[] paramValues = ((MIList) paramsRes.getMIValue()).getMIValues();
					parameters = new String[paramValues.length];
					for (int i = 0; i < paramValues.length; i++) {
						if (paramValues[i] instanceof MIConst) {
							parameters[i] = ((MIConst) paramValues[i]).getString();
						} else {
							parameters[i] = ""; //$NON-NLS-1$
						}
					}
				}
				MIResult messageRes = findResultRecord(results, "message"); //$NON-NLS-1$
				if (messageRes != null && messageRes.getMIValue() instanceof MIConst) {
					message = ((MIConst) messageRes.getMIValue()).getString();
				}
				// FRCH: I believe that the actual string is "msg" ...
				// FRCH: (at least for the version of gdb I'm using)
				else {
					messageRes = findResultRecord(results, "msg"); //$NON-NLS-1$
					if (messageRes != null && messageRes.getMIValue() instanceof MIConst) {
						message = ((MIConst) messageRes.getMIValue()).getString();
					}
				}
			}
			StringBuilder clientMsg = new StringBuilder();
			clientMsg.append("Failed to execute MI command:\n"); //$NON-NLS-1$
			clientMsg.append(origCommand.toString());
			if (message != null) {
				message = message.replaceAll("\\\\n", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
				clientMsg.append("Error message from debugger back end:\n"); //$NON-NLS-1$
				if (parameters != null) {
					try {
						clientMsg.append(MessageFormat.format(message, (Object[]) parameters));
					} catch (IllegalArgumentException e2) {
						// Message format string invalid.  Fallback to just appending the strings.
						clientMsg.append(message);
						clientMsg.append(Arrays.toString(parameters));
					}
				} else {
					clientMsg.append(message);
				}
			}
			return clientMsg.toString();
		}

		private String getBackendMessage(MIOutput response) {

			// Attempt to extract a message from the result record:
			String message = null;
			String[] parameters = null;
			if (response != null && response.getMIResultRecord() != null) {
				MIResult[] results = response.getMIResultRecord().getMIResults();

				// Extract the parameters
				MIResult paramsRes = findResultRecord(results, "parameters"); //$NON-NLS-1$
				if (paramsRes != null && paramsRes.getMIValue() instanceof MIList) {
					MIValue[] paramValues = ((MIList) paramsRes.getMIValue()).getMIValues();
					parameters = new String[paramValues.length];
					for (int i = 0; i < paramValues.length; i++) {
						if (paramValues[i] instanceof MIConst) {
							parameters[i] = ((MIConst) paramValues[i]).getString();
						} else {
							parameters[i] = ""; //$NON-NLS-1$
						}
					}
				}
				MIResult messageRes = findResultRecord(results, "message"); //$NON-NLS-1$
				if (messageRes != null && messageRes.getMIValue() instanceof MIConst) {
					message = ((MIConst) messageRes.getMIValue()).getString();
				}
				// FRCH: I believe that the actual string is "msg" ...
				// FRCH: (at least for the version of gdb I'm using)
				else {
					messageRes = findResultRecord(results, "msg"); //$NON-NLS-1$
					if (messageRes != null && messageRes.getMIValue() instanceof MIConst) {
						message = ((MIConst) messageRes.getMIValue()).getString();
					}
				}
			}
			StringBuilder clientMsg = new StringBuilder();
			if (message != null) {
				if (parameters != null) {
					try {
						clientMsg.append(MessageFormat.format(message, (Object[]) parameters));
					} catch (IllegalArgumentException e2) {
						// Message format string invalid.  Fallback to just appending the strings.
						clientMsg.append(message);
						clientMsg.append(Arrays.toString(parameters));
					}
				} else {
					clientMsg.append(message);
				}
			}
			return clientMsg.toString();
		}

		void processMIOutput(String line) {

			MIParser.RecordType recordType = fMiParser.getRecordType(line);

			if (recordType == MIParser.RecordType.ResultRecord) {
				final MIResultRecord rr = fMiParser.parseMIResultRecord(line);

				/*
				 *  Find the command in the current output list. If we cannot then this is
				 *  some form of asynchronous notification. Or perhaps general IO.
				 */
				int id = rr.getToken();

				final CommandHandle commandHandle = fRxCommands.remove(id);

				if (commandHandle != null) {
					final MIOutput response = new MIOutput(rr,
							fAccumulatedOOBRecords.toArray(new MIOOBRecord[fAccumulatedOOBRecords.size()]));
					fAccumulatedOOBRecords.clear();
					fAccumulatedStreamRecords.clear();

					MIInfo result = commandHandle.getCommand().getResult(response);
					DataRequestMonitor<MIInfo> rm = commandHandle.getRequestMonitor();

					/*
					 *  Not all users want to get there results. They indicate so by not having
					 *  a completion object.
					 */
					if (rm != null) {
						rm.setData(result);

						/*
						 * We need to indicate if this request had an error or not.
						 */
						String errorResult = rr.getResultClass();

						if (errorResult.equals(MIResultRecord.ERROR)) {
							String status = getStatusString(commandHandle.getCommand(), response);
							String message = getBackendMessage(response);
							Exception exception = new Exception(message);
							rm.setStatus(
									new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, REQUEST_FAILED, status, exception));
						}

						/*
						 *  We need to complete the command on the DSF thread for data security.
						 */
						final ICommandResult finalResult = result;
						getExecutor().execute(new DsfRunnable() {
							@Override
							public void run() {
								/*
								 *  Complete the specific command.
								 */
								if (commandHandle.getRequestMonitor() != null) {
									commandHandle.getRequestMonitor().done();
								}

								/*
								 *  Now tell the generic listeners about it.
								 */
								processCommandDone(commandHandle, finalResult);
							}

							@Override
							public String toString() {
								return "MI command output received for: " + commandHandle.getCommand(); //$NON-NLS-1$
							}
						});
					} else {
						/*
						 *  While the specific requestor did not care about the completion  we
						 *  need to call any listeners. This could have been a CLI command for
						 *  example and  the CommandDone listeners there handle the IO as part
						 *  of the work.
						 */
						final ICommandResult finalResult = result;
						getExecutor().execute(new DsfRunnable() {
							@Override
							public void run() {
								processCommandDone(commandHandle, finalResult);
							}

							@Override
							public String toString() {
								return "MI command output received for: " + commandHandle.getCommand(); //$NON-NLS-1$
							}
						});
					}
				} else {
					/*
					 *  GDB apparently can sometimes send multiple responses to the same command.  In those cases,
					 *  the command handle is gone, so post the result as an event.  To avoid processing OOB records
					 *  as events multiple times, do not include the accumulated OOB record list in the response
					 *  MIOutput object.
					 */
					final MIOutput response = new MIOutput(rr, new MIOOBRecord[0]);

					getExecutor().execute(new DsfRunnable() {
						@Override
						public void run() {
							processEvent(response);
						}

						@Override
						public String toString() {
							return "MI asynchronous output received: " + response; //$NON-NLS-1$
						}
					});
				}
			} else if (recordType == MIParser.RecordType.OOBRecord) {
				// Process OOBs
				final MIOOBRecord oob = fMiParser.parseMIOOBRecord(line);

				fAccumulatedOOBRecords.add(oob);
				// limit growth, but only if these are not responses to CLI commands
				// Bug 302927 & 330608
				if (fRxCommands.isEmpty() && fAccumulatedOOBRecords.size() > 20) {
					fAccumulatedOOBRecords.remove(0);
				}

				// The handling of this OOB record may need the stream records
				// that preceded it. One such case is a stopped event caused by a
				// catchpoint in gdb < 7.0. The stopped event provides no
				// reason, but we can determine it was caused by a catchpoint by
				// looking at the target stream.

				final MIOutput response = new MIOutput(oob,
						fAccumulatedStreamRecords.toArray(new MIStreamRecord[fAccumulatedStreamRecords.size()]));

				// If this is a stream record, add it to the accumulated bucket
				// for possible use in handling a future OOB (see comment above)
				if (oob instanceof MIStreamRecord) {
					fAccumulatedStreamRecords.add((MIStreamRecord) oob);
					if (fAccumulatedStreamRecords.size() > 20) { // limit growth; see bug 302927
						fAccumulatedStreamRecords.remove(0);
					}
				}

				/*
				 *   OOBS are events. So we pass them to any event listeners who want to see them. Again this must
				 *   be done on the DSF thread for integrity.
				 */
				getExecutor().execute(new DsfRunnable() {
					@Override
					public void run() {
						processEvent(response);
					}

					@Override
					public String toString() {
						return "MI asynchronous output received: " + response; //$NON-NLS-1$
					}
				});
			}

			getExecutor().execute(new DsfRunnable() {
				@Override
				public void run() {
					processNextQueuedCommand();
				}
			});
		}
	}

	/**
	 * A thread that will read GDB's stderr stream.
	 * When a PTY is not being used for the inferior, everything
	 * the inferior writes to stderr will be output on GDB's stderr.
	 * If we don't read it, gdb eventually blocks, when the sream is
	 * full.
	 *
	 * Although we could write this error output to the inferior
	 * console, we actually write it to the GDB console.  This is
	 * because we cannot differentiate between inferior errors printouts
	 * and GDB error printouts.
	 *
	 * See bug 327617 for details.
	 */
	private class ErrorThread extends Thread {
		private final InputStream fErrorStream;
		private final MIParser fMiParser = new MIParser();

		public ErrorThread(InputStream errorStream) {
			super("MI Error Thread"); //$NON-NLS-1$
			fErrorStream = errorStream;
		}

		@Override
		public void run() {
			BufferedReader reader = new BufferedReader(new InputStreamReader(fErrorStream));
			try {
				String line;
				while ((line = reader.readLine()) != null) {
					// Create an error MI out-of-band record so that our gdb console prints it.
					final MIOOBRecord oob = fMiParser.parseMIOOBRecord("&" + line + "\n"); //$NON-NLS-1$//$NON-NLS-2$
					final MIOutput response = new MIOutput(oob, new MIStreamRecord[0]);
					getExecutor().execute(new DsfRunnable() {
						@Override
						public void run() {
							processEvent(response);
						}

						@Override
						public String toString() {
							return "MI error output received: " + response; //$NON-NLS-1$
						}
					});
				}
			} catch (IOException e) {
				// Socket is shut down.
			} catch (RejectedExecutionException e) {
				// Dispatch thread is down.
			}
			// Must close the stream here to avoid leaking
			// Bug 345164 and Bug 339379
			try {
				fErrorStream.close();
			} catch (IOException e) {
			}
		}
	}

	// we keep track of currentStackLevel and currentThreadId because in
	// some cases we must use -thread-select and -stack-select-frame
	public void resetCurrentThreadLevel() {
		fCurrentThreadId = null;
	}

	public void resetCurrentStackLevel() {
		fCurrentStackLevel = -1;
	}

	/**
	 * @since 4.1
	 */
	@ConfinedToDsfExecutor("this.getExecutor()")
	protected void commandFailed(ICommandToken token, int statusCode, String errorMessage) {
		if (!(token instanceof CommandHandle && token.getCommand() instanceof MICommand<?>))
			return;
		final CommandHandle commandHandle = (CommandHandle) token;
		Integer tokenId = commandHandle.getTokenId();

		// If the timeout value is too small a command can be timed out but still processed by RxThread.
		// To avoid processing it twice we need to remove it from the command list.
		CommandHandle h = fRxCommands.remove(tokenId);
		if (h == null)
			// Command has already been processed by RxThread.
			return;

		MIConst value = new MIConst();
		value.setCString(errorMessage);
		MIResult result = new MIResult();
		result.setVariable("msg"); //$NON-NLS-1$
		result.setMIValue(value);
		MIResultRecord resultRecord = new MIResultRecord();
		resultRecord.setToken(tokenId.intValue());
		resultRecord.setResultClass(MIResultRecord.ERROR);
		resultRecord.setMIResults(new MIResult[] { result });
		MIOutput miOutput = new MIOutput(resultRecord, new MIOOBRecord[0]);

		final MIInfo info = commandHandle.getCommand().getResult(miOutput);
		DataRequestMonitor<MIInfo> rm = commandHandle.getRequestMonitor();

		if (rm != null) {
			rm.setData(info);
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, statusCode, errorMessage, null));
			rm.done();

			/*
			 *  Now tell the generic listeners about it.
			 */
			processCommandDone(commandHandle, info);
		}
	}

	/**
	 * @since 6.1
	 */
	@Override
	public void flushAllCachesAndRefresh(RequestMonitor rm) {
		DsfServicesTracker servicesTracker = getServicesTracker();

		Set<ICachingService> services = new HashSet<>(servicesTracker.getServices(ICachingService.class));
		for (ICachingService service : services) {
			service.flushCache(null);
		}

		// Issue a refresh event for any services or UI that is not an ICachingService
		getSession().dispatchEvent(new RefreshAllDMEvent(getContext()), getProperties());
		rm.done();
	}
}
