/*******************************************************************************
 * Copyright (c) 2014, 2021 Ericsson AB 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:
 *     Alvaro Sanchez-Leon (Ericsson) - First Implementation and API (Bug 235747)
 *     Bruno Medeiros (Renesas) - Persistence of register groups per process (449104)
 *     Santiago Gil-Sanchez (Microchip) - Avoid save of register groups before init done (Bug 562407)
 *******************************************************************************/
package org.eclipse.cdt.dsf.gdb.service;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.TreeMap;

import org.eclipse.cdt.debug.core.model.IRegisterDescriptor;
import org.eclipse.cdt.debug.internal.core.RegisterGroupsPersistance;
import org.eclipse.cdt.debug.internal.core.model.IRegisterGroupDescriptor;
import org.eclipse.cdt.dsf.concurrent.ConfinedToDsfExecutor;
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.datamodel.CompositeDMContext;
import org.eclipse.cdt.dsf.datamodel.DMContexts;
import org.eclipse.cdt.dsf.datamodel.IDMContext;
import org.eclipse.cdt.dsf.debug.service.IRegisters;
import org.eclipse.cdt.dsf.debug.service.IRegisters2;
import org.eclipse.cdt.dsf.debug.service.IRunControl.IContainerDMContext;
import org.eclipse.cdt.dsf.debug.service.IStack;
import org.eclipse.cdt.dsf.debug.service.IStack.IFrameDMContext;
import org.eclipse.cdt.dsf.gdb.internal.GdbPlugin;
import org.eclipse.cdt.dsf.mi.service.IMIExecutionDMContext;
import org.eclipse.cdt.dsf.mi.service.IMIProcessDMContext;
import org.eclipse.cdt.dsf.mi.service.MIRegisters;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.osgi.util.NLS;

/**
 * <p>An extension of MIRegisters to support management of Register Groups as per the IRegisters2 interface.</p>
 * <p>The managed registered groups are user-defined subsets of the complete list of Registers reported by GDB for a specific Target</p>
 * <p>This class also triggers the read/write (persistence) of the user-defined Register Groups during the start/shutdown process of a session respectively.
 * It optionally supports persistence of user-defined Register Groups per container/process,
 * see {@link #getPersistenceIdForRegisterGroupContainer(IContainerDMContext)}.</p>
 * @since 4.6
 */
public class GDBRegisters extends MIRegisters implements IRegisters2 {

	/**
	 * true if groups have been read on initialization.
	 * Will prevent save of blank register groups if eclipse shuts down on startup
	 */
	private boolean groupsRead = false;

	/**
	 * Unique temporary id for a group. 0 is reserved for the root group
	 */
	private static int fGroupBookingCount = 1;

	/**
	 * References to all groups related to a given context. Different programs may use different sets of registers e.g.
	 * 32/64 bits
	 */
	private final ContextToGroupsMap<IContainerDMContext, MIRegisterGroupDMC[]> fContextToGroupsMap = new ContextToGroupsMap<>();

	/**
	 * Used to save base list of Registers associated to a group, these registers can not be used as is for
	 * "getRegisters" since the execution context may change e.g. The current selection points to a process or a running
	 * thread or a different frame, all information besides the execution context is valid.
	 */
	private final GroupRegistersMap<MIRegisterGroupDMC, MIRegisterDMC[]> fGroupToRegistersMap = new GroupRegistersMap<>();

	/**
	 * Saves the Group number to RegisterGroupDescriptor created from the serialized memento, The group number is used across contexts as the
	 * key:Integer uses a booking number incremented across container contexts
	 */
	private final Map<Integer, IRegisterGroupDescriptor> fGroupMementoDescriptorIndex = new HashMap<>();

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

	private class ContextToGroupsMap<K, V> extends HashMap<IContainerDMContext, MIRegisterGroupDMC[]> {
		private static final long serialVersionUID = 1L;
		private final Map<IContainerDMContext, Map<String, MIRegisterGroupDMC>> fNameToGroupMap = new HashMap<>();

		@Override
		public MIRegisterGroupDMC[] put(IContainerDMContext key, MIRegisterGroupDMC[] value) {
			if (key == null || value == null) {
				return null;
			}

			// Contents are updated for the given context, reset this context
			// cache
			// So it can be rebuilt on the next get
			fNameToGroupMap.remove(key);
			return super.put(key, value);
		}

		@Override
		public void clear() {
			fNameToGroupMap.clear();
			fGroupMementoDescriptorIndex.clear();
			fGroupToRegistersMap.clear();
			super.clear();
		}

		@Override
		public MIRegisterGroupDMC[] remove(Object key) {
			fNameToGroupMap.remove(key);
			return super.remove(key);
		}

		public Map<String, MIRegisterGroupDMC> getGroupNameMap(IContainerDMContext key) {
			// validate input
			if (key == null) {
				return null;
			}

			Map<String, MIRegisterGroupDMC> nameMap = fNameToGroupMap.get(key);
			if (nameMap == null) {
				// cache not resolved, rebuild
				nameMap = new HashMap<>();
				MIRegisterGroupDMC[] groupsArr = super.get(key);
				// If the container context exist, build the name map
				if (groupsArr != null) {
					for (MIRegisterGroupDMC group : groupsArr) {
						nameMap.put(group.getName(), group);
					}

					// cache it !
					fNameToGroupMap.put(key, nameMap);
				}
			}

			return nameMap;
		}

