/*******************************************************************************
 * Copyright (c) 2010, 2017 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *      Maxime Porhel <maxime.porhel@obeo.fr> Obeo - Bug 435949
 *      Lars Vogel <Lars.Vogel@vogella.com> - Bug 472654
 *      Simon Scholz <simon.scholz@vogella.com> - Bug 484398
 ******************************************************************************/

package org.eclipse.e4.ui.internal.workbench;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import org.eclipse.core.expressions.EvaluationResult;
import org.eclipse.core.expressions.Expression;
import org.eclipse.core.expressions.ExpressionInfo;
import org.eclipse.core.internal.expressions.ReferenceExpression;
import org.eclipse.e4.core.commands.ExpressionContext;
import org.eclipse.e4.core.contexts.ContextInjectionFactory;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.core.di.InjectionException;
import org.eclipse.e4.core.di.InjectorFactory;
import org.eclipse.e4.core.di.annotations.Evaluate;
import org.eclipse.e4.core.di.suppliers.PrimaryObjectSupplier;
import org.eclipse.e4.core.internal.contexts.ContextObjectSupplier;
import org.eclipse.e4.core.internal.di.InjectorImpl;
import org.eclipse.e4.core.services.contributions.IContributionFactory;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.commands.MCommand;
import org.eclipse.e4.ui.model.application.ui.MCoreExpression;
import org.eclipse.e4.ui.model.application.ui.MElementContainer;
import org.eclipse.e4.ui.model.application.ui.MExpression;
import org.eclipse.e4.ui.model.application.ui.MImperativeExpression;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.basic.MTrimBar;
import org.eclipse.e4.ui.model.application.ui.basic.MTrimElement;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
import org.eclipse.e4.ui.model.application.ui.menu.MMenuContribution;
import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
import org.eclipse.e4.ui.model.application.ui.menu.MMenuSeparator;
import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
import org.eclipse.e4.ui.model.application.ui.menu.MToolBar;
import org.eclipse.e4.ui.model.application.ui.menu.MToolBarContribution;
import org.eclipse.e4.ui.model.application.ui.menu.MToolBarElement;
import org.eclipse.e4.ui.model.application.ui.menu.MToolBarSeparator;
import org.eclipse.e4.ui.model.application.ui.menu.MTrimContribution;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;

public final class ContributionsAnalyzer {

	private static final Object missingEvaluate = new Object();

	public static void trace(String msg, Throwable error) {
		if (DEBUG) {
			Activator.trace(Policy.DEBUG_MENUS_FLAG, msg, error);
		}
	}

	private static boolean DEBUG = Policy.DEBUG_MENUS;

	private static void trace(String msg, Object menu, Object menuModel) {
		trace(msg + ": " + menu + ": " + menuModel, null); //$NON-NLS-1$ //$NON-NLS-2$
	}

	public static void gatherTrimContributions(MTrimBar trimModel,
			List<MTrimContribution> trimContributions, String elementId,
			ArrayList<MTrimContribution> toContribute, ExpressionContext eContext) {
		if (elementId == null || elementId.length() == 0) {
			return;
		}
		for (MTrimContribution contribution : trimContributions) {
			String parentId = contribution.getParentId();
			boolean filtered = isFiltered(trimModel, contribution);
			if (filtered || !elementId.equals(parentId) || !contribution.isToBeRendered()) {
				continue;
			}
			toContribute.add(contribution);
		}
	}

	static boolean isFiltered(MTrimBar trimModel, MTrimContribution contribution) {
		return false;
	}

	public static void XXXgatherToolBarContributions(final MToolBar toolbarModel,
			final List<MToolBarContribution> toolbarContributionList, final String id,
			final ArrayList<MToolBarContribution> toContribute) {
		if (id == null || id.length() == 0) {
			return;
		}
		for (MToolBarContribution toolBarContribution : toolbarContributionList) {
			String parentID = toolBarContribution.getParentId();
			boolean filtered = isFiltered(toolbarModel, toolBarContribution);
			if (filtered || !id.equals(parentID) || !toolBarContribution.isToBeRendered()) {
				continue;
			}
			toContribute.add(toolBarContribution);
		}
	}

