/*******************************************************************************
 * Copyright (c) 2000, 2011 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:
 *   Jesper Kamstrup Linnet (eclipse@kamstrup-linnet.dk) - initial API and implementation
 * 			(report 36180: Callers/Callees view)
 *   Michael Fraenkel (fraenkel@us.ibm.com) - patch
 *          (report 60714: Call Hierarchy: display search scope in view title)
 *******************************************************************************/
package org.eclipse.jdt.internal.ui.callhierarchy;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.IDialogSettings;

import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IWorkingSet;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.actions.ActionGroup;

import org.eclipse.jdt.core.search.IJavaSearchScope;

import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.ui.IContextMenuConstants;

class SearchScopeActionGroup extends ActionGroup {
	private static final String TAG_SEARCH_SCOPE_TYPE= "search_scope_type"; //$NON-NLS-1$
	private static final String TAG_SELECTED_WORKING_SET= "working_set"; //$NON-NLS-1$
	private static final String TAG_WORKING_SET_COUNT = "working_set_count"; //$NON-NLS-1$

	private static final String DIALOGSTORE_SCOPE_TYPE= "SearchScopeActionGroup.search_scope_type"; //$NON-NLS-1$
	private static final String DIALOGSTORE_SELECTED_WORKING_SET= "SearchScopeActionGroup.working_set";  //$NON-NLS-1$

	static final int SEARCH_SCOPE_TYPE_WORKSPACE= 1;
	static final int SEARCH_SCOPE_TYPE_PROJECT= 2;
	// static final int SEARCH_SCOPE_TYPE_HIERARCHY= 3;
	static final int SEARCH_SCOPE_TYPE_WORKING_SET= 4;

	private SearchScopeAction fSelectedAction = null;
	private String[] fSelectedWorkingSetNames = null;
	private CallHierarchyViewPart fView;
	private IDialogSettings fDialogSettings;
	private SearchScopeProjectAction fSearchScopeProjectAction;
	private SearchScopeWorkspaceAction fSearchScopeWorkspaceAction;
	private SelectWorkingSetAction fSelectWorkingSetAction;

	public SearchScopeActionGroup(CallHierarchyViewPart view, IDialogSettings dialogSettings) {
		this.fView= view;
		this.fDialogSettings= dialogSettings;
		createActions();
	}

	/**
	 * Returns the current search scope.
	 * 
	 * @param includeMask the include mask
	 * @return the current search scope
	 * @since 3.7
	 */
	public IJavaSearchScope getSearchScope(int includeMask) {
		if (fSelectedAction != null) {
			return fSelectedAction.getSearchScope(includeMask);
		}

		return null;
	}

	@Override
	public void fillActionBars(IActionBars actionBars) {
		super.fillActionBars(actionBars);
		fillContextMenu(actionBars.getMenuManager());
	}

	protected void setActiveWorkingSets(IWorkingSet[] sets) {
		if (sets != null) {
			fSelectedWorkingSetNames = getWorkingSetNames(sets);
			fSelectedAction = new SearchScopeWorkingSetAction(this, sets, getScopeDescription(sets));
			fSelectedAction.run();
		} else {
			fSelectedWorkingSetNames = null;
			fSelectedAction = null;
		}
	}

	private String[] getWorkingSetNames(IWorkingSet[] sets) {
		String[] result= new String[sets.length];
		for (int i = 0; i < sets.length; i++) {
			result[i]= sets[i].getName();
		}
		return result;
	}

	protected IWorkingSet[] getActiveWorkingSets() {
		if (fSelectedWorkingSetNames != null) {
			return getWorkingSets(fSelectedWorkingSetNames);
		}

		return null;
	}

	private IWorkingSet[] getWorkingSets(String[] workingSetNames) {
		if (workingSetNames == null) {
			return null;
		}
		Set<IWorkingSet> workingSets= new HashSet<IWorkingSet>(2);
		for (int j= 0; j < workingSetNames.length; j++) {
			IWorkingSet workingSet= getWorkingSetManager().getWorkingSet(workingSetNames[j]);
			if (workingSet != null) {
				workingSets.add(workingSet);
			}
		}

		return workingSets.toArray(new IWorkingSet[workingSets.size()]);
	}