		/**
		 * Needed when group name(s) change but the associated group objects remain the same
		 */
		public void resetGroupNameMap(IContainerDMContext key) {
			fNameToGroupMap.remove(key);
		}

		/**
		 * The result will reflect the reverse order of creation, i.e. last created first
		 */
		public MIRegisterGroupDMC[] getReversed(IDMContext key) {
			MIRegisterGroupDMC[] groups = get(key);
			MIRegisterGroupDMC[] reversedGroups = new MIRegisterGroupDMC[groups.length];
			int size = groups.length;
			for (int i = 0; i < size; i++) {
				reversedGroups[size - 1 - i] = groups[i];
			}

			return reversedGroups;
		}
	}

	/**
	 * Used to associate two dependent maps, Group to ordered Register[] and Group to indexed registers (Map<String,
	 * Register>)
	 */
	private class GroupRegistersMap<K, V> extends HashMap<MIRegisterGroupDMC, MIRegisterDMC[]> {
		private static final long serialVersionUID = 1L;
		private final Map<MIRegisterGroupDMC, Map<String, MIRegisterDMC>> fNameToRegisterMap = new HashMap<>();

		@Override
		public MIRegisterDMC[] put(MIRegisterGroupDMC key, MIRegisterDMC[] value) {
			// Make sure a previous entry of the key does not keep an out of
			// date cache
			fNameToRegisterMap.remove(key);
			return super.put(key, value);
		}

		public Map<String, MIRegisterDMC> getIndexedRegisters(MIRegisterGroupDMC key) {
			Map<String, MIRegisterDMC> nameToRegisterMap = fNameToRegisterMap.get(key);
			if (nameToRegisterMap == null && get(key) != null) {
				// Needs indexing
				nameToRegisterMap = indexRegisters(key);
				if (nameToRegisterMap != null) {
					fNameToRegisterMap.put(key, nameToRegisterMap);
				}
			}

			return nameToRegisterMap;
		}

		@Override
		public void clear() {
			fNameToRegisterMap.clear();
			super.clear();
		}

		@Override
		public MIRegisterDMC[] remove(Object key) {
			fNameToRegisterMap.remove(key);
			return super.remove(key);
		}

		private Map<String, MIRegisterDMC> indexRegisters(MIRegisterGroupDMC registerGroup) {
			MIRegisterDMC[] registers = super.get(registerGroup);
			if (registers == null || registers.length < 1) {
				return null;
			}

			Map<String, MIRegisterDMC> registerNameMap = new HashMap<>();
			for (IRegisterDMContext register : registers) {
				assert (register instanceof MIRegisterDMC);
				MIRegisterDMC registerDmc = (MIRegisterDMC) register;
				registerNameMap.put(registerDmc.getName(), registerDmc);
			}

			return registerNameMap;
		}
	}

	private class RegisterGroupDescriptor implements IRegisterGroupDescriptor {
		private final boolean fEnabled;
		private final MIRegisterGroupDMC fgroup;

		public RegisterGroupDescriptor(MIRegisterGroupDMC group, boolean enabled) {
			fgroup = group;
			fEnabled = enabled;
		}

		@Override
		public String getName() {
			return fgroup.getName();
		}

		@Override
		public boolean isEnabled() {
			return fEnabled;
		}

		@Override
		public String getContainerId() {
			IContainerDMContext parent = fgroup.getContainerParent();
			return getPersistenceIdForRegisterGroupContainer(parent);
		}

		@Override
		public IRegisterDescriptor[] getChildren() throws CoreException {
			IRegisterDescriptor[] regDescriptors = null;
			// Get a snap shot of the current registers
			MIRegisterDMC[] registers = fGroupToRegistersMap.get(fgroup);
			if (registers != null && registers.length > 0) {
				regDescriptors = new IRegisterDescriptor[registers.length];
				for (int i = 0; i < registers.length; i++) {
					regDescriptors[i] = new RegisterDescriptor(registers[i]);
				}
			} else {
				// The registers were probably never fetched, obtain the
				// original definitions from deserialized groups
				IRegisterGroupDescriptor groupMementoDescriptor = fGroupMementoDescriptorIndex.get(fgroup.getGroupNo());
				if (groupMementoDescriptor != null) {
					regDescriptors = groupMementoDescriptor.getChildren();
				}
			}

			return regDescriptors;
		}

	}

	private class RegisterDescriptor implements IRegisterDescriptor {
		private final MIRegisterDMC fRegister;
		private final static String ORIGINAL_GROUP_NAME = "Main"; //$NON-NLS-1$

		public RegisterDescriptor(MIRegisterDMC register) {
			fRegister = register;
		}

		@Override
		public String getName() {
			return fRegister.getName();
		}

		@Override
		public String getGroupName() {
			// Hard coded to keep compatibility with CDI's format
			return ORIGINAL_GROUP_NAME;
		}
	}

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

	private void doInitialize(final RequestMonitor requestMonitor) {
		register(new String[] { IRegisters.class.getName(), IRegisters2.class.getName(), MIRegisters.class.getName(),
				GDBRegisters.class.getName() }, new Hashtable<String, String>());
		requestMonitor.done();
	}

