/*******************************************************************************
 * Copyright (c) 2009, 2013 Oracle. All rights reserved.
 * 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/.
 *
 * Contributors:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.common.ui.internal.prefs;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.IncrementalProjectBuilder;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jdt.internal.ui.preferences.PropertyAndPreferencePage;
import org.eclipse.jdt.internal.ui.preferences.ScrolledPageContent;
import org.eclipse.jface.dialogs.IDialogSettings;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.layout.PixelConverter;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jpt.common.core.internal.utility.WorkspaceRunnableAdapter;
import org.eclipse.jpt.common.core.utility.ValidationMessage;
import org.eclipse.jpt.common.ui.JptCommonUiMessages;
import org.eclipse.jpt.common.ui.internal.JptUIPlugin;
import org.eclipse.jpt.common.ui.internal.jface.RunnableWithProgressAdapter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.forms.events.ExpansionAdapter;
import org.eclipse.ui.forms.events.ExpansionEvent;
import org.eclipse.ui.forms.widgets.ExpandableComposite;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;

/**
 * Abstract problem severities page that supports
 * workspace- and project-level severities.
 */
@SuppressWarnings("restriction")
public abstract class JptProblemSeveritiesPage
	extends PropertyAndPreferencePage
{
	/**
	 * Changed severities are stored in this map and either committed
	 * (e.g. when the user presses the 'OK' button) or discarded
	 * (e.g. when the user presses the 'Cancel' button).<ul>
	 * <li> key = preference key (which is the
	 * {@link ValidationMessage#getID() validation message ID})
	 * <li> value = preference severity level (which is the
	 *   {@link IMessage#getSeverity() validation message severity}):<ul>
	 *   <li>{@link IMessage#HIGH_SEVERITY}
	 *   <li>{@link IMessage#NORMAL_SEVERITY}
	 *   <li>{@link IMessage#LOW_SEVERITY}
	 *   <li>{@link ValidationMessage#IGNORE_SEVERITY}
	 *   </ul>
	 * </ul>
	 */
	private final HashMap<String, Integer> changedSeverities = new HashMap<String, Integer>();

	/**
	 * Cache the {@link Combo}s so we can revert the settings.
	 */
	private final ArrayList<Combo> combos = new ArrayList<Combo>();

	/**
	 * Cache the {@link ExpandableComposite}s so we can save
	 * and restore the page's expansion state.
	 */
	private final ArrayList<ExpandableComposite> expandablePanes = new ArrayList<ExpandableComposite>();

	/**
	 * The key used to store and retrieve a combo's validation message.
	 * @see org.eclipse.swt.widgets.Widget#getData(String)
	 */
	/* CU private */ static final String VALIDATION_MESSAGE = ValidationMessage.class.getName();

	/**
	 * The scrollable pane used to show the content of this page.
	 */
	private ScrolledPageContent mainComposite;

	/**
	 * The possible choices which describes the severity of a single problem.
	 */
	private final PreferenceSeverity[] preferenceSeverities;
	private final String[] severityDisplayStrings;

	private Boolean hasProjectSpecificPreferences = null;

	/**
	 * Constant used to store the expansion state of each expandable pane.
	 */
	public static final String SETTINGS_EXPANDED = "expanded"; //$NON-NLS-1$

	/**
	 * The preference key used to retrieve the dialog settings where the expansion
	 * states have been stored.
	 */
	public static final String SETTINGS_SECTION_NAME = "JpaProblemSeveritiesPage"; //$NON-NLS-1$


	public JptProblemSeveritiesPage() {
		super();
		this.preferenceSeverities = this.buildPreferenceSeverities();
		this.severityDisplayStrings = this.buildSeverityDisplayStrings();
	}

	@Override
	protected IPreferenceStore doGetPreferenceStore() {
		return this.getUIPlugin().getPreferenceStore();
	}

	protected abstract JptUIPlugin getUIPlugin();

	protected PreferenceSeverity[] buildPreferenceSeverities() {
		return DEFAULT_PREFERENCE_SEVERITIES;
	}

	protected static final PreferenceSeverity[] DEFAULT_PREFERENCE_SEVERITIES = buildDefaultPreferenceSeverities();
	protected static PreferenceSeverity[] buildDefaultPreferenceSeverities() {
		ArrayList<PreferenceSeverity> severities = new ArrayList<PreferenceSeverity>();
		severities.add(new PreferenceSeverity(IMessage.HIGH_SEVERITY, JptCommonUiMessages.PROBLEM_SEVERITIES_PAGE__ERROR));
		severities.add(new PreferenceSeverity(IMessage.NORMAL_SEVERITY, JptCommonUiMessages.PROBLEM_SEVERITIES_PAGE__WARNING));
		severities.add(new PreferenceSeverity(IMessage.LOW_SEVERITY, JptCommonUiMessages.PROBLEM_SEVERITIES_PAGE__INFO));
		severities.add(new PreferenceSeverity(ValidationMessage.IGNORE_SEVERITY, JptCommonUiMessages.PROBLEM_SEVERITIES_PAGE__IGNORE));
		return severities.toArray(new PreferenceSeverity[severities.size()]);
	}

	/**
	 * Pair a preference value with its localized display string
	 * (e.g. <code>"error"</code> and <code>"Error"</code>).
	 */
	public static class PreferenceSeverity {
		public final int preferenceValue;
		public final String displayString;
		public PreferenceSeverity(int preferenceValue, String displayString) {
			super();
			this.preferenceValue = preferenceValue;
			this.displayString = displayString;
		}
	}

	/**
	 * Pre-condition: {@link #preferenceSeverities} is already built.
	 */
	protected String[] buildSeverityDisplayStrings() {
		int len = this.preferenceSeverities.length;
		String[] displayStrings = new String[len];
		for (int i = 0; i < len; i++) {
			displayStrings[i] = this.preferenceSeverities[i].displayString;
		}
		return displayStrings;
	}

	@Override
	protected Control createPreferenceContent(Composite parent) {
		PixelConverter pixelConverter = new PixelConverter(parent);
		// create a container because the caller will set the GridData and we need
		// to change the heightHint of the first child and we also need to set the
		// font otherwise the layout won't be calculated correctly
		Composite container = new Composite(parent, SWT.NONE);
		container.setFont(parent.getFont());
		GridLayout layout = new GridLayout(1, false);
		layout.marginHeight = 0;
		layout.marginWidth  = 0;
		container.setLayout(layout);

		// the page's main composite
		this.mainComposite = new ScrolledPageContent(container);

		GridData gridData = new GridData(GridData.FILL, GridData.FILL, true, true);
		gridData.heightHint = pixelConverter.convertHeightInCharsToPixels(20);
		this.mainComposite.setLayoutData(gridData);

		parent = this.mainComposite.getBody();
		parent.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true));
		layout = new GridLayout(1, false);
		layout.marginHeight = 0;
		layout.marginWidth  = 0;
		parent.setLayout(layout);

		this.addCombos(parent);

		this.restoreSectionExpansionStates();

		return container;
	}

	protected abstract void addCombos(Composite parent);

	protected void restoreSectionExpansionStates() {
		IDialogSettings settings = this.getDialogPreferences();
		for (int index = this.expandablePanes.size(); index-- > 0; ) {
			ExpandableComposite expandablePane = this.expandablePanes.get(index);
			if (settings == null) {
				expandablePane.setExpanded(index == 0);  // only expand the first node by default
			} else {
				expandablePane.setExpanded(settings.getBoolean(SETTINGS_EXPANDED + index));
			}
		}
	}

	@Override
	public Point computeSize() {
		return this.doComputeSize();
	}

	protected Composite addExpandableSection(Composite parent, String text) {
		return this.addExpandableSection(parent, text, new GridData(GridData.FILL, GridData.FILL, true, false));
	}

	protected Composite addSubExpandableSection(Composite parent, String text) {
		return this.addExpandableSection(parent, text, new GridData(GridData.FILL, GridData.FILL, true, false, 2, 1));
	}

	/**
	 * Creates and adds to the given <code>Composite</code> an expandable pane
	 * where its content can be shown or hidden depending on the expansion state.
	 *
	 * @param parent The parent container
	 * @param text The title of the expandable section
	 * @return The container to which widgets can be added, which is a child of
	 * the expandable pane
	 */
	private Composite addExpandableSection(Composite parent, String text, GridData gridData) {
		int expansionStype = ExpandableComposite.TWISTIE | ExpandableComposite.CLIENT_INDENT;
		ExpandableComposite expandablePane = new ExpandableComposite(parent, SWT.NONE, expansionStype);

		expandablePane.setText(text);
		expandablePane.setFont(JFaceResources.getFontRegistry().getBold(JFaceResources.DIALOG_FONT));
		expandablePane.setLayoutData(gridData);
		expandablePane.addExpansionListener(this.buildExpansionListener());

		this.mainComposite.adaptChild(expandablePane);
		this.expandablePanes.add(expandablePane);

		parent = new Composite(expandablePane, SWT.NONE);
		parent.setLayout(new GridLayout(2, false));
		expandablePane.setClient(parent);

		return parent;
	}

	private ExpansionAdapter buildExpansionListener() {
		return new ExpansionListener();
	}

	/* CU private */ class ExpansionListener
		extends ExpansionAdapter
	{
		@Override
		public void expansionStateChanged(ExpansionEvent e) {
			JptProblemSeveritiesPage.this.expansionStateChanged();
		}
	}

	/**
	 * Revalidates the layout in order to show or hide the vertical scroll bar
	 * after a section was either expanded or collapsed. This unfortunately does
	 * not happen automatically.
	 */
	protected void expansionStateChanged() {
		this.mainComposite.reflow(true);
	}

	/**
	 * Creates and adds to the given parent a labeled combo where the possible
	 * choices are "Ignore", "Error" and "Warning".
	 *
	 * @param parent The parent to which the widgets are added
	 * @param validationMessage The corresponding validation message
	 */
	protected void addLabeledCombo(Composite parent, ValidationMessage validationMessage) {
		Label label = new Label(parent, SWT.NONE);
		label.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));
		label.setText(validationMessage.getDescription() + ':');

		Combo combo = new Combo(parent, SWT.READ_ONLY);
		combo.setItems(this.severityDisplayStrings);
		combo.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_FILL));
		combo.setData(VALIDATION_MESSAGE, validationMessage);
		combo.select(this.getInitialComboIndex(validationMessage));
		combo.addSelectionListener(this.buildComboSelectionListener());

		this.mainComposite.adaptChild(combo);
		this.combos.add(combo);
	}

	/**
	 * Return the combo index corresponding to the specified validation message's
	 * current preference value.
	 * <p>
	 * Only called during initialization.
	 */
	protected int getInitialComboIndex(ValidationMessage validationMessage) {
		return this.convertPreferenceValueToComboIndex(this.getPreferenceValue(validationMessage));
	}

	/**
	 * Return the current preference value for the specified validation message.
	 * <p>
	 * Only called during initialization.
	 */
	protected int getPreferenceValue(ValidationMessage validationMessage) {
		int prefValue = this.getPreferenceValue_(validationMessage);
		return (prefValue != ValidationMessage.UNSET_SEVERITY_PREFERENCE) ? prefValue : validationMessage.getDefaultSeverity();
	}

	protected int getPreferenceValue_(ValidationMessage validationMessage) {
		String prefKey = validationMessage.getID();
		// useProjectSettings() won't work here since the page is still being initialized
		return (this.isProjectPreferencePage() && this.hasProjectSpecificOptions(this.getProject())) ?
				this.getValidationMessageSeverityPreference(this.getProject(), prefKey) :
				this.getValidationMessageSeverityPreference(prefKey);
	}

	protected int convertPreferenceValueToComboIndex(int prefValue) {
		for (int i = 0; i < this.preferenceSeverities.length; i++) {
			if (prefValue == this.preferenceSeverities[i].preferenceValue) {
				return i;
			}
		}
		throw new IllegalArgumentException("unknown preference value: " + prefValue); //$NON-NLS-1$
	}

	private SelectionListener buildComboSelectionListener() {
		return new ComboSelectionListener();
	}

	/* CU private */ class ComboSelectionListener
		extends SelectionAdapter
	{
		@Override
		public void widgetSelected(SelectionEvent e) {
			JptProblemSeveritiesPage.this.comboSelected((Combo) e.widget);
		}
	}

	protected void comboSelected(Combo combo) {
		ValidationMessage msg = (ValidationMessage) combo.getData(VALIDATION_MESSAGE);
		String prefKey = msg.getID();
		int prefValue = this.preferenceSeverities[combo.getSelectionIndex()].preferenceValue;
		this.changedSeverities.put(prefKey, Integer.valueOf(prefValue));
	}

	@Override
	protected boolean hasProjectSpecificOptions(IProject project) {
		return this.getWorkspaceValidationPreferencesOverridden(project);
	}

	/**
	 * For a project properties page, the superclass implementation calls
	 * {@link #enableProjectSpecificSettings(boolean)}, with an argument of
	 * <code>false</code>; so we need handle only the workspace preferences
	 * page case here.
	 */
	@Override
	protected void performDefaults() {
		if ( ! this.isProjectPreferencePage()) {
			this.revertWorkspaceToDefaultPreferences();
		}
		super.performDefaults();
	}

	/**
	 * This is called only when the page is a workspace preferences page.
	 */
	protected void revertWorkspaceToDefaultPreferences() {
		for (Combo combo : this.combos) {
			this.revertWorkspaceToDefaultPreference(combo);
		}
	}

	/**
	 * This is called only when the page is a workspace preferences page.
	 */
	protected void revertWorkspaceToDefaultPreference(Combo combo) {
		ValidationMessage validationMessage = (ValidationMessage) combo.getData(VALIDATION_MESSAGE);
		String prefKey = validationMessage.getID();
		int prefValue = validationMessage.getDefaultSeverity();
		combo.select(this.convertPreferenceValueToComboIndex(prefValue));
		// force the workspace-level preference to be removed
		this.changedSeverities.put(prefKey, Integer.valueOf(ValidationMessage.UNSET_SEVERITY_PREFERENCE));
	}

	/**
	 * This is called only when the page is a project properties page.
	 */
	@Override
	protected void enableProjectSpecificSettings(boolean useProjectSpecificSettings) {
		super.enableProjectSpecificSettings(useProjectSpecificSettings);
		if (this.getDefaultsButton() == null) {
			//@Hack("If the defaults button is null the control is currently being built," +
			//      "otherwise the 'enable project specific settings' checkbox is being pressed")
			return;
		}

		this.hasProjectSpecificPreferences = Boolean.valueOf(useProjectSpecificSettings);

		if (useProjectSpecificSettings){
			this.copyCurrentPreferencesToProject();
		} else {
			this.revertProjectPreferences();
		}
	}

	/**
	 * Copy <em>all</em> the current settings to the project-level settings.
	 * This locks down all the settings; otherwise future changes to the
	 * workspace-level settings would affect any project-level settings
	 * that were not copied over.
	 * <p>
	 * This is called only when the page is a project properties page.
	 */
	protected void copyCurrentPreferencesToProject() {
		for (Combo combo : this.combos) {
			this.copyCurrentPreferenceToProject(combo);
		}
	}

	/**
	 * This is called only when the page is a project properties page.
	 */
	protected void copyCurrentPreferenceToProject(Combo combo) {
		ValidationMessage validationMessage = (ValidationMessage) combo.getData(VALIDATION_MESSAGE);
		String prefKey = validationMessage.getID();
		int prefValue = this.getValidationMessageSeverityPreference(prefKey);
		if (prefValue == ValidationMessage.UNSET_SEVERITY_PREFERENCE) {
			prefValue = validationMessage.getDefaultSeverity();
		}
		combo.select(this.convertPreferenceValueToComboIndex(prefValue));
		// combo does not fire a selection event when set programmatically...
		this.changedSeverities.put(prefKey, Integer.valueOf(prefValue));
	}

	/**
	 * This is called only when the page is a project properties page.
	 */
	protected void revertProjectPreferences() {
		for (Combo combo : this.combos) {
			this.revertProjectPreference(combo);
		}
	}

	/**
	 * This is called only when the page is a project properties page.
	 */
	protected void revertProjectPreference(Combo combo) {
		ValidationMessage validationMessage = (ValidationMessage) combo.getData(VALIDATION_MESSAGE);
		String prefKey = validationMessage.getID();
		int prefValue = this.getValidationMessageSeverityPreference(prefKey);
		if (prefValue == ValidationMessage.UNSET_SEVERITY_PREFERENCE) {
			prefValue = validationMessage.getDefaultSeverity();
		}
		combo.select(this.convertPreferenceValueToComboIndex(prefValue));
		// force the project-level preference to be removed
		this.changedSeverities.put(prefKey, Integer.valueOf(ValidationMessage.UNSET_SEVERITY_PREFERENCE));
	}

	@Override
	protected void noDefaultAndApplyButton() {
		throw new IllegalStateException("Don't call this, see enableProjectSpecificSettings for the hack that looks for the defaultsButton being null"); //$NON-NLS-1$
	}


	// ********** plug-in preferences **********

	protected abstract int getValidationMessageSeverityPreference(IProject project, String prefKey);

	protected abstract int getValidationMessageSeverityPreference(String prefKey);

	protected abstract boolean getWorkspaceValidationPreferencesOverridden(IProject project);

	protected abstract void setWorkspaceValidationPreferencesOverridden(IProject project, boolean value);

	protected abstract void setValidationMessageSeverityPreference(String prefKey, int value);

	protected abstract void setValidationMessageSeverityPreference(IProject project, String prefKey, int value);


	// ********** OK/Revert/Apply behavior **********

	@Override
	public boolean performOk() {
		super.performOk();
		if (this.hasProjectSpecificPreferences != null) {
			this.setWorkspaceValidationPreferencesOverridden(this.getProject(), this.hasProjectSpecificPreferences.booleanValue());
		}
		for (Map.Entry<String, Integer> entry : this.changedSeverities.entrySet()) {
			this.setProblemSeverityPreference(entry.getKey(), entry.getValue().intValue());
		}
		try {
			// true=fork; false=uncancellable
			this.buildOKDialog().run(true, false, this.buildOKRunnable());
		} catch (InterruptedException ex) {
			// should *not* happen...
			Thread.currentThread().interrupt();
			return false;
		} catch (InvocationTargetException ex) {
			throw new RuntimeException(ex.getTargetException());
		}

		return true;
	}

	protected void setProblemSeverityPreference(String prefKey, int value) {
		if (this.isProjectPreferencePage()) {
			this.setValidationMessageSeverityPreference(this.getProject(), prefKey, value);
		} else {
			this.setValidationMessageSeverityPreference(prefKey, value);
		}
	}

	private IRunnableContext buildOKDialog() {
		return new ProgressMonitorDialog(this.getShell());
	}

	private IRunnableWithProgress buildOKRunnable() {
		return new OKRunnable();
	}

	/* CU private */ class OKRunnable
		extends RunnableWithProgressAdapter
	{
		@Override
		public void run(IProgressMonitor monitor) throws InvocationTargetException {
			try {
				this.run_(monitor);
			} catch (CoreException ex) {
				throw new InvocationTargetException(ex);
			}
		}
		/**
		 * {@link #performOk_(IProgressMonitor)} triggers a build that locks the
		 * workspace root, so we need to use the workspace root as our
		 * scheduling rule here
		 */
		private void run_(IProgressMonitor monitor) throws CoreException {
			IWorkspace ws = ResourcesPlugin.getWorkspace();
			ws.run(
					JptProblemSeveritiesPage.this.buildOkWorkspaceRunnable(),
					ws.getRoot(),
					IWorkspace.AVOID_UPDATE,
					monitor
				);
		}
	}

	IWorkspaceRunnable buildOkWorkspaceRunnable() {
		return new OKWorkspaceRunnable();
	}

	/* CU private */ class OKWorkspaceRunnable
		extends WorkspaceRunnableAdapter
	{
		@Override
		public void run(IProgressMonitor monitor) throws CoreException {
			JptProblemSeveritiesPage.this.performOk_(monitor);
		}
	}

	void performOk_(IProgressMonitor monitor) throws CoreException {
		int buildKind = IncrementalProjectBuilder.FULL_BUILD;
		IProject project = this.getProject();
		if (project != null) {
			// project preference page
			project.build(buildKind, monitor);
		} else {
			// workspace preference page
			ResourcesPlugin.getWorkspace().build(buildKind, monitor);
		}
	}

	@Override
	public void dispose() {
		this.storeSectionExpansionStates(this.getDialogPreferences());
		super.dispose();
	}

	protected IDialogSettings getDialogPreferences() {
		return this.getUIPlugin().getDialogSettings(SETTINGS_SECTION_NAME);
	}

	protected void storeSectionExpansionStates(IDialogSettings settings) {
		for (int index = this.expandablePanes.size(); index-- > 0; ) {
			ExpandableComposite expandablePane = this.expandablePanes.get(index);
			settings.put(SETTINGS_EXPANDED + index, expandablePane.isExpanded());
		}
	}

}
