/*******************************************************************************
 * Copyright (c) 2000, 2015 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
 *     Dan Rubel (dan_rubel@instantiations.com) - accessor to get menu id
 *     Lars Vogel <Lars.Vogel@vogella.com> - Bug 472654
 *******************************************************************************/
package org.eclipse.ui.internal;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionDelta;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IRegistryChangeEvent;
import org.eclipse.core.runtime.IRegistryChangeListener;
import org.eclipse.core.runtime.Platform;
import org.eclipse.e4.core.contexts.IEclipseContext;
import org.eclipse.e4.ui.internal.workbench.ContributionsAnalyzer;
import org.eclipse.e4.ui.internal.workbench.OpaqueElementUtil;
import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
import org.eclipse.e4.ui.internal.workbench.swt.MenuService;
import org.eclipse.e4.ui.model.application.ui.MElementContainer;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.basic.MPart;
import org.eclipse.e4.ui.model.application.ui.menu.MMenu;
import org.eclipse.e4.ui.model.application.ui.menu.MMenuElement;
import org.eclipse.e4.ui.model.application.ui.menu.MPopupMenu;
import org.eclipse.e4.ui.model.application.ui.menu.impl.MenuFactoryImpl;
import org.eclipse.e4.ui.workbench.renderers.swt.MenuManagerRenderer;
import org.eclipse.e4.ui.workbench.swt.factories.IRendererFactory;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IMenuListener2;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.SubMenuManager;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartSite;
import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;

/**
 * This class extends a single popup menu
 */