	public static void gatherToolBarContributions(final MToolBar toolbarModel,
			final List<MToolBarContribution> toolbarContributionList, final String id,
			final ArrayList<MToolBarContribution> toContribute, final ExpressionContext eContext) {
		if (id == null || id.length() == 0) {
			return;
		}
		for (MToolBarContribution toolBarContribution : toolbarContributionList) {
			String parentID = toolBarContribution.getParentId();
			boolean filtered = isFiltered(toolbarModel, toolBarContribution);
			if (filtered || !id.equals(parentID) || !toolBarContribution.isToBeRendered()) {
				continue;
			}
			toContribute.add(toolBarContribution);
		}
	}

	static boolean isFiltered(MToolBar toolbarModel, MToolBarContribution toolBarContribution) {
		return false;
	}

	public static void XXXgatherMenuContributions(final MMenu menuModel,
			final List<MMenuContribution> menuContributionList, final String id,
			final ArrayList<MMenuContribution> toContribute, final ExpressionContext eContext,
			boolean includePopups) {
		if (id == null || id.length() == 0) {
			return;
		}
		ArrayList<String> popupIds = new ArrayList<>();
		if (includePopups) {
			popupIds.add(id);
			for (String tag : menuModel.getTags()) {
				if (tag.startsWith("popup:")) { //$NON-NLS-1$
					String tmp = tag.substring("popup:".length()); //$NON-NLS-1$
					if (!popupIds.contains(tmp)) {
						popupIds.add(tmp);
					}
				}
			}
		}
		ArrayList<MMenuContribution> includedPopups = new ArrayList<>();
		for (MMenuContribution menuContribution : menuContributionList) {
			String parentID = menuContribution.getParentId();
			if (parentID == null) {
				// it doesn't make sense for this to be null, temporary workaround for bug 320790
				continue;
			}
			boolean popupTarget = includePopups && popupIds.contains(parentID);
			boolean popupAny = includePopups && menuModel instanceof MPopupMenu
					&& POPUP_PARENT_ID.equals(parentID);
			boolean filtered = isFiltered(menuModel, menuContribution, includePopups);
			if (!filtered && menuContribution.isToBeRendered() && popupAny) {
				// process POPUP_ANY first
				toContribute.add(menuContribution);
			} else {
				if (filtered || (!popupTarget && !parentID.equals(id))
				|| !menuContribution.isToBeRendered()) {
					continue;
				}
				includedPopups.add(menuContribution);
			}
		}
		toContribute.addAll(includedPopups);
	}

	public static void gatherMenuContributions(final MMenu menuModel,
			final List<MMenuContribution> menuContributionList, final String id,
			final ArrayList<MMenuContribution> toContribute, final ExpressionContext eContext,
			boolean includePopups) {
		if (id == null || id.length() == 0) {
			return;
		}
		boolean menuBar = (((MUIElement) ((EObject) menuModel).eContainer()) instanceof MWindow);
		for (MMenuContribution menuContribution : menuContributionList) {
			String parentID = menuContribution.getParentId();
			if (parentID == null) {
				// it doesn't make sense for this to be null, temporary workaround for bug 320790
				continue;
			}
			boolean popup = parentID.equals(POPUP_PARENT_ID) && (menuModel instanceof MPopupMenu)
					&& includePopups;
			boolean filtered = isFiltered(menuModel, menuContribution, includePopups);
			if (filtered || (!popup && !parentID.equals(id)) || !menuContribution.isToBeRendered()) {
				continue;
			}
			if (menuBar || isVisible(menuContribution, eContext)) {
				toContribute.add(menuContribution);
			}
		}
	}

