/*******************************************************************************
 * Copyright (c) 2000, 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
 *
 *******************************************************************************/
package org.eclipse.dltk.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.dltk.core.IDLTKLanguageToolkit;
import org.eclipse.dltk.core.search.IDLTKSearchScope;
import org.eclipse.dltk.internal.corext.util.Messages;
import org.eclipse.dltk.ui.IContextMenuConstants;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
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;

public abstract 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 SearchScopeHierarchyAction fSearchScopeHierarchyAction;
	private SearchScopeProjectAction fSearchScopeProjectAction;
	private SearchScopeWorkspaceAction fSearchScopeWorkspaceAction;
	private SelectWorkingSetAction fSelectWorkingSetAction;

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

	/**
	 * @return IJavaSearchScope
	 */
	public IDLTKSearchScope getSearchScope() {
		if (fSelectedAction != null) {
			return fSelectedAction.getSearchScope();
		}

		return null;
	}

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

	protected abstract IDLTKLanguageToolkit getLangaugeToolkit();

	protected void setActiveWorkingSets(IWorkingSet[] sets) {
		if (sets != null) {
			fSelectedWorkingSetNames = getWorkingSetNames(sets);
			fSelectedAction = new SearchScopeWorkingSetAction(this, sets,
					getScopeDescription(sets));
		} 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<>(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
	 * @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) {
		menu.add(new Separator(IContextMenuConstants.GROUP_SEARCH));

		MenuManager javaSearchMM = new MenuManager(
				CallHierarchyMessages.SearchScopeActionGroup_searchScope,
				IContextMenuConstants.GROUP_SEARCH);
		javaSearchMM.setRemoveAllWhenShown(true);

		javaSearchMM.addMenuListener(manager -> fillSearchActions(manager));

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

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

		Iterator iter = SearchUtil.getLRUWorkingSets().sortedIterator();
		while (iter.hasNext()) {
			IWorkingSet[] workingSets = (IWorkingSet[]) 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 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);
		fSearchScopeHierarchyAction = new SearchScopeHierarchyAction(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_HIERARCHY:
			return fSearchScopeHierarchyAction;
		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
	 * @return Returns true 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<>(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;
	}

	public String getFullDescription() {
		if (fSelectedAction != null)
			return fSelectedAction.getFullDescription();
		return null;
	}
}