	/**
	 * Sets the new search scope type.
	 *
	 * @param newSelection New action which should be the checked one (can be null iff <code>ignoreUnchecked == false</code>)
	 * @param ignoreUnchecked Ignores actions which are unchecked (necessary since both the old and the new action fires).
	 */
	protected void setSelected(SearchScopeAction newSelection, boolean ignoreUnchecked) {
		if (!ignoreUnchecked || newSelection.isChecked()) {
			if (newSelection instanceof SearchScopeWorkingSetAction) {
				fSelectedWorkingSetNames = getWorkingSetNames(((SearchScopeWorkingSetAction) newSelection).getWorkingSets());
			} else {
				fSelectedWorkingSetNames = null;
			}

			if (newSelection != null) {
				fSelectedAction= newSelection;
			} else {
				fSelectedAction= fSearchScopeWorkspaceAction;
			}

			fDialogSettings.put(DIALOGSTORE_SCOPE_TYPE, getSearchScopeType());
			fDialogSettings.put(DIALOGSTORE_SELECTED_WORKING_SET, fSelectedWorkingSetNames);
		}
	}

	protected CallHierarchyViewPart getView() {
		return fView;
	}

	protected IWorkingSetManager getWorkingSetManager() {
		IWorkingSetManager workingSetManager = PlatformUI.getWorkbench()
		.getWorkingSetManager();

		return workingSetManager;
	}

	protected void fillSearchActions(IMenuManager javaSearchMM) {
		Action[] actions = getActions();

		for (int i = 0; i < actions.length; i++) {
			Action action = actions[i];

			if (action.isEnabled()) {
				javaSearchMM.add(action);
			}
		}

		javaSearchMM.setVisible(!javaSearchMM.isEmpty());
	}

	@Override
	public void fillContextMenu(IMenuManager menu) {
		MenuManager javaSearchMM = new MenuManager(CallHierarchyMessages.SearchScopeActionGroup_searchScope,
				IContextMenuConstants.GROUP_SEARCH);
		javaSearchMM.setRemoveAllWhenShown(true);

		javaSearchMM.addMenuListener(new IMenuListener() {
			/* (non-Javadoc)
			 * @see org.eclipse.jface.action.IMenuListener#menuAboutToShow(org.eclipse.jface.action.IMenuManager)
			 */
			public void menuAboutToShow(IMenuManager manager) {
				fillSearchActions(manager);
			}
		});

		fillSearchActions(javaSearchMM);
		menu.appendToGroup(IContextMenuConstants.GROUP_SEARCH, javaSearchMM);
	}

	private Action[] getActions() {
		List<Action> actions = new ArrayList<Action>(SearchUtil.LRU_WORKINGSET_LIST_SIZE + 4);
		addAction(actions, fSearchScopeWorkspaceAction);
		addAction(actions, fSearchScopeProjectAction);
		addAction(actions, fSelectWorkingSetAction);

		Iterator<IWorkingSet[]> iter= SearchUtil.getLRUWorkingSets().sortedIterator();
		while (iter.hasNext()) {
			IWorkingSet[] workingSets= iter.next();
			String description = SearchUtil.toString(workingSets);
			SearchScopeWorkingSetAction workingSetAction = new SearchScopeWorkingSetAction(this, workingSets, description);

			if (isSelectedWorkingSet(workingSets)) {
				workingSetAction.setChecked(true);
			}

			actions.add(workingSetAction);
		}

		Action[] result = actions.toArray(new Action[actions.size()]);

		ensureExactlyOneCheckedAction(result);
		return result;
	}

	private void ensureExactlyOneCheckedAction(Action[] result) {
		int checked = getCheckedActionCount(result);
		if (checked != 1) {
			if (checked > 1) {
				for (int i = 0; i < result.length; i++) {
					Action action = result[i];
					action.setChecked(false);
				}
			}
			fSearchScopeWorkspaceAction.setChecked(true);
		}
	}

	private int getCheckedActionCount(Action[] result) {
		// Ensure that exactly one action is selected
		int checked= 0;
		for (int i = 0; i < result.length; i++) {
			Action action = result[i];
			if (action.isChecked()) {
				checked++;
			}
		}
		return checked;
	}

	private void addAction(List<Action> actions, Action action) {
		if (action == fSelectedAction) {
			action.setChecked(true);
		} else {
			action.setChecked(false);
		}

		actions.add(action);
	}