	static boolean isFiltered(MMenu menuModel, MMenuContribution menuContribution,
			boolean includePopups) {
		if (includePopups || menuModel.getTags().contains(ContributionsAnalyzer.MC_POPUP)) {
			return !menuContribution.getTags().contains(ContributionsAnalyzer.MC_POPUP)
					&& menuContribution.getTags().contains(ContributionsAnalyzer.MC_MENU);
		}
		if (menuModel.getTags().contains(ContributionsAnalyzer.MC_MENU)) {
			return !menuContribution.getTags().contains(ContributionsAnalyzer.MC_MENU)
					&& menuContribution.getTags().contains(ContributionsAnalyzer.MC_POPUP);
		}
		if (!includePopups) {
			// not including popups, so filter out popup menu contributions if the menu is a regular
			// menu
			return menuContribution.getTags().contains(ContributionsAnalyzer.MC_POPUP);
		}
		return false;
	}

	public static void collectInfo(ExpressionInfo info, MExpression exp) {
		if (!(exp instanceof MCoreExpression)) {
			return;
		}
		MCoreExpression expr = (MCoreExpression) exp;
		Expression ref = null;
		if (expr.getCoreExpression() instanceof Expression) {
			ref = (Expression) expr.getCoreExpression();
		} else {
			ref = new ReferenceExpression(expr.getCoreExpressionId());
			expr.setCoreExpression(ref);
		}
		ref.collectExpressionInfo(info);
	}

	public static boolean isVisible(MMenuContribution menuContribution, ExpressionContext eContext) {
		if (menuContribution.getVisibleWhen() == null) {
			return true;
		}
		return isVisible(menuContribution.getVisibleWhen(), eContext);
	}

	public static boolean isVisible(MToolBarContribution contribution, ExpressionContext eContext) {
		if (contribution.getVisibleWhen() == null) {
			return true;
		}
		return isVisible(contribution.getVisibleWhen(), eContext);
	}

	public static boolean isVisible(MTrimContribution contribution, ExpressionContext eContext) {
		if (contribution.getVisibleWhen() == null) {
			return true;
		}
		return isVisible(contribution.getVisibleWhen(), eContext);
	}

	public static boolean isVisible(MExpression exp, final ExpressionContext eContext) {
		if (exp instanceof MCoreExpression) {
			MCoreExpression coreExpression = (MCoreExpression) exp;
			return isCoreExpressionVisible(coreExpression, eContext);
		} else if (exp instanceof MImperativeExpression) {
			return isImperativeExpressionVisible((MImperativeExpression) exp, eContext);
		}

		return true;
	}

	private static boolean isCoreExpressionVisible(MCoreExpression coreExpression, final ExpressionContext eContext) {
		final Expression ref;
		if (coreExpression.getCoreExpression() instanceof Expression) {
			ref = (Expression) coreExpression.getCoreExpression();
		} else {
			ref = new ReferenceExpression(coreExpression.getCoreExpressionId());
			coreExpression.setCoreExpression(ref);
		}
		// Creates dependency on a predefined value that can be "poked" by
		// the evaluation
		// service
		ExpressionInfo info = ref.computeExpressionInfo();
		String[] names = info.getAccessedPropertyNames();
		for (String name : names) {
			eContext.getVariable(name + ".evaluationServiceLink"); //$NON-NLS-1$
		}
		boolean ret = false;
		try {
			ret = ref.evaluate(eContext) != EvaluationResult.FALSE;
		} catch (Exception e) {
			if (DEBUG) {
				trace("isVisible exception", e); //$NON-NLS-1$
			}
		}
		return ret;
	}

