/*******************************************************************************
 * 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
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.test.internal.performance.results.ui;

import java.io.File;
import java.util.Iterator;

import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.DirectoryDialog;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Text;
import org.eclipse.test.internal.performance.PerformanceTestPlugin;
import org.eclipse.test.internal.performance.results.db.DB_Results;
import org.eclipse.test.internal.performance.results.utils.IPerformancesConstants;
import org.eclipse.test.performance.ui.UiPlugin;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPreferencePage;
import org.osgi.service.prefs.BackingStoreException;

/**
 * Defines the 'Performances' preferences page.
 */
public class PerformanceResultsPreferencePage extends PreferencePage
	implements IWorkbenchPreferencePage, SelectionListener, ModifyListener, IPerformancesConstants {

	private Button mVersionRadioButton;
	private Button dVersionRadionButton;
	private CCombo databaseLocationCombo;
	private Button dbConnectionCheckBox;
	private Button dbLocalBrowseButton;
	private Button dbRelengRadioButton;
	private Button dbLocalRadioButton;
	private CCombo defaultDimensionCombo;
//	private CCombo lastBuildCombo;
	private List resultsDimensionsList;
	private Label dbLocationLabel;

	// Status SWT objects
	private Button statusValuesCheckBox;
	private Button statusErrorNoneRadioButton;
	private Button statusErrorNoticeableRadioButton;
	private Button statusErrorSuspiciousRadioButton;
	private Button statusErrorWeirdRadioButton;
	private Button statusErrorInvalidRadioButton;
	private Button statusSmallBuildValueCheckBox;
	private Button statusSmallDeltaValueCheckBox;
	private Button statusStatisticNoneRadioButton;
	private Button statusStatisticErraticRadioButton;
	private Button statusStatisticUnstableRadioButton;
	private Text statusBuildsToConfirm;
	private Text comparisonThresholdFailure;
	private Text comparisonThresholdError;
	private Text comparisonThresholdImprovement;

	// TODO See whether config descriptors need to be set as preferences or not...
	// private Table configDescriptorsTable;

	private BuildsView buildsView;

/**
 * Utility method that creates a push button instance and sets the default
 * layout data.
 *
 * @param parent
 *            the parent for the new button
 * @param label
 *            the label for the new button
 * @return the newly-created button
 */
private Button createCheckBox(Composite parent, String label) {
	Button button = new Button(parent, SWT.CHECK);
	button.setText(label);
	button.addSelectionListener(this);
	GridData data = new GridData();
	data.horizontalAlignment = GridData.FILL;
	data.horizontalSpan = 5;
	button.setLayoutData(data);
	return button;
}

/**
 * Create a text field specific for this application
 *
 * @param parent
 *            the parent of the new text field
 * @return the new text field
 */
private CCombo createCombo(Composite parent) {
	CCombo combo= new CCombo(parent, SWT.BORDER);
	combo.addModifyListener(this);
	GridData data = new GridData();
	data.horizontalSpan = 3;
	data.horizontalAlignment = GridData.FILL;
	data.grabExcessHorizontalSpace = true;
	data.verticalAlignment = GridData.CENTER;
	data.grabExcessVerticalSpace = false;
	combo.setLayoutData(data);
	return combo;
}


/**
 * Creates composite control and sets the default layout data.
 *
 * @param parent
 *            the parent of the new composite
 * @param numColumns
 *            the number of columns for the new composite
 * @param hSpan TODO
 * @return the newly-created coposite
 */
private Composite createComposite(Composite parent, int numColumns, int hSpan) {
	Composite composite = new Composite(parent, SWT.NULL);

	// GridLayout
	GridLayout layout = new GridLayout();
	layout.numColumns = numColumns;
	composite.setLayout(layout);

	// GridData
	GridData data = new GridData();
	data.verticalAlignment = GridData.FILL;
	data.horizontalAlignment = GridData.FILL;
	data.horizontalSpan = hSpan;
	composite.setLayoutData(data);
	return composite;
}

@Override
protected Control createContents(Composite parent) {

	this.buildsView = (BuildsView) PerformancesView.getWorkbenchView("org.eclipse.test.internal.performance.results.ui.BuildsView");
	if (this.buildsView == null) {
		Label errorLabel = createLabel(parent, "No performances preferences can be set because the build view has not been created yet!", false);
		errorLabel.setForeground(Display.getDefault().getSystemColor(SWT.COLOR_RED));
	} else {
		// Eclipse version choice
		Composite composite_eclipseVersion = createComposite(parent, 5, 1);
		createLabel(composite_eclipseVersion, "Eclipse version", false);
		Composite composite_versionChoice = createComposite(composite_eclipseVersion, 5, 1);
		this.mVersionRadioButton = createRadioButton(composite_versionChoice, "v"+ECLIPSE_MAINTENANCE_VERSION);
		this.dVersionRadionButton = createRadioButton(composite_versionChoice, "v"+ECLIPSE_DEVELOPMENT_VERSION);

		// Database location
		Composite compositeDatabase = createComposite(parent, 5, 1);
		Group databaseGroup = createGroup(compositeDatabase, "Database", 5);
		Composite compositeDatabaseConnection = createComposite(databaseGroup, 3, 5);
		this.dbConnectionCheckBox = createCheckBox(compositeDatabaseConnection, "Connected");
		this.dbRelengRadioButton = createRadioButton(compositeDatabaseConnection, "Releng");
		this.dbLocalRadioButton = createRadioButton(compositeDatabaseConnection, "Local");
		this.dbLocationLabel = createLabel(databaseGroup, "Location", false);
		this.databaseLocationCombo = createCombo(databaseGroup);
		this.databaseLocationCombo.setEditable(false);
	    this.dbLocalBrowseButton = createPushButton(databaseGroup, "Browse");

		// Status
		Composite compositeStatus = createComposite(parent, 1, 3);
		Group statusGroup = createGroup(compositeStatus, "Status", 1);
		this.statusValuesCheckBox = createCheckBox(statusGroup, "Values");
		this.statusValuesCheckBox.setToolTipText("Include numbers while writing status");
		Group statusErrorGroup = createGroup(statusGroup, "Error level", 5);
		statusErrorGroup.setToolTipText("Exclude from the written status failures depending on their build result error...");
		this.statusErrorNoneRadioButton = createRadioButton(statusErrorGroup, "None");
		this.statusErrorNoneRadioButton.setToolTipText("Do not exclude failures if they have a noticeable error");
		this.statusErrorInvalidRadioButton = createRadioButton(statusErrorGroup, "Invalid");
		this.statusErrorInvalidRadioButton.setToolTipText("Exclude all invalid failures (i.e. result error is over 100%)");
		this.statusErrorWeirdRadioButton = createRadioButton(statusErrorGroup, "Weird");
		this.statusErrorWeirdRadioButton.setToolTipText("Exclude all weird failures (i.e. result error is over 50%)");
		this.statusErrorSuspiciousRadioButton = createRadioButton(statusErrorGroup, "Suspicious");
		this.statusErrorSuspiciousRadioButton.setToolTipText("Exclude all suspicious failures (i.e. result error is over 25%)");
		this.statusErrorNoticeableRadioButton = createRadioButton(statusErrorGroup, "Noticeable");
		this.statusErrorNoticeableRadioButton.setToolTipText("Exclude all failures which have a noticeable error (i.e result error is over 3%)");
		Group statusSmallGroup = createGroup(statusGroup, "Small value", 5);
		statusErrorGroup.setToolTipText("Exclude from the written status failures depending on their value");
		this.statusSmallBuildValueCheckBox = createCheckBox(statusSmallGroup, "Build value");
		this.statusSmallBuildValueCheckBox.setToolTipText("Exclude all failures which have a build result value smaller than 100ms");
		this.statusSmallDeltaValueCheckBox = createCheckBox(statusSmallGroup, "Delta value");
		this.statusSmallDeltaValueCheckBox.setToolTipText("Exclude all failures which have a delta result value smaller than 100ms");
		Group statusStatisticsGroup = createGroup(statusGroup, "Statistics", 5);
		statusStatisticsGroup.setToolTipText("Exclude from the written status failures depending on build results statistics...");
		this.statusStatisticNoneRadioButton = createRadioButton(statusStatisticsGroup, "None");
		this.statusStatisticNoneRadioButton.setToolTipText("Do not exclude failures which have bad baseline results statistics (i.e. variation is over 10%)");
		this.statusStatisticUnstableRadioButton = createRadioButton(statusStatisticsGroup, "Unstable");
		this.statusStatisticUnstableRadioButton.setToolTipText("Exclude all failures which have unstable baseline results statistics (i.e. variation is between 10% and 20%)");
		this.statusStatisticErraticRadioButton = createRadioButton(statusStatisticsGroup, "Erratic");
		this.statusStatisticErraticRadioButton.setToolTipText("Exclude all failures which have erratic baseline results statistics (i.e. variation is over 20%)");
		createLabel(statusGroup, "Builds to confirm:", false);
		this.statusBuildsToConfirm = createTextField(statusGroup);
		this.statusBuildsToConfirm.setToolTipText("The number of previous builds to take into account to confirm a regression");

		// Comparison
		Composite compositeComparison = createComposite(parent, 1, 3);
		Group comparisonGroup = createGroup(compositeComparison, "Comparison", 1);
		Group thresholdsGroup = createGroup(comparisonGroup, "Thresholds", 6);
//		Composite compositeFailureThreshold = createComposite(comparisonGroup, 2, 2);
		createLabel(thresholdsGroup, "Failure:", false);
		this.comparisonThresholdFailure = createTextField(thresholdsGroup);
		this.comparisonThresholdFailure.setToolTipText("The threshold in percentage to report a failure");
		createLabel(thresholdsGroup, "Error:", false);
		this.comparisonThresholdError = createTextField(thresholdsGroup);
		this.comparisonThresholdError.setToolTipText("The threshold in percentage to report an error");
		createLabel(thresholdsGroup, "Improvement:", false);
		this.comparisonThresholdImprovement = createTextField(thresholdsGroup);
		this.comparisonThresholdImprovement.setToolTipText("The threshold in percentage to report an improvement");

		// Default dimension layout
		StringBuilder tooltip = new StringBuilder("Select the default dimension which will be used for performance results\n");
		tooltip.append("When changed, the new selected dimension is automatically added to the dimensions list below...");
		String tooltipText = tooltip.toString();
		Composite compositeDefaultDimension = createComposite(parent, 3, 1);
		createLabel(compositeDefaultDimension, "Default dimension: ", false);
		this.defaultDimensionCombo = createCombo(compositeDefaultDimension);
		this.defaultDimensionCombo.setEditable(false);
		this.defaultDimensionCombo.setToolTipText(tooltipText);

		// Results dimensions layout
		tooltip = new StringBuilder("Select the dimensions which will be used while generating performance results\n");
		tooltip.append("When changed, the default dimension above is automatically added to the new list...");
		tooltipText = tooltip.toString();
		Composite compositeResultsDimensions = createComposite(parent, 3, 1);
		createLabel(compositeResultsDimensions, "Results dimensions: ", true/*beginning*/);
		this.resultsDimensionsList = createList(compositeResultsDimensions);
		this.resultsDimensionsList.setToolTipText(tooltipText);

		// Config descriptors layout
		/* TODO See whether config descriptors need to be set as preferences or not...
		Composite compositeConfigDescriptors = createComposite(parent, 3);
		createLabel(compositeConfigDescriptors, "Config descriptors: ", false);
		this.configDescriptorsTable = createTable(compositeConfigDescriptors);
		TableColumn firstColumn = new TableColumn(this.configDescriptorsTable, SWT.LEFT);
		firstColumn.setText ("Name");
		firstColumn.setWidth(50);
		TableColumn secondColumn = new TableColumn(this.configDescriptorsTable, SWT.FILL | SWT.LEFT);
		secondColumn.setText ("Description");
		secondColumn.setWidth(300);
		*/

		// init values
		initializeValues();
	}

	// font = null;
	Composite contents = new Composite(parent, SWT.NULL);
	contents.pack(true);
	return contents;
}

/**
 * Utility method that creates a label instance and sets the default layout
 * data.
 *
 * @param parent
 *            the parent for the new label
 * @param text
 *            the text for the new label
 * @return the new label
 */
private Group createGroup(Composite parent, String text, int columns) {
	Group group = new Group(parent, SWT.NONE);
	group.setLayout(new GridLayout(columns, false));
	group.setText(text);
	GridData data = new GridData(SWT.FILL, SWT.FILL, true, true);
//	data.horizontalSpan = 1;
	group.setLayoutData(data);
	return group;
}

/**
 * Utility method that creates a label instance and sets the default layout
 * data.
 *
 * @param parent
 *            the parent for the new label
 * @param text
 *            the text for the new label
 * @param beginning TODO
 * @return the new label
 */
private Label createLabel(Composite parent, String text, boolean beginning) {
	Label label = new Label(parent, SWT.BEGINNING|SWT.LEFT);
	label.setText(text);
	GridData data = new GridData();
	data.horizontalAlignment = GridData.FILL;
	data.verticalAlignment = beginning ? GridData.BEGINNING : GridData.CENTER;
	label.setLayoutData(data);
	return label;
}

/**
 * Create a text field specific for this application
 *
 * @param parent
 *            the parent of the new text field
 * @return the new text field
 */
private List createList(Composite parent) {
	List list = new List(parent, SWT.MULTI | SWT.BORDER);
	list.addSelectionListener(this);
	GridData data = new GridData();
	data.horizontalSpan = 2;
	data.horizontalAlignment = GridData.FILL;
	data.grabExcessHorizontalSpace = true;
	data.verticalAlignment = GridData.CENTER;
	data.grabExcessVerticalSpace = false;
	list.setLayoutData(data);
	return list;
}

/**
 * Utility method that creates a push button instance and sets the default
 * layout data.
 *
 * @param parent
 *            the parent for the new button
 * @param label
 *            the label for the new button
 * @return the newly-created button
 */
private Button createPushButton(Composite parent, String label) {
	Button button = new Button(parent, SWT.PUSH);
	button.setText(label);
	button.addSelectionListener(this);
	GridData data = new GridData();
	data.horizontalAlignment = SWT.LEFT;
	data.grabExcessHorizontalSpace = true;
//	data.horizontalSpan = 2;
	data.minimumWidth = 100;
	button.setLayoutData(data);
	return button;
}

/**
 * Utility method that creates a radio button instance and sets the default
 * layout data.
 *
 * @param parent
 *            the parent for the new button
 * @param label
 *            the label for the new button
 * @return the newly-created button
 */
private Button createRadioButton(Composite parent, String label) {
	Button button = new Button(parent, SWT.RADIO | SWT.LEFT);
	button.setText(label);
	button.addSelectionListener(this);
	GridData data = new GridData();
	button.setLayoutData(data);
	return button;
}

/*
 * Create a text field specific for this application
 *
 * @param parent
 *            the parent of the new text field
 * @return the new text field
 *
private Table createTable(Composite parent) {
	Table table = new Table(parent, SWT.BORDER);
	table.setLinesVisible (true);
	table.setHeaderVisible (true);
	GridData gridData = new GridData(SWT.FILL, SWT.FILL, true, true, 3, 1);
	gridData.heightHint = 150;
	table.setLayoutData(gridData);
	return table;
}
*/

/*
 * Create a text field specific for this application
 *
 * @param parent
 *            the parent of the new text field
 * @return the new text field
 */
private Text createTextField(Composite parent) {
	Text text = new Text(parent, SWT.SINGLE | SWT.BORDER);
	text.addModifyListener(this);
	GridData data = new GridData();
	data.horizontalAlignment = GridData.FILL;
	data.grabExcessHorizontalSpace = true;
	data.verticalAlignment = GridData.CENTER;
	data.grabExcessVerticalSpace = false;
	text.setLayoutData(data);
	return text;
}

/**
 * The <code>ReadmePreferencePage</code> implementation of this
 * <code>PreferencePage</code> method returns preference store that belongs to
 * the our plugin. This is important because we want to store our preferences
 * separately from the workbench.
 */
@Override
protected IPreferenceStore doGetPreferenceStore() {
	return UiPlugin.getDefault().getPreferenceStore();
}

String getDialogTitle() {
	String title = DB_Results.getDbTitle();
	if (title == null) {
		// DB is not connected
		int version;
		if (this.mVersionRadioButton.getSelection()) {
			version = ECLIPSE_MAINTENANCE_VERSION;
		} else {
			version = ECLIPSE_DEVELOPMENT_VERSION;
		}
		title = "Eclipse " + version + " - DB not connected";
	}
	return title;
}

/*
 * Get the directory path using the given location as default.
 */
private String getDirectoryPath(String location) {
	DirectoryDialog dialog = new DirectoryDialog(getShell(), SWT.OPEN);
	dialog.setText(getDialogTitle());
	dialog.setMessage("Select local database directory:");
	dialog.setFilterPath(location);
	String path = dialog.open();
	if (path != null) {
		File dir = new File(path);
		if (dir.exists() && dir.isDirectory()) {
			return dir.getAbsolutePath();
		}
	}
	return null;
}

@Override
public void init(IWorkbench workbench) {
	// do nothing
}

/*
 * Init he contents of the dimensions list controls.
 */
void initDimensionsLists() {
	// Dimensions lists
	java.util.List<String> dimensions = PerformanceTestPlugin.getDimensions();
	Iterator<String> names = dimensions.iterator();
	while (names.hasNext()) {
		String name = names.next();
		this.defaultDimensionCombo.add(name);
		this.resultsDimensionsList.add(name);
	}
}

/**
 * Initializes states of the controls using default values in the preference
 * store.
 */
private void initializeDefaults() {
	IPreferenceStore store = getPreferenceStore();

	// Init default database values
	this.dbConnectionCheckBox.setSelection(store.getDefaultBoolean(PRE_DATABASE_CONNECTION));
	this.dbRelengRadioButton.setSelection(false);
	this.dbLocalRadioButton.setSelection(false);
	final boolean dbLocal = store.getDefaultBoolean(PRE_DATABASE_LOCAL);
	if (dbLocal) {
		this.dbLocalRadioButton.setSelection(true);
	} else {
		this.dbRelengRadioButton.setSelection(true);
	}
	this.databaseLocationCombo.removeAll();
	this.databaseLocationCombo.setText(store.getDefaultString(PRE_DATABASE_LOCATION));
	updateDatabaseGroup();

	// Init default status values
	int writeStatus = store.getDefaultInt(PRE_WRITE_STATUS);
	initStatusValues(writeStatus);

	// Init comparison thresholds
	this.comparisonThresholdFailure.setText(String.valueOf(store.getDefaultInt(PRE_COMPARISON_THRESHOLD_FAILURE)));
	this.comparisonThresholdError.setText(String.valueOf(store.getDefaultInt(PRE_COMPARISON_THRESHOLD_ERROR)));
	this.comparisonThresholdImprovement.setText(String.valueOf(store.getDefaultInt(PRE_COMPARISON_THRESHOLD_IMPROVEMENT)));

	// Init eclipse version
	this.mVersionRadioButton.setSelection(false);
	this.dVersionRadionButton.setSelection(false);
	int version = store.getDefaultInt(PRE_ECLIPSE_VERSION);
	if (version == ECLIPSE_MAINTENANCE_VERSION) {
		this.mVersionRadioButton.setSelection(true);
	} else {
		this.dVersionRadionButton.setSelection(true);
	}
    updateBrowseButtonToolTip(version);

	// Init default default dimension
	String defaultDimension = store.getDefaultString(PRE_DEFAULT_DIMENSION);
	this.defaultDimensionCombo.setText(defaultDimension);

	// Init default generated dimensions
	this.resultsDimensionsList.add(store.getDefaultString(PRE_RESULTS_DIMENSION+".0"));
	this.resultsDimensionsList.add(store.getDefaultString(PRE_RESULTS_DIMENSION+".1"));
}

/**
 * Initializes states of the controls from the preference store.
 */
private void initializeValues() {
	IPreferenceStore store = getPreferenceStore();

	// Init database info
	this.dbConnectionCheckBox.setSelection(store.getBoolean(PRE_DATABASE_CONNECTION));
	final boolean dbLocal = store.getBoolean(PRE_DATABASE_LOCAL);
	if (dbLocal) {
		this.dbLocalRadioButton.setSelection(true);
		this.dbRelengRadioButton.setToolTipText("");
	} else {
		this.dbRelengRadioButton.setSelection(true);
		this.dbRelengRadioButton.setToolTipText(NETWORK_DATABASE_LOCATION);
	}
	this.databaseLocationCombo.removeAll();
	this.databaseLocationCombo.setText(store.getString(PRE_DATABASE_LOCATION));
	for (int i = 0; i < 3; i++) {
		String history = store.getString(PRE_DATABASE_LOCATION + "." + i);
		if (history.length() == 0)
			break;
		this.databaseLocationCombo.add(history);
	}
	updateDatabaseGroup();

	// Init status values
	int writeStatus = store.getInt(PRE_WRITE_STATUS);
	initStatusValues(writeStatus);

	// Init comparison thresholds
	this.comparisonThresholdFailure.setText(String.valueOf(store.getInt(PRE_COMPARISON_THRESHOLD_FAILURE)));
	this.comparisonThresholdError.setText(String.valueOf(store.getInt(PRE_COMPARISON_THRESHOLD_ERROR)));
	this.comparisonThresholdImprovement.setText(String.valueOf(store.getInt(PRE_COMPARISON_THRESHOLD_IMPROVEMENT)));

	// Init eclipse version
	int version = store.getInt(PRE_ECLIPSE_VERSION);
	if (version == ECLIPSE_MAINTENANCE_VERSION) {
		this.mVersionRadioButton.setSelection(true);
	} else {
		this.dVersionRadionButton.setSelection(true);
	}
    updateBrowseButtonToolTip(version);

	// Init composite lists
	initDimensionsLists();

	// Init default dimension
	String defaultDimension = store.getString(PRE_DEFAULT_DIMENSION);
	this.defaultDimensionCombo.setText(defaultDimension);

	// Init generated dimensions
	int count = this.resultsDimensionsList.getItemCount();
	int[] indices = new int[count];
	int n = 0;
	String resultsDimension = store.getString(PRE_RESULTS_DIMENSION + "." + n);
	while (resultsDimension.length() > 0) {
		indices[n++] = this.resultsDimensionsList.indexOf(resultsDimension);
		resultsDimension = store.getString(PRE_RESULTS_DIMENSION + "." + n);
	}
	if (n < count) {
		System.arraycopy(indices, 0, indices = new int[n], 0, n);
	}
	this.resultsDimensionsList.select(indices);

	// Init config descriptors
	/* TODO See whether config descriptors need to be set as preferences or not...
	this.configDescriptorsTable.clearAll();
	int d = 0;
	String descriptorName = store.getString(PRE_CONFIG_DESCRIPTOR_NAME + "." + d);
	String descriptorDescription = store.getString(PRE_CONFIG_DESCRIPTOR_DESCRIPTION + "." + d++);
	while (descriptorName.length() > 0) {
		TableItem tableItem = new TableItem (this.configDescriptorsTable, SWT.NONE);
		tableItem.setText (0, descriptorName);
		tableItem.setText (1, descriptorDescription);
		descriptorName = store.getString(PRE_CONFIG_DESCRIPTOR_NAME + "." + d);
		descriptorDescription = store.getString(PRE_CONFIG_DESCRIPTOR_DESCRIPTION + "." + d++);
	}
	*/
}

private void initStatusValues(int writeStatus) {
	this.statusValuesCheckBox.setSelection((writeStatus & STATUS_VALUES) != 0);
	this.statusErrorNoneRadioButton.setSelection(false);
	this.statusErrorNoticeableRadioButton.setSelection(false);
	this.statusErrorSuspiciousRadioButton.setSelection(false);
	this.statusErrorWeirdRadioButton.setSelection(false);
	this.statusErrorInvalidRadioButton.setSelection(false);
	switch (writeStatus & STATUS_ERROR_LEVEL_MASK) {
		case STATUS_ERROR_NONE:
			this.statusErrorNoneRadioButton.setSelection(true);
			break;
		case STATUS_ERROR_NOTICEABLE:
			this.statusErrorNoticeableRadioButton.setSelection(true);
			break;
		case STATUS_ERROR_SUSPICIOUS:
			this.statusErrorSuspiciousRadioButton.setSelection(true);
			break;
		case STATUS_ERROR_WEIRD:
			this.statusErrorWeirdRadioButton.setSelection(true);
			break;
		case STATUS_ERROR_INVALID:
			this.statusErrorInvalidRadioButton.setSelection(true);
			break;
	}
	this.statusSmallBuildValueCheckBox.setSelection(false);
	this.statusSmallDeltaValueCheckBox.setSelection(false);
	switch (writeStatus & STATUS_SMALL_VALUE_MASK) {
		case STATUS_SMALL_VALUE_BUILD:
			this.statusSmallBuildValueCheckBox.setSelection(true);
			break;
		case STATUS_SMALL_VALUE_DELTA:
			this.statusSmallDeltaValueCheckBox.setSelection(true);
			break;
	}
	this.statusStatisticNoneRadioButton.setSelection(false);
	this.statusStatisticErraticRadioButton.setSelection(false);
	this.statusStatisticUnstableRadioButton.setSelection(false);
	switch (writeStatus & STATUS_STATISTICS_MASK) {
		case 0:
			this.statusStatisticNoneRadioButton.setSelection(true);
			break;
		case STATUS_STATISTICS_ERRATIC:
			this.statusStatisticErraticRadioButton.setSelection(true);
			break;
		case STATUS_STATISTICS_UNSTABLE:
			this.statusStatisticUnstableRadioButton.setSelection(true);
			break;
	}
	this.statusBuildsToConfirm.setText(String.valueOf(writeStatus & STATUS_BUILDS_NUMBER_MASK));
}

@Override
public void modifyText(ModifyEvent event) {

	// Add default dimension to results if necessary
	if (event.getSource() == this.defaultDimensionCombo) {
		String[] resultsDimensions = this.resultsDimensionsList.getSelection();
		int length = resultsDimensions.length;
		String defaultDimension = this.defaultDimensionCombo.getText();
		for (int i = 0; i < length; i++) {
			if (resultsDimensions[i].equals(defaultDimension)) {
				// Default dim is already set as a results dimension, hence nothing has to be done
				return;
			}
		}
		System.arraycopy(resultsDimensions, 0, resultsDimensions = new String[length + 1], 0, length);
		resultsDimensions[length] = defaultDimension;
		this.resultsDimensionsList.setSelection(resultsDimensions);
	}

	// Verify the 'builds to confirm' number
	if (event.getSource() == this.statusBuildsToConfirm) {
		try {
			int number = Integer.parseInt(this.statusBuildsToConfirm.getText());
			if (number < 0) {
				this.statusBuildsToConfirm.setText("0");
			} else {
				int buildsNumber = DB_Results.getBuildsNumber();
				if (number > buildsNumber) {
					this.statusBuildsToConfirm.setText(String.valueOf(buildsNumber));
				}
			}
		}
		catch (NumberFormatException nfe) {
			this.statusBuildsToConfirm.setText("1");
		}
	}
}


/**
 * @param milestone
 */
void openMilestoneErrorMessage(String milestone) {
	MessageDialog.openError(getShell(), getDialogTitle(), milestone+" is an invalid milestone date. Only 'yyyymmddHHMM' format is accepted!");
}

@Override
protected void performDefaults() {
	super.performDefaults();
	initializeDefaults();
}

@Override
public boolean performOk() {
	final boolean hasBuildsView = this.buildsView != null;
	if (hasBuildsView) {
		storeValues();
		try {
			IEclipsePreferences preferences = InstanceScope.INSTANCE.getNode(PLUGIN_ID);
			preferences.flush();
			this.buildsView.resetView();
		} catch (BackingStoreException e) {
			e.printStackTrace();
			return false;
		}
	}
	return true;
}

/**
 * Stores the values of the controls back to the preference store.
 */
private void storeValues() {
	IPreferenceStore store = getPreferenceStore();

	// Set version
	int version;
	if (this.mVersionRadioButton.getSelection()) {
		version = ECLIPSE_MAINTENANCE_VERSION;
	} else {
		version = ECLIPSE_DEVELOPMENT_VERSION;
	}
	store.setValue(PRE_ECLIPSE_VERSION, version);

	// Set database values
	store.setValue(PRE_DATABASE_CONNECTION, this.dbConnectionCheckBox.getSelection());
	final boolean dbLocal = this.dbLocalRadioButton.getSelection();
	store.setValue(PRE_DATABASE_LOCAL, dbLocal);
	String location = this.databaseLocationCombo.getText();
	if (dbLocal) {
		store.setValue(PRE_DATABASE_LOCATION, location);
	} else {
		store.setValue(PRE_DATABASE_LOCATION, NETWORK_DATABASE_LOCATION);
	}
	int count = this.databaseLocationCombo.getItemCount();
	for (int i=0; i<count; i++) {
		String item = this.databaseLocationCombo.getItem(i);
		if (item.equals(location)) {
			this.databaseLocationCombo.remove(i);
			break;
		}
	}
	if (dbLocal) {
		this.databaseLocationCombo.add(location, 0);
	}
	int i=0;
	for (; i<count; i++) {
		String item = this.databaseLocationCombo.getItem(i);
		if (item.length() == 0) break;
		store.setValue(PRE_DATABASE_LOCATION+"."+i, item);
	}
	while (store.getString(PRE_DATABASE_LOCATION+"."+i).length() > 0) {
		store.setToDefault(PRE_DATABASE_LOCATION+"."+i);
		i++;
	}

	// Set status values
	int writeStatus = 0;
	if (this.statusValuesCheckBox.getSelection()) {
		writeStatus |= STATUS_VALUES;
	}
	if (this.statusErrorNoneRadioButton.getSelection()) {
		writeStatus |= STATUS_ERROR_NONE;
	} else if (this.statusErrorNoticeableRadioButton.getSelection()) {
		writeStatus |= STATUS_ERROR_NOTICEABLE;
	} else if (this.statusErrorSuspiciousRadioButton.getSelection()) {
		writeStatus |= STATUS_ERROR_SUSPICIOUS;
	} else if (this.statusErrorWeirdRadioButton.getSelection()) {
		writeStatus |= STATUS_ERROR_WEIRD;
	} else if (this.statusErrorInvalidRadioButton.getSelection()) {
		writeStatus |= STATUS_ERROR_INVALID;
	}
	if (this.statusSmallBuildValueCheckBox.getSelection()) {
		writeStatus |= STATUS_SMALL_VALUE_BUILD;
	}
	if (this.statusSmallDeltaValueCheckBox.getSelection()) {
		writeStatus |= STATUS_SMALL_VALUE_DELTA;
	}
	if (this.statusStatisticNoneRadioButton.getSelection()) {
		writeStatus &= ~STATUS_STATISTICS_MASK;
	} else if (this.statusStatisticErraticRadioButton.getSelection()) {
		writeStatus |= STATUS_STATISTICS_ERRATIC;
	} else if (this.statusStatisticUnstableRadioButton.getSelection()) {
		writeStatus |= STATUS_STATISTICS_UNSTABLE;
	}
	writeStatus += Integer.parseInt(this.statusBuildsToConfirm.getText());
	store.setValue(PRE_WRITE_STATUS, writeStatus);

	// Init comparison thresholds
	store.setValue(PRE_COMPARISON_THRESHOLD_FAILURE, Integer.parseInt(this.comparisonThresholdFailure.getText()));
	store.setValue(PRE_COMPARISON_THRESHOLD_ERROR, Integer.parseInt(this.comparisonThresholdError.getText()));
	store.setValue(PRE_COMPARISON_THRESHOLD_IMPROVEMENT, Integer.parseInt(this.comparisonThresholdImprovement.getText()));

	// Set milestones
	String prefix = PRE_MILESTONE_BUILDS + "." + version;

	// Unset previous additional milestones
	String milestone = store.getString(prefix + count);
	while (milestone != null && milestone.length() > 0) {
		store.putValue(prefix + count++, "");
		milestone = store.getString(prefix + count);
	}

	// Set default dimension
	String defaultDimension = this.defaultDimensionCombo.getText();
	store.putValue(PRE_DEFAULT_DIMENSION, defaultDimension);
	DB_Results.setDefaultDimension(defaultDimension);

	// Set generated dimensions
	int[] indices = this.resultsDimensionsList.getSelectionIndices();
	int length = indices.length;
	String[] dimensions = new String[length];
	if (length > 0) {
		for (i = 0; i < indices.length; i++) {
			dimensions[i] = this.resultsDimensionsList.getItem(indices[i]);
			store.putValue(PRE_RESULTS_DIMENSION + "." + i, dimensions[i]);
		}
	}
	int currentLength = DB_Results.getResultsDimensions().length;
	if (currentLength > length) {
		for (i = currentLength - 1; i >= length; i--) {
			store.putValue(PRE_RESULTS_DIMENSION + "." + i, ""); // reset extra dimensions
		}
	}
	DB_Results.setResultsDimensions(dimensions);

}

@Override
public void widgetDefaultSelected(SelectionEvent event) {
}

@Override
public void widgetSelected(SelectionEvent event) {

	// As for directory when 'Local' button is pushed
	final Object source = event.getSource();
	if (source == this.dbLocalBrowseButton) {
		String location = this.databaseLocationCombo.getText();
		String path = getDirectoryPath(location);
		if (path != null) {
			// First verify that the selected dir was correct
			int version;
			if (this.mVersionRadioButton.getSelection()) {
				version = ECLIPSE_MAINTENANCE_VERSION;
			} else {
				version = ECLIPSE_DEVELOPMENT_VERSION;
			}
			File dbDir = new File(path, "perfDb"+version);
			if (!dbDir.exists() || !dbDir.isDirectory()) {
				StringBuilder message = new StringBuilder("Invalid performance database directory\n");
				message.append(path+" should contain 'perfDb");
				message.append(version);
				message.append("' directory and none was found!");
				MessageDialog.openError(getShell(), getDialogTitle(), message.toString());
				return;
			}

			// Look for selected dir in combo box list
			int count = this.databaseLocationCombo.getItemCount();
			int index = -1;
			for (int i = 0; i < count; i++) {
				String item = this.databaseLocationCombo.getItem(i);
				if (item.length() == 0) { // nothing in the combo-box list
					break;
				}
				if (item.equals(path)) {
					index = i;
					break;
				}
			}
			// Set the selected dir the more recent in the previous dirs list
			if (index !=  0) {
				if (index > 0) {
					// the dir was used before, but not recently => remove it from previous dirs list
					this.databaseLocationCombo.remove(index);
				}
				// add the selected dir on the top of the previous dirs list
				this.databaseLocationCombo.add(path, 0);
			}
			// Set combo box text
			this.databaseLocationCombo.setText(path);
			updateLocalDb();
		}
	}

	// Reset dabase location when 'Releng' button is pushed
	if (source == this.dbConnectionCheckBox) {
		updateDatabaseGroup();
	}

	// Reset dabase location when 'Releng' check-box is checked
	if (source == this.dbLocalRadioButton) {
		updateLocalDb();
	}

	// Add default dimension to results if necessary
	if (source == this.resultsDimensionsList) {
		String[] resultsDimensions = this.resultsDimensionsList.getSelection();
		int length = resultsDimensions.length;
		String defaultDimension = this.defaultDimensionCombo.getText();
		for (int i = 0; i < length; i++) {
			if (resultsDimensions[i].equals(defaultDimension)) {
				// Default dim is already set as a results dimension, hence nothing has to be done
				return;
			}
		}
		System.arraycopy(resultsDimensions, 0, resultsDimensions = new String[length + 1], 0, length);
		resultsDimensions[length] = defaultDimension;
		this.resultsDimensionsList.setSelection(resultsDimensions);
	}

//	if (source == this.lastBuildCheckBox) {
//		this.lastBuildCombo.setEnabled(this.lastBuildCheckBox.getSelection());
//	}

	if (source == this.mVersionRadioButton) {
		if (this.mVersionRadioButton.getSelection()) {
		    updateBrowseButtonToolTip(ECLIPSE_MAINTENANCE_VERSION);
		}
	}

	if (source == this.dVersionRadionButton) {
		if (this.dVersionRadionButton.getSelection()) {
		    updateBrowseButtonToolTip(ECLIPSE_DEVELOPMENT_VERSION);
		}
	}
}

/*
 * Update browse tooltip
 */
void updateBrowseButtonToolTip(int version) {
	this.dbLocalBrowseButton.setToolTipText("Select the directory where the database was unzipped\n(i.e. should contain the perfDb"+version+" subdirectory)");
}

/*
 * Update database group controls.
 */
void updateDatabaseGroup() {
	if (this.dbConnectionCheckBox.getSelection()) {
		this.dbRelengRadioButton.setEnabled(true);
		this.dbLocalRadioButton.setEnabled(true);
		updateLocalDb();
	} else {
		this.dbRelengRadioButton.setEnabled(false);
		this.dbLocalRadioButton.setEnabled(false);
		this.databaseLocationCombo.setEnabled(false);
		this.dbLocalBrowseButton.setEnabled(false);
		setValid(true);
	}
}

/*
 * Update database location controls.
 */
void updateLocalDb() {
	if (this.dbLocalRadioButton.getSelection()) {
		this.databaseLocationCombo.setEnabled(true);
		this.dbLocalBrowseButton.setEnabled(true);
		if (this.databaseLocationCombo.getItemCount() == 0) {
			this.databaseLocationCombo.setText("");
			setValid(false);
		} else {
			this.databaseLocationCombo.select(0);
			setValid(true);
		}
		this.dbRelengRadioButton.setToolTipText("");
		this.dbLocationLabel.setEnabled(true);
	} else {
		this.dbRelengRadioButton.setToolTipText(NETWORK_DATABASE_LOCATION);
		this.databaseLocationCombo.setText("");
		this.databaseLocationCombo.setEnabled(false);
		this.dbLocalBrowseButton.setEnabled(false);
		setValid(true);
		this.dbLocationLabel.setEnabled(false);
	}
}

}