	private void createActions() {
		fSearchScopeWorkspaceAction = new SearchScopeWorkspaceAction(this);
		fSelectWorkingSetAction = new SelectWorkingSetAction(this);
		fSearchScopeProjectAction = new SearchScopeProjectAction(this);

		int searchScopeType;
		try {
			searchScopeType= fDialogSettings.getInt(DIALOGSTORE_SCOPE_TYPE);
		} catch (NumberFormatException e) {
			searchScopeType= SEARCH_SCOPE_TYPE_WORKSPACE;
		}
		String[] workingSetNames= fDialogSettings.getArray(DIALOGSTORE_SELECTED_WORKING_SET);
		setSelected(getSearchScopeAction(searchScopeType, workingSetNames), false);
	}

	public void saveState(IMemento memento) {
		int type= getSearchScopeType();
		memento.putInteger(TAG_SEARCH_SCOPE_TYPE, type);
		if (type == SEARCH_SCOPE_TYPE_WORKING_SET) {
			memento.putInteger(TAG_WORKING_SET_COUNT, fSelectedWorkingSetNames.length);
			for (int i = 0; i < fSelectedWorkingSetNames.length; i++) {
				String workingSetName = fSelectedWorkingSetNames[i];
				memento.putString(TAG_SELECTED_WORKING_SET+i, workingSetName);
			}
		}
	}

	public void restoreState(IMemento memento) {
		String[] workingSetNames= null;
		Integer scopeType= memento.getInteger(TAG_SEARCH_SCOPE_TYPE);
		if (scopeType != null) {
			if (scopeType.intValue() == SEARCH_SCOPE_TYPE_WORKING_SET) {
				Integer workingSetCount= memento.getInteger(TAG_WORKING_SET_COUNT);
				if (workingSetCount != null) {
					workingSetNames = new String[workingSetCount.intValue()];
					for (int i = 0; i < workingSetCount.intValue(); i++) {
						workingSetNames[i]= memento.getString(TAG_SELECTED_WORKING_SET+i);
					}
				}
			}
			setSelected(getSearchScopeAction(scopeType.intValue(), workingSetNames), false);
		}
	}

	private SearchScopeAction getSearchScopeAction(int searchScopeType, String[] workingSetNames) {
		switch (searchScopeType) {
			case SEARCH_SCOPE_TYPE_WORKSPACE:
				return fSearchScopeWorkspaceAction;
			case SEARCH_SCOPE_TYPE_PROJECT:
				return fSearchScopeProjectAction;
			case SEARCH_SCOPE_TYPE_WORKING_SET:
				IWorkingSet[] workingSets= getWorkingSets(workingSetNames);
				if (workingSets != null && workingSets.length > 0) {
					return new SearchScopeWorkingSetAction(this, workingSets, getScopeDescription(workingSets));
				}
				return null;
		}
		return null;
	}

	private int getSearchScopeType() {
		if (fSelectedAction != null) {
			return fSelectedAction.getSearchScopeType();
		}
		return 0;
	}

	private String getScopeDescription(IWorkingSet[] workingSets) {
		return Messages.format(CallHierarchyMessages.WorkingSetScope, new String[] {SearchUtil.toString(workingSets)});
	}

	/**
	 * Determines whether the specified working sets correspond to the currently selected working
	 * sets.
	 *
	 * @param workingSets the array of working sets
	 * @return <code>true</code> if the specified working sets correspond to the currently selected
	 *         working sets
	 */
	private boolean isSelectedWorkingSet(IWorkingSet[] workingSets) {
		if (fSelectedWorkingSetNames != null && fSelectedWorkingSetNames.length == workingSets.length) {
			Set<String> workingSetNames= new HashSet<String>(workingSets.length);
			for (int i = 0; i < workingSets.length; i++) {
				workingSetNames.add(workingSets[i].getName());
			}
			for (int i = 0; i < fSelectedWorkingSetNames.length; i++) {
				if (!workingSetNames.contains(fSelectedWorkingSetNames[i])) {
					return false;
				}
			}
			return true;
		}
		return false;
	}

	/**
	 * Fetches the full description of the scope with the appropriate include mask.
	 * 
	 * @param includeMask the include mask
	 * @return the description of the scope with the appropriate include mask
	 * @since 3.7
	 */
	public String getFullDescription(int includeMask) {
		if (fSelectedAction != null)
			return fSelectedAction.getFullDescription(includeMask);
		return null;
	}
}