	private static boolean isImperativeExpressionVisible(MImperativeExpression exp, final ExpressionContext eContext) {
		Object imperativeExpressionObject = exp.getObject();
		if (imperativeExpressionObject == null) {
			IContributionFactory contributionFactory = eContext.eclipseContext.get(IContributionFactory.class);
			Object newImperativeExpression = contributionFactory.create(exp.getContributionURI(),
					eContext.eclipseContext);
			exp.setObject(newImperativeExpression);
			imperativeExpressionObject = newImperativeExpression;
		}

		Object result = null;

		if (exp.isTracking()) {
			result = invoke(imperativeExpressionObject, Evaluate.class, eContext.eclipseContext, null, missingEvaluate);
		} else {
			result = ContextInjectionFactory.invoke(imperativeExpressionObject, Evaluate.class, eContext.eclipseContext,
					null, missingEvaluate);
		}

		if (result == missingEvaluate) {
			throw new IllegalStateException(
					"There is no method annotated with @Evaluate in the imperative expression class"); //$NON-NLS-1$
		}
		return (boolean) result;
	}

	final private static InjectorImpl injector = (InjectorImpl) InjectorFactory.getDefault();

	static private Object invoke(Object object, Class<? extends Annotation> qualifier, IEclipseContext context,
			IEclipseContext localContext, Object defaultValue) throws InjectionException {
		PrimaryObjectSupplier supplier = ContextObjectSupplier.getObjectSupplier(context, injector);
		PrimaryObjectSupplier tempSupplier = ContextObjectSupplier.getObjectSupplier(localContext, injector);
		return injector.invoke(object, qualifier, defaultValue, supplier, tempSupplier, false, true);
	}

	public static void addMenuContributions(final MMenu menuModel,
			final ArrayList<MMenuContribution> toContribute,
			final ArrayList<MMenuElement> menuContributionsToRemove) {

		HashSet<String> existingMenuIds = new HashSet<>();
		HashSet<String> existingSeparatorNames = new HashSet<>();
		for (MMenuElement child : menuModel.getChildren()) {
			String elementId = child.getElementId();
			if (child instanceof MMenu && elementId != null) {
				existingMenuIds.add(elementId);
			} else if (child instanceof MMenuSeparator && elementId != null) {
				existingSeparatorNames.add(elementId);
			}
		}

		boolean done = toContribute.isEmpty();
		while (!done) {
			ArrayList<MMenuContribution> curList = new ArrayList<>(toContribute);
			int retryCount = toContribute.size();
			toContribute.clear();

			for (MMenuContribution menuContribution : curList) {
				if (!processAddition(menuModel, menuContributionsToRemove, menuContribution,
						existingMenuIds, existingSeparatorNames)) {
					toContribute.add(menuContribution);
				}
			}
			// We're done if the retryList is now empty (everything done) or
			// if the list hasn't changed at all (no hope)
			done = (toContribute.isEmpty()) || (toContribute.size() == retryCount);
		}
	}

	public static boolean processAddition(final MMenu menuModel,
			final ArrayList<MMenuElement> menuContributionsToRemove,
			MMenuContribution menuContribution, final HashSet<String> existingMenuIds,
			HashSet<String> existingSeparatorNames) {
		int idx = getIndex(menuModel, menuContribution.getPositionInParent());
		if (idx == -1) {
			return false;
		}
		for (MMenuElement item : menuContribution.getChildren()) {
			if (item instanceof MMenu && existingMenuIds.contains(item.getElementId())) {
				// skip this, it's already there
				continue;
			} else if (item instanceof MMenuSeparator
					&& existingSeparatorNames.contains(item.getElementId())) {
				// skip this, it's already there
				continue;
			}
			MMenuElement copy = (MMenuElement) EcoreUtil.copy((EObject) item);
			if (DEBUG) {
				trace("addMenuContribution " + copy, menuModel.getWidget(), menuModel); //$NON-NLS-1$
			}
			menuContributionsToRemove.add(copy);
			menuModel.getChildren().add(idx++, copy);
			if (copy instanceof MMenu && copy.getElementId() != null) {
				existingMenuIds.add(copy.getElementId());
			} else if (copy instanceof MMenuSeparator && copy.getElementId() != null) {
				existingSeparatorNames.add(copy.getElementId());
			}
		}
		return true;
	}