public class PopupMenuExtender implements IMenuListener2,
		IRegistryChangeListener {

    /**
     * The bit in <code>bitSet</code> that stores whether the static actions
     * have been read from the registry.
     */
    private static final int STATIC_ACTION_READ = 1;

    /**
     * The bit in <code>bitSet</code> that stores whether the editor input
     * should be included for the sake of object contributions.
     */
    private static final int INCLUDE_EDITOR_INPUT = 1 << 1;

    private final MenuManager menu;

    private SubMenuManager menuWrapper;

    private final ISelectionProvider selProvider;

    private final IWorkbenchPart part;

	private Map<String, ViewerActionBuilder> staticActionBuilders = null;

    /**
     * The boolean properties maintained by this extender. A bit set is used to
     * save memory.
     */
	private int bitSet = 0;

	private ArrayList<PluginActionContributionItem> actionContributionCache = new ArrayList<>();
	private boolean cleanupNeeded = false;

	private MPart modelPart;

	/**
	 * The context that will be used to create the popup menu's context under.
	 */
	private IEclipseContext context;

    /**
     * Construct a new menu extender.
     *
     * @param id
     *            the menu id
     * @param menu
     *            the menu to extend
     * @param prov
     *            the selection provider
     * @param part
     *            the part to extend
	 * @param context
	 *            the context to create the child popup menu context under
     */
	public PopupMenuExtender(String id, MenuManager menu, ISelectionProvider prov,
			IWorkbenchPart part, IEclipseContext context) {
		this(id, menu, prov, part, context, true);
	}

    /**
     * Construct a new menu extender.
     *
     * @param id
     *            the menu id
     * @param menu
     *            the menu to extend
     * @param prov
     *            the selection provider
     * @param part
     *            the part to extend
	 * @param context
	 *            the context to create the child popup menu context under
     * @param includeEditorInput
     *            Whether the editor input should be included when adding object
     *            contributions to this context menu.
     */
	public PopupMenuExtender(final String id, final MenuManager menu,
			final ISelectionProvider prov, final IWorkbenchPart part, IEclipseContext context,
			final boolean includeEditorInput) {
		super();
		this.menu = menu;
		this.selProvider = prov;
		this.part = part;
		this.context = context;
		this.modelPart = part.getSite().getService(MPart.class);
		if (includeEditorInput) {
			bitSet |= INCLUDE_EDITOR_INPUT;
		}
		menu.addMenuListener(this);
		if (!menu.getRemoveAllWhenShown()) {
			menuWrapper = new SubMenuManager(menu);
			menuWrapper.setVisible(true);
		}
		createModelFor(id);
		addMenuId(id);

		Platform.getExtensionRegistry().addRegistryChangeListener(this);
	}

	private void createModelFor(String id) {
		if (id == null) {
			id = getClass().getName() + '.' + System.identityHashCode(this);
		}
		menuModel = null;
		for (MMenu item : modelPart.getMenus()) {
			if (id.equals(item.getElementId()) && item instanceof MPopupMenu
					&& item.getTags().contains("popup")) { //$NON-NLS-1$
				menuModel = (MPopupMenu) item;
				break;
			}
		}
		if (menuModel == null) {
			menuModel = MenuFactoryImpl.eINSTANCE.createPopupMenu();
			menuModel.setElementId(id);
			menuModel.getTags().add(ContributionsAnalyzer.MC_POPUP);
			modelPart.getMenus().add(menuModel);
		}
		IRendererFactory factory = modelPart.getContext().get(IRendererFactory.class);
		AbstractPartRenderer obj = factory.getRenderer(menuModel, null);
		if (obj instanceof MenuManagerRenderer) {
			((MenuManagerRenderer) obj).linkModelToManager(menuModel, menu);
		}
		registerE4Support();
		cleanUpContributionCache();
	}

	private void registerE4Support() {
		if (menuModel.getWidget() == null && menu.getMenu() != null) {
			MenuService.registerMenu(menu.getMenu().getParent(), menuModel, context);
		}
	}
	// getMenuId() added by Dan Rubel (dan_rubel@instantiations.com)
    /**
     * Return the menu identifiers for this extender.
     *
     * @return The set of all identifiers that represent this extender.
     */
	public Set<String> getMenuIds() {
    	if (staticActionBuilders == null) {
			return Collections.emptySet();
    	}

        return staticActionBuilders.keySet();
    }

    /**
     * <p>
     * Adds another menu identifier to this extender. An extender can represent
     * many menu identifiers. These identifiers should represent the same menu
     * manager, selection provider and part. Duplicate identifiers are
     * automatically ignored.
     * </p>
     * <p>
     * For example, it is necessary to filter out duplicate identifiers for
     * <code>CompilationUnitEditor</code> instances, as these define both
     * <code>"#CompilationUnitEditorContext"</code> and
     * <code>"org.eclipse.jdt.ui.CompilationUnitEditor.EditorContext"</code>
     * as menu identifier for the same pop-up menu. We don't want to contribute
     * duplicate items in this case.
     * </p>
     *
     * @param menuId
     *            The menu identifier to add to this extender; should not be
     *            <code>null</code>.
     */
    public final void addMenuId(final String menuId) {
		bitSet &= ~STATIC_ACTION_READ;
		if (menuModel != null) {
			List<String> tags = menuModel.getTags();
			String tag = "popup:" + menuId; //$NON-NLS-1$
			if (!tags.contains(tag)) {
				tags.add(tag);
			}
		}
		readStaticActionsFor(menuId);
	}

    /**
     * Determines whether this extender would be the same as another extender
     * created with the given values. Two extenders are equivalent if they have
     * the same menu manager, selection provider and part (i.e., if the menu
     * they represent is about to show, they would populate it with duplicate
     * values).
     *
     * @param menuManager
     *            The menu manager with which to compare; may be
     *            <code>null</code>.
     * @param selectionProvider
     *            The selection provider with which to compare; may be
     *            <code>null</code>.
     * @param part
     *            The part with which to compare; may be <code>null</code>.
     * @return <code>true</code> if the menu manager, selection provider and
     *         part are all the same.
     */
    public final boolean matches(final MenuManager menuManager,
            final ISelectionProvider selectionProvider,
            final IWorkbenchPart part) {
        return (this.menu == menuManager)
                && (this.selProvider == selectionProvider)
                && (this.part == part);
    }

    /**
     * Contributes items registered for the currently active editor.
     */
	private void addEditorActions(IMenuManager mgr, Set<IObjectActionContributor> alreadyContributed) {
        ISelectionProvider activeEditor = new ISelectionProvider() {

            @Override
			public void addSelectionChangedListener(
                    ISelectionChangedListener listener) {
                throw new UnsupportedOperationException(
                "This ISelectionProvider is static, and cannot be modified."); //$NON-NLS-1$
            }

            @Override
			public ISelection getSelection() {
                if (part instanceof IEditorPart) {
                    final IEditorPart editorPart = (IEditorPart) part;
                    return new StructuredSelection(new Object[] { editorPart
                            .getEditorInput() });
                }

                return new StructuredSelection(new Object[0]);
            }

            @Override
			public void removeSelectionChangedListener(
                    ISelectionChangedListener listener) {
                throw new UnsupportedOperationException(
                "This ISelectionProvider is static, and cannot be modified."); //$NON-NLS-1$
            }

            @Override
			public void setSelection(ISelection selection) {
                throw new UnsupportedOperationException(
                        "This ISelectionProvider is static, and cannot be modified."); //$NON-NLS-1$
            }
        };

		if (ObjectActionContributorManager.getManager().contributeObjectActions(part, mgr,
				activeEditor, alreadyContributed)) {
			mgr.add(new Separator());
		}
    }

    /**
     * Contributes items registered for the object type(s) in
     * the current selection.
     */
	private void addObjectActions(IMenuManager mgr, Set<IObjectActionContributor> alreadyContributed) {
        if (selProvider != null) {
			if (ObjectActionContributorManager.getManager().contributeObjectActions(part, mgr,
					selProvider, alreadyContributed)) {
				mgr.add(new Separator());
            }
        }
    }

    /**
     * Disposes all of the static actions.
     */
    private final void clearStaticActions() {
		bitSet &= ~STATIC_ACTION_READ;
		if (staticActionBuilders != null) {
			final Iterator<ViewerActionBuilder> staticActionBuilderItr = staticActionBuilders
					.values().iterator();
			while (staticActionBuilderItr.hasNext()) {
				final ViewerActionBuilder staticActionBuilder = staticActionBuilderItr.next();
				staticActionBuilder.dispose();
			}
		}
	}

    /**
     * Adds static items to the context menu.
     */
    private void addStaticActions(IMenuManager mgr) {
		if (staticActionBuilders != null) {
			final Iterator<ViewerActionBuilder> staticActionBuilderItr = staticActionBuilders
					.values().iterator();
			while (staticActionBuilderItr.hasNext()) {
				final ViewerActionBuilder staticActionBuilder = staticActionBuilderItr.next();
				staticActionBuilder.contribute(mgr, null, true);
			}
		}
	}

    /**
     * Notifies the listener that the menu is about to be shown.
     */
    @Override
	public void menuAboutToShow(IMenuManager mgr) {
		registerE4Support();

    	// Add this menu as a visible menu.
    	final IWorkbenchPartSite site = part.getSite();
    	if (site != null) {
			final IWorkbench workbench = site.getWorkbenchWindow()
					.getWorkbench();
			if (workbench instanceof Workbench) {
				final Workbench realWorkbench = (Workbench) workbench;
				runCleanUp(realWorkbench);
				ISelection input = null;
				if ((bitSet & INCLUDE_EDITOR_INPUT) != 0) {
					if (part instanceof IEditorPart) {
						final IEditorPart editorPart = (IEditorPart) part;
						input = new StructuredSelection(
								new Object[] { editorPart.getEditorInput() });
					}
				}
				ISelection s = (selProvider == null ? null : selProvider
						.getSelection());
				realWorkbench.addShowingMenus(getMenuIds(), s, input);
			}
		}

		addMenuContributions(mgr);

    	readStaticActions();
        // test for additions removed to comply with menu contributions
        if (menuWrapper != null) {
            mgr = menuWrapper;
            menuWrapper.removeAll();
        }
		Set<IObjectActionContributor> contributedItems = new HashSet<>();
        if ((bitSet & INCLUDE_EDITOR_INPUT) != 0) {
			addEditorActions(mgr, contributedItems);
        }
		addObjectActions(mgr, contributedItems);
        addStaticActions(mgr);
    }


	/**
	 * well, this goes to the renderer.
	 *
	 * @param mgr
	 */
	private void addMenuContributions(IMenuManager mgr) {
		IRendererFactory factory = modelPart.getContext().get(IRendererFactory.class);
		AbstractPartRenderer obj = factory.getRenderer(menuModel, null);
		if (obj instanceof MenuManagerRenderer) {
			MenuManagerRenderer renderer = (MenuManagerRenderer) obj;
			renderer.reconcileManagerToModel(menu, menuModel);
			renderer.processContributions(menuModel, menuModel.getElementId(), false, true);
			// double cast because we're bad people
			renderer.processContents((MElementContainer<MUIElement>) ((Object) menuModel));
		}
	}

	private MPopupMenu menuModel;

    /**
	 * Notifies the listener that the menu is about to be hidden.
	 */
    @Override
	public final void menuAboutToHide(final IMenuManager mgr) {
    	gatherContributions(mgr);
		cleanupNeeded = true;
    	// Remove this menu as a visible menu.
    	final IWorkbenchPartSite site = part.getSite();
    	if (site != null) {
    		final IWorkbench workbench = site.getWorkbenchWindow().getWorkbench();
    		if (workbench instanceof Workbench) {
    			// try delaying this until after the selection event
    			// has been fired.
    			// This is less threatening if the popup: menu
    			// contributions aren't tied to the evaluation service
				workbench.getDisplay().asyncExec(() -> {
					final Workbench realWorkbench = (Workbench) workbench;
					runCleanUp(realWorkbench);
				});
			}
    	}
    }

	private void runCleanUp(Workbench realWorkbench) {
		if (!cleanupNeeded) {
			return;
		}
		cleanupNeeded = false;
		realWorkbench.removeShowingMenus(getMenuIds(), null, null);
		cleanUpContributionCache();
	}

	private void gatherContributions(final IMenuManager mgr) {
		final IContributionItem[] items = mgr.getItems();
		for (IContributionItem item : items) {
			if (item instanceof PluginActionContributionItem) {
				actionContributionCache.add((PluginActionContributionItem) item);
			} else if (item instanceof IMenuManager) {
				gatherContributions(((IMenuManager) item));
			}
		}
	}

	private void cleanUpContributionCache() {
		if (!actionContributionCache.isEmpty()) {
			PluginActionContributionItem[] items = actionContributionCache
					.toArray(new PluginActionContributionItem[actionContributionCache.size()]);
			actionContributionCache.clear();
			for (PluginActionContributionItem item : items) {
				item.dispose();
			}
		}

		if (modelPart == null || menuModel == null) {
			return;
		}
		IEclipseContext modelContext = modelPart.getContext();
		if (modelContext != null) {
			IRendererFactory factory = modelContext.get(IRendererFactory.class);
			if (factory != null) {
				AbstractPartRenderer obj = factory.getRenderer(menuModel, null);
				if (obj instanceof MenuManagerRenderer) {
					MenuManagerRenderer renderer = (MenuManagerRenderer) obj;
					renderer.cleanUp(menuModel);
				}
			}
		}
	}

	/**
     * Read all of the static items for the content menu.
     */
    private final void readStaticActions() {
    	if (staticActionBuilders != null) {
			final Iterator<String> menuIdItr = staticActionBuilders.keySet().iterator();
			while (menuIdItr.hasNext()) {
				final String menuId = menuIdItr.next();
				readStaticActionsFor(menuId);
			}
		}
    }

    /**
	 * Read static items for a particular menu id, into the context menu.
	 */
    private void readStaticActionsFor(final String menuId) {
		if ((bitSet & STATIC_ACTION_READ) != 0) {
			return;
		}

		bitSet |= STATIC_ACTION_READ;

		// If no menu id provided, then there is no contributions
		// to add. Fix for bug #33140.
		if ((menuId == null) || (menuId.length() < 1)) {
			return;
		}

		if (staticActionBuilders == null) {
			staticActionBuilders = new HashMap<>();
		}

		Object object = staticActionBuilders.get(menuId);
		if (!(object instanceof ViewerActionBuilder)) {
			object = new ViewerActionBuilder();
			staticActionBuilders.put(menuId, (ViewerActionBuilder) object);
		}
		final ViewerActionBuilder staticActionBuilder = (ViewerActionBuilder) object;
		staticActionBuilder.readViewerContributions(menuId, selProvider, part);
	}

    /**
     * Dispose of the menu extender. Should only be called when the part
     * is disposed.
     */
    public void dispose() {
		clearStaticActions();
		Platform.getExtensionRegistry().removeRegistryChangeListener(this);
		menu.removeMenuListener(this);

		if (menuModel != null) {
			// unlink ourselves from the renderer
			IRendererFactory factory = modelPart.getContext().get(IRendererFactory.class);
			AbstractPartRenderer obj = factory.getRenderer(menuModel, null);
			if (obj instanceof MenuManagerRenderer) {
				MenuManagerRenderer renderer = (MenuManagerRenderer) obj;
				unlink(renderer, menuModel);
				renderer.clearModelToManager(menuModel, menu);
			}

			modelPart.getMenus().remove(menuModel);
		}
	}

	/**
	 * Unlink all contribution items from the given model menu.
	 *
	 * @param renderer
	 *            the renderer that is holding the links
	 * @param menu
	 *            the model menu whose children should have its items unlinked
	 *            from their corresponding contribution items
	 */
	private void unlink(MenuManagerRenderer renderer, MMenu menu) {
		for (MMenuElement menuElement : menu.getChildren()) {
			if (OpaqueElementUtil.isOpaqueMenuItem(menuElement)
					|| OpaqueElementUtil.isOpaqueMenuSeparator(menuElement)) {
				Object item = OpaqueElementUtil.getOpaqueItem(menuElement);
				if (item instanceof IContributionItem) {
					renderer.clearModelToContribution(menuElement, (IContributionItem) item);
					OpaqueElementUtil.clearOpaqueItem(menuElement);
				}
			} else if (menuElement instanceof MMenu) {
				MMenu subMenu = (MMenu) menuElement;
				unlink(renderer, subMenu);
				MenuManager manager = renderer.getManager(subMenu);
				if (manager != null) {
					renderer.clearModelToManager(subMenu, manager);
				}
			} else {
				IContributionItem contribution = renderer.getContribution(menuElement);
				if (contribution != null) {
					renderer.clearModelToContribution(menuElement, contribution);
				}
			}
		}
	}

	@Override
	public void registryChanged(final IRegistryChangeEvent event) {
		Display display = Display.getDefault();
		if (part != null) {
			display = part.getSite().getPage().getWorkbenchWindow().getWorkbench().getDisplay();
		}
		//check the delta to see if there are any viewer contribution changes.  if so, null our builder to cause reparsing on the next menu show
		IExtensionDelta [] deltas = event.getExtensionDeltas();
		for (IExtensionDelta delta : deltas) {
			IExtensionPoint extensionPoint = delta.getExtensionPoint();
			if (extensionPoint.getContributor().getName().equals(WorkbenchPlugin.PI_WORKBENCH)
					&& extensionPoint.getSimpleIdentifier().equals(
							IWorkbenchRegistryConstants.PL_POPUP_MENU)) {

				boolean clearPopups = false;
				IConfigurationElement [] elements = delta.getExtension().getConfigurationElements();
				for (IConfigurationElement element : elements) {
					if (element.getName().equals(IWorkbenchRegistryConstants.TAG_VIEWER_CONTRIBUTION)) {
						clearPopups = true;
						break;
					}
				}

				if (clearPopups) {
					display.syncExec(() -> clearStaticActions());
				}
			}
		}
	}

	public MenuManager getManager() {
		return menu;
	}
}
