/*******************************************************************************
 * Copyright (c) 2004, 2009 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 Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jface.tests.action;

import org.eclipse.jface.action.ActionContributionItem;
import org.eclipse.jface.action.GroupMarker;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IContributionItem;
import org.eclipse.jface.action.IContributionManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.swt.widgets.Decorations;
import org.eclipse.swt.widgets.Menu;

/**
 * Tests for the MenuManager API.
 *
 * @since 3.1
 */
public class MenuManagerTest extends JFaceActionTest {

	private int groupMarkerCount = 0;
	private int separatorCount = 0;

	/**
	 * Constructs a new test with the given name.
	 *
	 * @param name the name of the test
	 */
	public MenuManagerTest(String name) {
		super(name);
	}

	/**
	 * Tests that a menu with no concrete visible items (that is, ignoring
	 * separators and group markers) is hidden.
	 *
	 * @see MenuManager#isVisible()
	 */
	public void testMenuWithNoConcreteVisibleItemsIsHidden() {
		MenuManager menuBarMgr = createMenuBarManager();

		MenuManager fileMenu = createMenuManager("File", "gsgn");
		menuBarMgr.add(fileMenu);
		menuBarMgr.updateAll(false);
		assertEquals(0, getShell().getMenuBar().getItems().length);
	}

	/**
	 * Tests that adding a concrete visible item to a menu with no concrete visible
	 * items makes the menu visible. Regression test for bug 54779 [RCP] Problem
	 * updating menus, menu not appearing
	 *
	 * @see MenuManager#isVisible()
	 * @see MenuManager#markDirty()
	 */
	public void testAddingConcreteItemToMenuWithNoConcreteVisibleItems() {
		MenuManager menuBarMgr = createMenuBarManager();

		MenuManager fileMenuMgr = createMenuManager("File", "gsgn");
		menuBarMgr.add(fileMenuMgr);
		menuBarMgr.updateAll(false);

		Menu menuBar = getShell().getMenuBar();
		assertEquals(0, menuBar.getItems().length);

		fileMenuMgr.add(createItem('a'));
		menuBarMgr.updateAll(false);
		assertEquals(1, menuBar.getItems().length);

		assertEquals("File", menuBar.getItems()[0].getText());

		Menu fileMenu = menuBar.getItems()[0].getMenu();
		assertEquals(1, fileMenu.getItems().length);
	}

	/**
	 * This is a test case for bug 204788 to ensure that a disposed menu is marked
	 * as being dirty.
	 */
	public void testDisposedMenuIsDirty() {
		MenuManager menuBarMgr = createMenuBarManager();

		MenuManager fileMenuMgr = createMenuManager("File", "gsgn");
		menuBarMgr.add(fileMenuMgr);
		menuBarMgr.updateAll(false);

		assertFalse(menuBarMgr.isDirty());

		menuBarMgr.dispose();
		assertTrue(menuBarMgr.isDirty());
	}

	/**
	 * This is a test case for bug 255429 to ensure that a menu manager without any
	 * text set does not throw an NPE.
	 */
	public void testEmptyMenuManagerNPE() {
		Menu menu = new Menu(getShell());
		MenuManager manager = new MenuManager();
		manager.fill(menu, -1);
	}

	/**
	 * Creates a menu manager with the given name, adding items based on the given
	 * template.
	 *
	 * @param name     the name
	 * @param template the template
	 *
	 * @return a menu with no concrete visible items
	 */
	private MenuManager createMenuManager(String name, String template) {
		MenuManager menuMgr = new MenuManager(name);
		addItems(menuMgr, template);
		return menuMgr;
	}

	private void addItems(IContributionManager manager, String template) {
		for (int i = 0; i < template.length(); ++i) {
			manager.add(createItem(template.charAt(i)));
		}
	}

	private IContributionItem createItem(char template) {
		switch (template) {
		case 'g':
			return new GroupMarker("testGroup" + groupMarkerCount++);
		case 's':
			return new Separator("testSeparator" + separatorCount++);
		case 'a': {
			IAction action = new DummyAction();
			return new ActionContributionItem(action);
		}
		case 'n': {
			IAction action = new DummyAction();
			ActionContributionItem item = new ActionContributionItem(action);
			item.setVisible(false);
			return item;
		}
		default:
			throw new IllegalArgumentException("Unknown template char: " + template);
		}
	}

	protected MenuManager createMenuBarManager() {
		Decorations shell = getShell();
		MenuManager menuMgr = new MenuManager();
		Menu menuBar = menuMgr.createMenuBar(shell);
		shell.setMenuBar(menuBar);
		return menuMgr;
	}
}