	public static boolean processAddition(final MToolBar toolBarModel,
			MToolBarContribution toolBarContribution, List<MToolBarElement> contributions,
			HashSet<String> existingSeparatorNames) {
		int idx = getIndex(toolBarModel, toolBarContribution.getPositionInParent());
		if (idx == -1) {
			return false;
		}
		for (MToolBarElement item : toolBarContribution.getChildren()) {
			if (item instanceof MToolBarSeparator
					&& existingSeparatorNames.contains(item.getElementId())) {
				// skip this, it's already there
				continue;
			}
			MToolBarElement copy = (MToolBarElement) EcoreUtil.copy((EObject) item);
			if (DEBUG) {
				trace("addToolBarContribution " + copy, toolBarModel.getWidget(), toolBarModel); //$NON-NLS-1$
			}
			toolBarModel.getChildren().add(idx++, copy);
			contributions.add(copy);
			if (copy instanceof MToolBarSeparator && copy.getElementId() != null) {
				existingSeparatorNames.add(copy.getElementId());
			}
		}
		return true;
	}

	public static boolean processAddition(final MTrimBar trimBar, MTrimContribution contribution,
			List<MTrimElement> contributions, HashSet<String> existingToolbarIds) {
		int idx = getIndex(trimBar, contribution.getPositionInParent());
		if (idx == -1) {
			return false;
		}
		for (MTrimElement item : contribution.getChildren()) {
			if (item instanceof MToolBar && existingToolbarIds.contains(item.getElementId())) {
				// skip this, it's already there
				continue;
			}
			MTrimElement copy = (MTrimElement) EcoreUtil.copy((EObject) item);
			if (DEBUG) {
				trace("addTrimContribution " + copy, trimBar.getWidget(), trimBar); //$NON-NLS-1$
			}
			trimBar.getChildren().add(idx++, copy);
			contributions.add(copy);
			if (copy instanceof MToolBar && copy.getElementId() != null) {
				existingToolbarIds.add(copy.getElementId());
			}
		}
		return true;
	}

	private static int getIndex(MElementContainer<?> menuModel, String positionInParent) {
		String id = null;
		String modifier = null;
		if (positionInParent != null && positionInParent.length() > 0) {
			String[] array = positionInParent.split("="); //$NON-NLS-1$
			modifier = array[0];
			// may have an invalid position, check for this
			if (array.length > 1) {
				id = array[1];
			}
		}
		if (id == null) {
			return menuModel.getChildren().size();
		}

		int idx = 0;
		int size = menuModel.getChildren().size();
		while (idx < size) {
			if (id.equals(menuModel.getChildren().get(idx).getElementId())) {
				if ("after".equals(modifier)) { //$NON-NLS-1$
					idx++;
				}
				return idx;
			}
			idx++;
		}
		return id.equals("additions") ? menuModel.getChildren().size() : -1; //$NON-NLS-1$
	}

	public static MCommand getCommandById(MApplication app, String cmdId) {
		return app.getCommand(cmdId);
	}

	static class Key {
		private int tag = -1;
		private int hc = -1;
		private String parentId;
		private String position;
		private MCoreExpression vexp;
		private Object factory;

		public Key(String parentId, String position, List<String> tags, MCoreExpression vexp,
				Object factory) {
			this.parentId = parentId;
			this.position = position;
			this.vexp = vexp;
			this.factory = factory;
			if (tags.contains("scheme:menu")) { //$NON-NLS-1$
				tag = 1;
			} else if (tags.contains("scheme:popup")) { //$NON-NLS-1$
				tag = 2;
			} else if (tags.contains("scheme:toolbar")) { //$NON-NLS-1$
				tag = 3;
			} else {
				tag = 0;
			}
		}

		int getSchemeTag() {
			return tag;
		}

