/*******************************************************************************
 * Copyright (c) 2004, 2015 IBM Corporation 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:
 * IBM - Initial API and implementation
 * hzhou@actuate.com - Fix for  Bug 71695 -
 * [WorkingSets]Removed Working Set is still shown under the menu item
 * when it is the recently used working set
 *******************************************************************************/
package org.eclipse.ui.internal.ide.actions;

import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.application.IActionBarConfigurer;

/**
 * Sub-menu off project menu for showing MRU list of working set builds.
 *
 * @since 3.0
 */
public class BuildSetMenu extends ContributionItem {
    private IActionBarConfigurer actionBars;

    boolean dirty = true;

    private IMenuListener menuListener = manager -> {
	    manager.markDirty();
	    dirty = true;
	};

    private IAction selectBuildWorkingSetAction;

    private IWorkbenchWindow window;

    /**
     * Create a new instance of the receiver.
     * @param window
     * @param actionBars
     */
    public BuildSetMenu(IWorkbenchWindow window, IActionBarConfigurer actionBars) {
        this.window = window;
        this.actionBars = actionBars;
        selectBuildWorkingSetAction = new SelectBuildWorkingSetAction(window,
                actionBars);
    }

    /**
     * Adds a mnemonic accelerator to actions in the MRU list of
     * recently built working sets.
     * @param action the action to add
     * @param index the index to add it at
     */
    private void addMnemonic(BuildSetAction action, int index) {
        StringBuilder label = new StringBuilder();
        //add the numerical accelerator
        if (index < 9) {
            label.append('&');
            label.append(index);
            label.append(' ');
        }
        label.append(action.getWorkingSet().getLabel());
        action.setText(label.toString());
    }

    @Override
	public void fill(Menu menu, int index) {
        if (getParent() instanceof MenuManager) {
			((MenuManager) getParent()).addMenuListener(menuListener);
		}
        if (!dirty) {
			return;
		}
        fillMenu(menu);
        dirty = false;
    }

    /**
     * Fills the menu with Show View actions.
     * @param menu The menu being filled.
     */
    private void fillMenu(Menu menu) {
        boolean isAutoBuilding = ResourcesPlugin.getWorkspace()
                .isAutoBuilding();

        //build MRU list of recently built working sets:
        IWorkingSet[] sets = window.getWorkbench().getWorkingSetManager()
                .getRecentWorkingSets();
        BuildSetAction last = BuildSetAction.lastBuilt;
        IWorkingSet lastSet = null;
        //add build action for the last working set that was built
        int accel = 1;
        if (last != null) {
			// add it only if it has not been removed
			boolean found = false;
			for (IWorkingSet set : sets) {
				if (set.equals(last.getWorkingSet())){
					found = true;
					break;
				}
			}
			if (found) {
	            last.setChecked(true);
	            last.setEnabled(!isAutoBuilding);
	            last.setActionDefinitionId("org.eclipse.ui.project.buildLast"); //$NON-NLS-1$
	            addMnemonic(last, accel++);
	            new ActionContributionItem(last).fill(menu, -1);
	            lastSet = last.getWorkingSet();
			} else {
				BuildSetAction.lastBuilt = null;
			}
        }
        //add build actions for the most recently used working sets
        for (IWorkingSet set : sets) {
            if (lastSet != null && lastSet.equals(set)) {
				continue;
			}
            BuildSetAction action = new BuildSetAction(set, window,
                    actionBars);
            addMnemonic(action, accel++);
            action.setEnabled(!isAutoBuilding);
            new ActionContributionItem(action).fill(menu, -1);
        }
        //add the action to select a different working set
        if (sets.length > 0) {
			new Separator().fill(menu, -1);
		}
        selectBuildWorkingSetAction.setEnabled(!isAutoBuilding);
        new ActionContributionItem(selectBuildWorkingSetAction).fill(menu, -1);
    }

    @Override
	public boolean isDirty() {
        return dirty;
    }

    /**
     * Overridden to always return true and force dynamic menu building.
     */
    @Override
	public boolean isDynamic() {
        return true;
    }

	@Override
	public void dispose() {
		window = null;
		selectBuildWorkingSetAction = null;
		actionBars = null;
		super.dispose();
	}
}