	@Override
	public void getRegisterGroups(final IDMContext ctx, final DataRequestMonitor<IRegisterGroupDMContext[]> rm) {
		final IContainerDMContext contDmc = DMContexts.getAncestorOfType(ctx, IContainerDMContext.class);
		if (contDmc == null) {
			IStatus status = new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
					"Container context not provided, unable to get Register Groups", null); //$NON-NLS-1$
			rm.setStatus(status);
			rm.done();
			return;
		}

		if (fContextToGroupsMap.containsKey(contDmc)) {
			// The groups information is already available and can be returned
			rm.setData(fContextToGroupsMap.getReversed(contDmc));
			rm.done();
			return;
		}

		// The register groups information needs to be built from GDB and user-defined groups i.e. de-serialized
		// from the launch configuration.
		super.getRegisterGroups(ctx, new ImmediateDataRequestMonitor<IRegisterGroupDMContext[]>(rm) {
			@Override
			@ConfinedToDsfExecutor("fExecutor")
			protected void handleSuccess() {
				final IRegisterGroupDMContext[] regGroups = getData();
				// only one group from MI is expected at the moment
				assert (regGroups.length == 1);
				assert (regGroups[0] instanceof MIRegisterGroupDMC);

				final MIRegisterGroupDMC miGroup = (MIRegisterGroupDMC) regGroups[0];

				// read serialized groups
				MIRegisterGroupDMC[] mementoGroups = readGroupsFromMemento(contDmc);

				// Track the groups associated to this context
				// The root group (mi) is placed and expected at index 0 followed
				// by the user groups read from the memento
				MIRegisterGroupDMC[] regGroupsCtx = concatenateArr(new MIRegisterGroupDMC[] { miGroup }, mementoGroups);

				// Have the information ready for subsequent request or group operations.
				fContextToGroupsMap.put(contDmc, regGroupsCtx);

				// Reverse the order i.e. latest on top and get back to parent monitor
				rm.setData(fContextToGroupsMap.getReversed(contDmc));
				rm.done();
			}
		});
	}

	@Override
	public void getRegisterGroupData(final IRegisterGroupDMContext regGroupDmc,
			final DataRequestMonitor<IRegisterGroupDMData> rm) {

		assert (regGroupDmc instanceof MIRegisterGroupDMC);

		if (regGroupDmc instanceof MIRegisterGroupDMC) {
			MIRegisterGroupDMC groupDmc = (MIRegisterGroupDMC) regGroupDmc;
			rm.setData(createRegisterGroupData(groupDmc));
		} else {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR,
					"Unable to resolve Group Data, Invalid Register Group provided", null)); //$NON-NLS-1$
		}

		rm.done();
	}

	private IRegisterGroupDMData createRegisterGroupData(final MIRegisterGroupDMC groupDmc) {

		IRegisterGroupDMData groupData = new IRegisterGroupDMData() {
			@Override
			public String getName() {
				return groupDmc.getName();
			}

			@Override
			public String getDescription() {
				if (groupDmc.getName().equals(ROOT_GROUP_NAME)) {
					return ROOT_GROUP_DESCRIPTION;
				}

				return BLANK_STRING;
			}

		};

		// Make sure this group is available in the groups to registers map,
		// as this map provides the input to save /serialize the groups
		// The associated registers will be resolved upon request.
		if (fGroupToRegistersMap.get(groupDmc) == null) {
			fGroupToRegistersMap.put(groupDmc, new MIRegisterDMC[0]);
		}

		return groupData;
	}

	@Override
	public void getRegisters(final IDMContext aCtx, final DataRequestMonitor<IRegisterDMContext[]> rm) {
		findRegisterGroup(aCtx, ROOT_GROUP_NAME, new ImmediateDataRequestMonitor<IRegisterGroupDMContext>() {
			@Override
			protected void handleSuccess() {
				//Get the root group, needed as a possible default group and to resolve target registers
				IRegisterGroupDMContext rootGroup = getData();
				assert (rootGroup instanceof MIRegisterGroupDMC);
				final MIRegisterGroupDMC rootGroupContext = (MIRegisterGroupDMC) rootGroup;

				//if the received context does not contain a register group i.e.is null, the default group to resolve registers is the root group
				MIRegisterGroupDMC tGroupDmc = DMContexts.getAncestorOfType(aCtx, MIRegisterGroupDMC.class);

				IDMContext tCtx = aCtx;
				if (tGroupDmc == null) {
					tGroupDmc = rootGroupContext;
					//We need a register group as part of the context to resolve registers
					tCtx = new CompositeDMContext(new IDMContext[] { aCtx, tGroupDmc });
				}

				final IDMContext ctx = tCtx;

				final MIRegisterGroupDMC groupDmc = tGroupDmc;
				// check if base registers have been loaded already
				MIRegisterDMC[] baseRegisters = fGroupToRegistersMap.get(groupDmc);
				if (baseRegisters != null && baseRegisters.length > 0) {
					// use baseRegisters to build registers associated to the given context
					buildGroupRegisters(ctx, baseRegisters, rm);
					return;
				}

				IContainerDMContext rootGroupContainer = DMContexts.getAncestorOfType(rootGroupContext,
						IContainerDMContext.class);
				MIRegisterDMC[] registerBase = fGroupToRegistersMap.get(rootGroupContainer);
				if (registerBase == null || registerBase.length < 1) {
					// Prepare to fetch the register information from GDB (root group)
					// Include the frame/execution context whenever available
					IDMContext miExecDmc = DMContexts.getAncestorOfType(ctx, IFrameDMContext.class);
					if (miExecDmc == null) {
						miExecDmc = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class);
					}

					// if Execution context is not available return shallow registers i.e. no execution context
					final CompositeDMContext compCtx;
					if (miExecDmc != null) {
						compCtx = new CompositeDMContext(new IDMContext[] { rootGroupContext, miExecDmc });
					} else {
						compCtx = new CompositeDMContext(new IDMContext[] { rootGroupContext });
					}

					// Fetch the register base from GDB
					GDBRegisters.super.getRegisters(compCtx,
							new DataRequestMonitor<IRegisterDMContext[]>(getExecutor(), rm) {
								@Override
								@ConfinedToDsfExecutor("fExecutor")
								protected void handleSuccess() {
									IRegisterDMContext[] iregisters = getData();
									MIRegisterDMC[] registers = Arrays.copyOf(iregisters, iregisters.length,
											MIRegisterDMC[].class);

									// associate group to bare registers i.e. not associated to a specific execution context
									fGroupToRegistersMap.put(rootGroupContext, toBareRegisters(registers));
									if (groupDmc.getName().equals(ROOT_GROUP_NAME)) {
										buildGroupRegisters(ctx, registers, rm);
										return;
									}

									// Now proceed to resolve the requested user group registers
									getUserGroupRegisters(ctx, rm);
								}
							});
				} else {
					if (groupDmc.getName().equals(ROOT_GROUP_NAME)) {
						buildGroupRegisters(ctx, registerBase, rm);
					} else {
						// resolve user group registers
						getUserGroupRegisters(ctx, rm);
					}
				}

			}
		});
	}

	@Override
	public void canAddRegisterGroup(IDMContext selectionContext, DataRequestMonitor<Boolean> rm) {
		// Not relevant checks at this point
		rm.setData(true);
		rm.done();
	}

	@Override
	public void addRegisterGroup(final IDMContext containerContext, final String groupName,
			final IRegisterDMContext[] registers, RequestMonitor rm) {
		if (registers == null || registers.length < 1) {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
					Messages.RegisterGroup_invalid_number_of_registers, null));
			rm.done();
			return;
		}

		if (groupName.trim().toLowerCase().equals(ROOT_GROUP_NAME.toLowerCase())) {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
					NLS.bind(Messages.RegisterGroup_name_reserved, ROOT_GROUP_NAME), null));
			rm.done();
			return;
		}

		if (!(registers[0] instanceof MIRegisterDMC)) {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
					"Unexpected IRegisterDMContext input instance type", null)); //$NON-NLS-1$
			rm.done();
			return;
		}

		IContainerDMContext contDmc = DMContexts.getAncestorOfType(registers[0], IContainerDMContext.class);
		if (contDmc == null) {
			contDmc = DMContexts.getAncestorOfType(containerContext, IContainerDMContext.class);
			if (contDmc == null) {
				rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
						"Unable to add Register group, Invalid Container", null)); //$NON-NLS-1$
				rm.done();
				return;
			}
		}

		// Make sure the name is not currently in use
		if (fContextToGroupsMap.getGroupNameMap(contDmc).get(groupName) != null) {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
					NLS.bind(Messages.RegisterGroup_name_used, groupName), null));
			rm.done();
			return;
		}

		//create the new group
		MIRegisterGroupDMC group = new MIRegisterGroupDMC(this, contDmc, fGroupBookingCount, groupName);
		fGroupBookingCount++;

		// Update the context to groups map including the new group
		fContextToGroupsMap.put(contDmc,
				concatenateArr(fContextToGroupsMap.get(contDmc), new MIRegisterGroupDMC[] { group }));

		//type adjustment
		MIRegisterDMC[] miRegisters = Arrays.copyOf(registers, registers.length, MIRegisterDMC[].class);

		// associate group to bare registers i.e. not associated to a specific execution context
		MIRegisterDMC[] bareRegisters = toBareRegisters(miRegisters);
		fGroupToRegistersMap.put(group, bareRegisters);

		// Create event notification, to trigger the UI refresh
		getSession().dispatchEvent(new GroupsChangedDMEvent(contDmc), null);
		rm.done();
	}

	@Override
	public void canEditRegisterGroup(IRegisterGroupDMContext group, DataRequestMonitor<Boolean> rm) {
		rm.setData(canEditRegisterGroup(group));
		rm.done();
	}

	@Override
	public void editRegisterGroup(IRegisterGroupDMContext group, String newGroupName, IRegisterDMContext[] iRegisters,
			RequestMonitor rm) {

		if (iRegisters != null && iRegisters.length == 0) {
			rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
					Messages.RegisterGroup_invalid_number_of_registers, null));
			return;
		}

		if (!(group instanceof MIRegisterGroupDMC)) {
			rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR, "Unknown DMC type", null)); //$NON-NLS-1$
			return;
		}

		IContainerDMContext contDmc = DMContexts.getAncestorOfType(group, IContainerDMContext.class);
		if (contDmc == null) {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
					"Unable to edit Register group, Invalid Container", null)); //$NON-NLS-1$
			rm.done();
		}

		MIRegisterGroupDMC miGroup = ((MIRegisterGroupDMC) group);

		if (!canEditRegisterGroup(group)) {
			// Should not happen as canEdit is expected to be called before edit
			rm.done(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_STATE,
					"Cannot currently edit register groups", null)); //$NON-NLS-1$
			return;
		}

		if (newGroupName != null && !newGroupName.isEmpty()) {
			// Make sure the new group name is not the reserved root group name
			if (newGroupName.trim().toLowerCase().equals(ROOT_GROUP_NAME.toLowerCase())) {
				rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
						NLS.bind(Messages.RegisterGroup_name_reserved, ROOT_GROUP_NAME), null));
				rm.done();
				return;
			}

			// Make sure the name is not currently in use
			if (!miGroup.getName().equals(newGroupName)) {
				// we are updating the name, lets make sure this new name is not in use
				if (fContextToGroupsMap.getGroupNameMap(contDmc).get(newGroupName) != null) {
					rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, NOT_SUPPORTED,
							NLS.bind(Messages.RegisterGroup_name_used, newGroupName), null));
					rm.done();
					return;
				}
			}

			miGroup.setName(newGroupName);

			//make sure we update the group name cache
			fContextToGroupsMap.resetGroupNameMap(contDmc);

			generateRegisterGroupChangedEvent(miGroup);
		} else {
			// Request to keep name the same
		}

		if (iRegisters != null) {
			assert (iRegisters.length > 0);

			// transform to MIRegistersDMC[]
			MIRegisterDMC[] registers = arrangeRegisters(iRegisters);

			// preserve registers in a general format not associated to a specific frame
			registers = toBareRegisters(registers);
			fGroupToRegistersMap.put(miGroup, registers);
			// Notify of Registers changed
			generateRegistersChangedEvent(miGroup);
		} else {
			// Request to keep register list the same
		}

		rm.done();
	}

	@Override
	public void removeRegisterGroups(IRegisterGroupDMContext[] groups, RequestMonitor rm) {
		removeRegisterGroups(groups, false, rm);
	}

	@Override
	public void restoreDefaultGroups(final IDMContext selectionContext, final RequestMonitor rm) {
		for (IDMContext context : fContextToGroupsMap.keySet()) {
			removeRegisterGroups(context);
		}

		// clean the serialized registers group information
		save();

		// Clear all global references to the contexts and groups
		fContextToGroupsMap.clear();
		rm.done();
	}

	/**
	 * Reset this class i.e. does not impact saved groups within launch configuration
	 *
	 * @param rm
	 */
	public void reset(final RequestMonitor rm) {
		for (IDMContext context : fContextToGroupsMap.keySet()) {
			removeRegisterGroups(context);
		}

		// Clear all global references to the contexts and groups
		fContextToGroupsMap.clear();
		rm.done();
	}

	@Override
	public void findRegisterGroup(final IDMContext ctx, final String name,
			final DataRequestMonitor<IRegisterGroupDMContext> rm) {
		final IContainerDMContext contDmc = DMContexts.getAncestorOfType(ctx, IContainerDMContext.class);
		if (contDmc == null) {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE, "Container context not found", //$NON-NLS-1$
					null));
			rm.done();
			return;
		}

		if (fContextToGroupsMap.get(ctx) == null) {
			// Need to build the list of register groups including the one from target
			getRegisterGroups(contDmc, new DataRequestMonitor<IRegisterGroupDMContext[]>(getExecutor(), rm) {
				@Override
				protected void handleSuccess() {
					// Using the list of groups indirectly to find the one with the given name from it
					findRegisterGroup(contDmc, name, rm);
				}
			});
		} else {
			// The context to groups map has been initialized and can be used
			findRegisterGroup(contDmc, name, rm);
		}
	}

	/**
	 * Call it only after getRegisterGroups has been called at least once, so the context to groups map is not empty
	 */
	private void findRegisterGroup(IContainerDMContext contDmc, String name,
			DataRequestMonitor<IRegisterGroupDMContext> rm) {
		Map<String, MIRegisterGroupDMC> nameToGroup = fContextToGroupsMap.getGroupNameMap(contDmc);
		if (nameToGroup != null) {
			rm.setData(nameToGroup.get(name));
		} else {
			rm.setData(null);
		}

		rm.done();
	}

	@Override
	public void shutdown(RequestMonitor rm) {
		//If register groups have not been read before shutdown is invoked
		//then do not attempt a save as existing register groups will be overwritten with an empty list.
		if (groupsRead) {
			save();
		}
		super.shutdown(rm);
	}

	/**
	 * Save the register group settings into the underlying launch configuration.
	 */
	public void save() {
		IRegisterGroupDescriptor[] groups = buildDescriptors();
		ILaunchConfiguration launchConfig = getLaunchConfig();
		if (launchConfig != null) {
			RegisterGroupsPersistance serializer = new RegisterGroupsPersistance(launchConfig);
			try {
				serializer.saveGroups(groups);
			} catch (CoreException e) {
				GdbPlugin.log(e);
			}
		}

	}

	/**
	 * Cast to MI and sort them ascending order by register index
	 */
	private MIRegisterDMC[] arrangeRegisters(IRegisterDMContext[] iRegisters) {
		TreeMap<Integer, MIRegisterDMC> sortedRegisters = new TreeMap<>();
		for (int i = 0; i < iRegisters.length; i++) {
			assert (iRegisters[i] instanceof MIRegisterDMC);
			MIRegisterDMC register = (MIRegisterDMC) iRegisters[i];
			sortedRegisters.put(register.getRegNo(), register);
		}

		return sortedRegisters.values().toArray(new MIRegisterDMC[sortedRegisters.size()]);
	}

	/**
	 * @param groups
	 *            - The groups to be removed
	 * @param removeRoot
	 *            - indicates if the root group needs to be removed e.g. during restore to defaults
	 * @param rm
	 */
	private void removeRegisterGroups(IRegisterGroupDMContext[] groups, boolean removeRoot, RequestMonitor rm) {
		if (groups != null) {
			// Save a list of updated containers to only send an update event for each of them
			final Set<IContainerDMContext> updatedContainers = new HashSet<>();
			for (IRegisterGroupDMContext group : groups) {

				if (!removeRoot) {
					// Prevent removal of the Root Group
					if (!(group instanceof MIRegisterGroupDMC)) {
						// All groups are expected to be instances of MIREgisterGroupDMC
						assert (false);
						continue;
					}

					if (((MIRegisterGroupDMC) group).getName().equals(ROOT_GROUP_NAME)) {
						// Skip removal of a root group, except when restoring to default groups
						continue;
					}
				}

				final IContainerDMContext containerDmc = DMContexts.getAncestorOfType(group, IContainerDMContext.class);

				// All given groups are expected to be part of the same Container, however it's safer to create a new list
				// per context to cover the unsual case
				// This could be revisited in case there is performance concerns which does not seem an issue at this
				// point.
				MIRegisterGroupDMC[] groupsCtx = fContextToGroupsMap.get(containerDmc);
				assert (groupsCtx != null);

				if (groupsCtx != null) {
					List<MIRegisterGroupDMC> groupsList = new ArrayList<>(Arrays.asList(groupsCtx));

					// Removing a single group
					groupsList.remove(group);

					// Back to context map without the given group
					fContextToGroupsMap.put(containerDmc,
							groupsList.toArray(new MIRegisterGroupDMC[groupsList.size()]));
					// Now remove the group from the groups to registers map
					if (fGroupToRegistersMap.remove(group) != null) {
						updatedContainers.add(containerDmc);
					}
				} else {
					rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INVALID_HANDLE,
							"Unable to remove Register group, Invalid Container", null)); //$NON-NLS-1$
					rm.done();
					return;
				}
			}

			// Sending only one update per container
			for (IContainerDMContext container : updatedContainers) {
				getSession().dispatchEvent(new GroupsChangedDMEvent(container), null);
			}
		}

		rm.done();
	}

	private void removeRegisterGroups(IDMContext containerDmc) {
		MIRegisterGroupDMC[] groups = fContextToGroupsMap.get(containerDmc);
		if (groups != null) {
			removeRegisterGroups(groups, true, new RequestMonitor(getExecutor(), null) {
			});
		}
	}

	private boolean canEditRegisterGroup(IRegisterGroupDMContext group) {
		if (group instanceof MIRegisterGroupDMC) {
			MIRegisterGroupDMC miGroup = ((MIRegisterGroupDMC) group);
			// Prevent changes to the root group
			if (miGroup.getName().trim().toLowerCase().equals(ROOT_GROUP_NAME.toLowerCase())) {
				return false;
			}

			// Expected to be on the existing groups map
			if (fGroupToRegistersMap.containsKey(group)) {
				return true;
			}
		}

		return false;
	}

	private ILaunchConfiguration getLaunchConfig() {
		ILaunch launch = (ILaunch) getSession().getModelAdapter(ILaunch.class);
		if (launch == null) {
			// The launch is no longer active
			return null;
		}

		ILaunchConfiguration config = launch.getLaunchConfiguration();
		return config;
	}

	IRegisterGroupDescriptor[] buildDescriptors() {
		// use a tree map to sort the entries by group number
		TreeMap<Integer, MIRegisterGroupDMC> sortedGroups = new TreeMap<>();

		for (MIRegisterGroupDMC group : fGroupToRegistersMap.keySet()) {
			sortedGroups.put(Integer.valueOf(group.getGroupNo()), group);
		}

		// Not serializing the root group which is dynamically created from GDB
		sortedGroups.remove(Integer.valueOf(0));

		Set<Entry<Integer, MIRegisterGroupDMC>> groupSet = sortedGroups.entrySet();
		IRegisterGroupDescriptor[] descriptors = new IRegisterGroupDescriptor[groupSet.size()];

		// load group descriptors sorted in ascending order to their group
		// number into the result array
		int i = 0;
		for (Entry<Integer, MIRegisterGroupDMC> groupEntry : groupSet) {
			descriptors[i] = new RegisterGroupDescriptor(groupEntry.getValue(), true);
			i++;
		}

		return descriptors;
	}

	private <T> T[] concatenateArr(T[] origArr, T[] deltaArr) {
		if (origArr == null) {
			return deltaArr;
		}

		if (deltaArr == null) {
			return origArr;
		}

		T[] newArr = Arrays.copyOf(origArr, origArr.length + deltaArr.length);
		System.arraycopy(deltaArr, 0, newArr, origArr.length, deltaArr.length);
		return newArr;
	}

	MIRegisterGroupDMC[] readGroupsFromMemento(final IContainerDMContext contDmc) {
		//Set to true so shutdown will have register groups to save.
		groupsRead = true;

		String containerId = getPersistenceIdForRegisterGroupContainer(contDmc);

		RegisterGroupsPersistance deserializer = new RegisterGroupsPersistance(getLaunchConfig());
		IRegisterGroupDescriptor[] groupDescriptions;
		try {
			groupDescriptions = deserializer.parseGroups(containerId);
		} catch (CoreException e) {
			return new MIRegisterGroupDMC[0];
		}

		List<MIRegisterGroupDMC> groups = new ArrayList<>();
		for (IRegisterGroupDescriptor group : groupDescriptions) {
			fGroupMementoDescriptorIndex.put(fGroupBookingCount, group);
			groups.add(new MIRegisterGroupDMC(this, contDmc, fGroupBookingCount, group.getName()));
			fGroupBookingCount++;
		}
		return groups.toArray(new MIRegisterGroupDMC[groups.size()]);
	}

	/**
	 * @return the persistence id for the register group in the given contDmc container context,
	 * or null to associate the Register Groups in the given container to the launch itself (this is the default behavior).
	 *
	 * Subclasses may override. Alternatively simply use override {@link #useProcessIdAsRegisterGroupPersistanceId()} to return true to have
	 * the process id be used as the persistence id.
	 *
	 * Note that for this to work correctly the id returned for a given container must be same across launch sessions,
	 * otherwise persistence info will be lost. (Hence why null is the default behavior)
	 *
	 * @since 5.3
	 */
	protected String getPersistenceIdForRegisterGroupContainer(final IContainerDMContext contDmc) {
		if (useProcessIdAsRegisterGroupPersistanceId()) {
			IMIProcessDMContext processDmc = DMContexts.getAncestorOfType(contDmc, IMIProcessDMContext.class);
			return processDmc == null ? null : processDmc.getProcId();
		} else {
			return null;
		}
	}

	/**
	 * @return whether the process id should be used as a container id for the persistence
	 * of the register groups. Subclasses may override.
	 *
	 * @see #getPersistenceIdForRegisterGroupContainer(IContainerDMContext)
	 *
	 * @since 5.3
	 */
	protected boolean useProcessIdAsRegisterGroupPersistanceId() {
		return false;
	}

	private void getUserGroupRegisters(IDMContext ctx, final DataRequestMonitor<IRegisterDMContext[]> rm) {
		final MIRegisterGroupDMC groupDmc = DMContexts.getAncestorOfType(ctx, MIRegisterGroupDMC.class);

		// Need to build the corresponding register[] from the memento descriptors
		IRegisterGroupDescriptor grpDescriptor = fGroupMementoDescriptorIndex.get(groupDmc.getGroupNo());

		if (grpDescriptor == null) {
			rm.setStatus(new Status(IStatus.ERROR, GdbPlugin.PLUGIN_ID, INTERNAL_ERROR,
					"The Register Group Descriptor does not exist for group: " + groupDmc.getName(), null)); //$NON-NLS-1$
			rm.done();
			return;
		}

		MIRegisterDMC[] registers;
		try {
			// Resolve bare registers from the memento descriptors
			registers = resolveRegisters(grpDescriptor, ctx);
		} catch (CoreException e) {
			rm.setStatus(e.getStatus());
			rm.done();
			return;
		}

		// update internal data
		fGroupToRegistersMap.put(groupDmc, registers);

		// now resolve to context specific registers
		buildGroupRegisters(ctx, registers, rm);
	}

	/**
	 * Resolve register dmcs from de-serialized memento descriptors
	 */
	private MIRegisterDMC[] resolveRegisters(IRegisterGroupDescriptor grpDescriptor, IDMContext ctx)
			throws CoreException {
		final List<MIRegisterDMC> registerContexts = new ArrayList<>();
		final IContainerDMContext containerDmc = DMContexts.getAncestorOfType(ctx, IContainerDMContext.class);
		final MIRegisterGroupDMC groupDmc = DMContexts.getAncestorOfType(ctx, MIRegisterGroupDMC.class);

		IRegisterDescriptor[] registerDescriptions = grpDescriptor.getChildren();
		MIRegisterGroupDMC[] groupContexts = fContextToGroupsMap.get(containerDmc);
		if (groupContexts != null && groupContexts.length > 0) {
			// Get the General Group (base) at index 0,
			// Registers map indexed by name
			Map<String, MIRegisterDMC> indexedRegisterBase = fGroupToRegistersMap.getIndexedRegisters(groupContexts[0]);

			// For each descriptors find its corresponding MIRegisterDMC
			for (IRegisterDescriptor registerDescription : registerDescriptions) {
				MIRegisterDMC registerDmc = indexedRegisterBase.get(registerDescription.getName());
				if (registerDmc == null) {
					// The Register is not present from the base received from GDB
					// Create a register DMC with no execution dmc and invalid
					// register number e.g. not mapped to a gdb register.
					registerDmc = new MIRegisterDMC(this, groupDmc, -1, registerDescription.getName());
				}

				registerContexts.add(registerDmc);
			}
		}

		return registerContexts.toArray(new MIRegisterDMC[registerContexts.size()]);
	}

	@Override
	protected void generateRegisterChangedEvent(final IRegisterDMContext dmc) {
		// notify the register value change
		getSession().dispatchEvent(new RegisterChangedDMEvent(dmc), getProperties());

		// Propagate notification to all groups.
		// A change of a single register needs to be propagated to all groups within the same Container/Process
		// I.e. Some registers are dependent on the value of others and these dependent registers could be
		// associated to different groups.
		IContainerDMContext containerDmc = DMContexts.getAncestorOfType(dmc, IContainerDMContext.class);
		generateRegistersChangedEvent(containerDmc);
	}

	private void generateRegistersChangedEvent(IContainerDMContext containerDmc) {
		//resolve the groups for the current container (process) context
		final MIRegisterGroupDMC[] groups = fContextToGroupsMap.get(containerDmc);

		//trigger notification to all groups in the container
		for (int i = 0; i < groups.length; i++) {
			//We need final locals variables from the loop. Use a method call for this
			generateRegistersChangedEvent(groups[i]);
		}
	}

	private void generateRegistersChangedEvent(final MIRegisterGroupDMC groupDmc) {
		IRegistersChangedDMEvent event = new IRegistersChangedDMEvent() {
			@Override
			public IRegisterGroupDMContext getDMContext() {
				return groupDmc;
			}
		};

		getSession().dispatchEvent(event, getProperties());
	}

	private void generateRegisterGroupChangedEvent(final MIRegisterGroupDMC groupDmc) {
		IGroupChangedDMEvent event = new IGroupChangedDMEvent() {
			@Override
			public IRegisterGroupDMContext getDMContext() {
				return groupDmc;
			}
		};

		getSession().dispatchEvent(event, getProperties());
	}

	/**
	 * Create Registers from specific execution context to a generic register context, e.g. not associated to a specific
	 * execution context.
	 */
	private MIRegisterDMC[] toBareRegisters(MIRegisterDMC[] registers) {

		MIRegisterDMC[] bareRegisters = new MIRegisterDMC[registers.length];
		for (int i = 0; i < registers.length; i++) {
			// only one parent i.e. group context
			MIRegisterGroupDMC groupDmc = DMContexts.getAncestorOfType(registers[i], MIRegisterGroupDMC.class);
			assert (groupDmc != null);
			bareRegisters[i] = new MIRegisterDMC(this, groupDmc, registers[i].getRegNo(), registers[i].getName());
		}

		return bareRegisters;
	}

	private void buildGroupRegisters(final IDMContext ctx, final MIRegisterDMC[] baseRegisters,
			final DataRequestMonitor<IRegisterDMContext[]> rm) {
		final MIRegisterGroupDMC groupDmc = DMContexts.getAncestorOfType(ctx, MIRegisterGroupDMC.class);

		assert (groupDmc != null);

		final IFrameDMContext frameDmc = DMContexts.getAncestorOfType(ctx, IFrameDMContext.class);
		if (frameDmc == null) {
			// The selection does not provide a specific frame, then resolve the top frame on the current thread
			// if the execution frame is not available proceed with no frame context i.e. will not be able to resolve
			// values.
			IMIExecutionDMContext execDmc = DMContexts.getAncestorOfType(ctx, IMIExecutionDMContext.class);
			if (execDmc != null) {
				IStack stackService = getServicesTracker().getService(IStack.class);
				if (stackService != null) {
					stackService.getTopFrame(execDmc, new ImmediateDataRequestMonitor<IStack.IFrameDMContext>(rm) {
						@Override
						protected void handleSuccess() {
							cloneRegistersToContext(groupDmc, getData(), baseRegisters, rm);
						}

						@Override
						protected void handleFailure() {
							// Unable to resolve top frame on current thread.
							// The thread could e.g. be in running state,
							// we return register instances with no associated execution context
							// i.e. unable to resolve its associated value.
							cloneRegistersToContext(groupDmc, null, baseRegisters, rm);
						}
					});

					return;
				}
			}
		}

		cloneRegistersToContext(groupDmc, frameDmc, baseRegisters, rm);
	}

	/**
	 * Create a new array of register instances with the given context
	 */
	private void cloneRegistersToContext(MIRegisterGroupDMC groupDmc, IFrameDMContext frameDmc,
			MIRegisterDMC[] baseRegisters, DataRequestMonitor<IRegisterDMContext[]> rm) {
		MIRegisterDMC[] registers = new MIRegisterDMC[baseRegisters.length];
		if (frameDmc != null) {
			// build to valid stack frame context
			for (int i = 0; i < registers.length; i++) {
				registers[i] = new MIRegisterDMC(this, groupDmc, frameDmc, baseRegisters[i].getRegNo(),
						baseRegisters[i].getName());
			}
		} else {
			// build with no execution context, normal case if a selection is pointing to
			// e.g. a running thread, a process.. i.e. not able to associate register values.
			for (int i = 0; i < registers.length; i++) {
				registers[i] = new MIRegisterDMC(this, groupDmc, baseRegisters[i].getRegNo(),
						baseRegisters[i].getName());
			}
		}

		// return the registers
		rm.setData(registers);
		rm.done();
	}

	@Override
	public void canRemoveRegisterGroups(IRegisterGroupDMContext[] groups, DataRequestMonitor<Boolean> rm) {
		if (groups == null || groups.length < 1) {
			rm.setData(false);
			rm.done();
			return;
		}

		for (IRegisterGroupDMContext group : groups) {
			assert (group instanceof MIRegisterGroupDMC);
			MIRegisterGroupDMC miGroup = (MIRegisterGroupDMC) group;
			if (miGroup.getName().equals(ROOT_GROUP_NAME)) {
				// Not allowed to remove the root group
				rm.setData(false);
				rm.done();
				return;
			}
		}

		rm.setData(true);
		rm.done();

	}

	@Override
	public void canRestoreDefaultGroups(IDMContext selectionContext, DataRequestMonitor<Boolean> rm) {
		// Not relevant checks at this point
		rm.setData(true);
		rm.done();
	}
}