		@Override
		public boolean equals(Object obj) {
			if (!(obj instanceof Key)) {
				return false;
			}
			Key other = (Key) obj;
			Object exp1 = vexp == null ? null : vexp.getCoreExpression();
			Object exp2 = other.vexp == null ? null : other.vexp.getCoreExpression();
			return Objects.equals(parentId, other.parentId) && Objects.equals(position, other.position)
					&& getSchemeTag() == other.getSchemeTag() && Objects.equals(exp1, exp2)
					&& Objects.equals(factory, other.factory);
		}

		@Override
		public int hashCode() {
			if (hc == -1) {
				Object exp1 = vexp == null ? null : vexp.getCoreExpression();
				hc = Util.hashCode(parentId);
				hc = hc * 87 + Util.hashCode(position);
				hc = hc * 87 + getSchemeTag();
				hc = hc * 87 + Util.hashCode(exp1);
				hc = hc * 87 + Util.hashCode(factory);
			}
			return hc;
		}

		@Override
		public String toString() {
			return getClass().getName() + " " + parentId + "--" + position //$NON-NLS-1$ //$NON-NLS-2$
					+ "--" + getSchemeTag() + "--" + vexp; //$NON-NLS-1$//$NON-NLS-2$
		}
	}

	static class MenuKey extends Key {
		static final String FACTORY = "ContributionFactory"; //$NON-NLS-1$
		private MMenuContribution contribution;

		public MenuKey(MMenuContribution mc) {
			super(mc.getParentId(), mc.getPositionInParent(), mc.getTags(), (MCoreExpression) mc
					.getVisibleWhen(), mc.getTransientData().get(FACTORY));
			this.contribution = mc;
			mc.setWidget(this);
		}

		public MMenuContribution getContribution() {
			return contribution;
		}
	}

	static class ToolBarKey extends Key {
		static final String FACTORY = "ToolBarContributionFactory"; //$NON-NLS-1$
		private MToolBarContribution contribution;

		public ToolBarKey(MToolBarContribution mc) {
			super(mc.getParentId(), mc.getPositionInParent(), mc.getTags(), (MCoreExpression) mc
					.getVisibleWhen(), mc.getTransientData().get(FACTORY));
			this.contribution = mc;
			mc.setWidget(this);
		}

		public MToolBarContribution getContribution() {
			return contribution;
		}
	}

	static class TrimKey extends Key {
		private MTrimContribution contribution;

		public TrimKey(MTrimContribution mc) {
			super(mc.getParentId(), mc.getPositionInParent(), mc.getTags(), (MCoreExpression) mc
					.getVisibleWhen(), null);
			this.contribution = mc;
			mc.setWidget(this);
		}

		public MTrimContribution getContribution() {
			return contribution;
		}
	}

	private static MenuKey getKey(MMenuContribution contribution) {
		if (contribution.getWidget() instanceof MenuKey) {
			return (MenuKey) contribution.getWidget();
		}
		return new MenuKey(contribution);
	}

	private static ToolBarKey getKey(MToolBarContribution contribution) {
		if (contribution.getWidget() instanceof ToolBarKey) {
			return (ToolBarKey) contribution.getWidget();
		}
		return new ToolBarKey(contribution);
	}

	private static TrimKey getKey(MTrimContribution contribution) {
		if (contribution.getWidget() instanceof TrimKey) {
			return (TrimKey) contribution.getWidget();
		}
		return new TrimKey(contribution);
	}

	public static void printContributions(ArrayList<MMenuContribution> contributions) {
		if (!DEBUG) {
			return;
		}
		for (MMenuContribution c : contributions) {
			trace("\n" + c, null); //$NON-NLS-1$
			for (MMenuElement element : c.getChildren()) {
				printElement(1, element);
			}
		}
	}

	private static void printElement(int level, MMenuElement element) {
		StringBuilder buf = new StringBuilder();
		for (int i = 0; i < level; i++) {
			buf.append('\t');
		}
		buf.append(element.toString());
		trace(buf.toString(), null);
		if (element instanceof MMenu) {
			for (MMenuElement item : ((MMenu) element).getChildren()) {
				printElement(level + 1, item);
			}
		}
	}

	public static void mergeToolBarContributions(ArrayList<MToolBarContribution> contributions,
			ArrayList<MToolBarContribution> result) {
		HashMap<ToolBarKey, ArrayList<MToolBarContribution>> buckets = new HashMap<>();
		if (DEBUG) {
			trace("mergeContributions size: " + contributions.size(), null); //$NON-NLS-1$
		}
		// first pass, sort by parentId?position,scheme,visibleWhen
		for (MToolBarContribution contribution : contributions) {
			ToolBarKey key = getKey(contribution);
			ArrayList<MToolBarContribution> slot = buckets.get(key);
			if (slot == null) {
				slot = new ArrayList<>();
				buckets.put(key, slot);
			}
			slot.add(contribution);
		}
		Iterator<MToolBarContribution> i = contributions.iterator();
		while (i.hasNext() && !buckets.isEmpty()) {
			MToolBarContribution contribution = i.next();
			ToolBarKey key = getKey(contribution);
			ArrayList<MToolBarContribution> slot = buckets.remove(key);
			if (slot == null) {
				continue;
			}
			MToolBarContribution toContribute = null;
			for (MToolBarContribution item : slot) {
				if (toContribute == null) {
					toContribute = item;
					continue;
				}
				Object[] array = item.getChildren().toArray();
				for (Object element : array) {
					MToolBarElement me = (MToolBarElement) element;
					if (!containsMatching(toContribute.getChildren(), me)) {
						toContribute.getChildren().add(me);
					}
				}
			}
			if (toContribute != null) {
				toContribute.setWidget(null);
				result.add(toContribute);
			}
		}
		if (DEBUG) {
			trace("mergeContributions: final size: " + result.size(), null); //$NON-NLS-1$
		}
	}

	public static void mergeContributions(ArrayList<MMenuContribution> contributions,
			ArrayList<MMenuContribution> result) {
		HashMap<MenuKey, ArrayList<MMenuContribution>> buckets = new HashMap<>();
		if (DEBUG) {
			trace("mergeContributions size: " + contributions.size(), null); //$NON-NLS-1$
			printContributions(contributions);
		}
		// first pass, sort by parentId?position,scheme,visibleWhen
		for (MMenuContribution contribution : contributions) {
			MenuKey key = getKey(contribution);
			ArrayList<MMenuContribution> slot = buckets.get(key);
			if (slot == null) {
				slot = new ArrayList<>();
				buckets.put(key, slot);
			}
			slot.add(contribution);
		}
		Iterator<MMenuContribution> i = contributions.iterator();
		while (i.hasNext() && !buckets.isEmpty()) {
			MMenuContribution contribution = i.next();
			MenuKey key = getKey(contribution);
			ArrayList<MMenuContribution> slot = buckets.remove(key);
			if (slot == null) {
				continue;
			}
			MMenuContribution toContribute = null;
			for (MMenuContribution item : slot) {
				if (toContribute == null) {
					toContribute = item;
					continue;
				}
				Object[] array = item.getChildren().toArray();
				int idx = getIndex(toContribute, item.getPositionInParent());
				if (idx == -1) {
					idx = 0;
				}
				for (Object element : array) {
					MMenuElement me = (MMenuElement) element;
					if (!containsMatching(toContribute.getChildren(), me)) {
						toContribute.getChildren().add(idx, me);
						idx++;
					}
				}
			}
			if (toContribute != null) {
				toContribute.setWidget(null);
				result.add(toContribute);
			}
		}
		trace("mergeContributions: final size: " + result.size(), null); //$NON-NLS-1$
	}

	private static boolean containsMatching(List<MMenuElement> children, MMenuElement me) {
		for (MMenuElement element : children) {
			if (Objects.equals(me.getElementId(), element.getElementId())
					&& element.getClass().isInstance(me)
					&& (element instanceof MMenuSeparator || element instanceof MMenu)) {
				return true;
			}
		}
		return false;
	}

	private static boolean containsMatching(List<MToolBarElement> children, MToolBarElement me) {
		for (MToolBarElement element : children) {
			if (Objects.equals(me.getElementId(), element.getElementId())
					&& element.getClass().isInstance(me)
					&& (element instanceof MToolBarSeparator || element instanceof MToolBar)) {
				return true;
			}
		}
		return false;
	}

	private static boolean containsMatching(List<MTrimElement> children, MTrimElement me) {
		for (MTrimElement element : children) {
			if (Objects.equals(me.getElementId(), element.getElementId())
					&& element.getClass().isInstance(me)
					&& (element instanceof MToolBarSeparator || element instanceof MToolBar)) {
				return true;
			}
		}
		return false;
	}

	public static int indexForId(MElementContainer<MMenuElement> parentMenu, String id) {
		if (id == null || id.length() == 0) {
			return -1;
		}
		int i = 0;
		for (MMenuElement item : parentMenu.getChildren()) {
			if (id.equals(item.getElementId())) {
				return i;
			}
			i++;
		}
		return -1;
	}

	public static final String MC_POPUP = "menuContribution:popup"; //$NON-NLS-1$
	public static final String MC_MENU = "menuContribution:menu"; //$NON-NLS-1$
	public static final String MC_TOOLBAR = "menuContribution:toolbar"; //$NON-NLS-1$
	public static final String POPUP_PARENT_ID = "popup"; //$NON-NLS-1$

	public static void mergeTrimContributions(ArrayList<MTrimContribution> contributions,
			ArrayList<MTrimContribution> result) {
		HashMap<TrimKey, ArrayList<MTrimContribution>> buckets = new HashMap<>();
		if (DEBUG) {
			trace("mergeContributions size: " + contributions.size(), null); //$NON-NLS-1$
		}
		// first pass, sort by parentId?position,scheme,visibleWhen
		for (MTrimContribution contribution : contributions) {
			TrimKey key = getKey(contribution);
			ArrayList<MTrimContribution> slot = buckets.get(key);
			if (slot == null) {
				slot = new ArrayList<>();
				buckets.put(key, slot);
			}
			slot.add(contribution);
		}
		Iterator<MTrimContribution> i = contributions.iterator();
		while (i.hasNext() && !buckets.isEmpty()) {
			MTrimContribution contribution = i.next();
			TrimKey key = getKey(contribution);
			ArrayList<MTrimContribution> slot = buckets.remove(key);
			if (slot == null) {
				continue;
			}
			MTrimContribution toContribute = null;
			for (MTrimContribution item : slot) {
				if (toContribute == null) {
					toContribute = item;
					continue;
				}
				Object[] array = item.getChildren().toArray();
				for (Object element : array) {
					MTrimElement me = (MTrimElement) element;
					if (!containsMatching(toContribute.getChildren(), me)) {
						toContribute.getChildren().add(me);
					}
				}
			}
			if (toContribute != null) {
				toContribute.setWidget(null);
				result.add(toContribute);
			}
		}
		if (DEBUG) {
			trace("mergeContributions: final size: " + result.size(), null); //$NON-NLS-1$
		}
	}

	public static void populateModelInterfaces(Object modelObject, IEclipseContext context,
			Class<?>[] interfaces) {
		for (Class<?> intf : interfaces) {
			if (Policy.DEBUG_CONTEXTS) {
				Activator.trace(Policy.DEBUG_CONTEXTS_FLAG, "Adding " + intf.getName() + " for " //$NON-NLS-1$ //$NON-NLS-2$
						+ modelObject.getClass().getName(), null);
			}
			context.set(intf.getName(), modelObject);

			populateModelInterfaces(modelObject, context, intf.getInterfaces());
		}
	}
}
