//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 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 implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.common.serviceability;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.epf.common.plugin.AbstractPlugin;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;


/**
 * A message dialog used for displaying error, warning, confirmation or
 * informational messages.
 * 
 * @author Kelvin Low
 * @since 1.0
 */
public class MsgDialog {

	// The plug-in instance.
	private AbstractPlugin plugin;

	// The plug-in ID.
	private String pluginId;

	// The plug-in logger.
	private Logger logger;

	/**
	 * Create a new instance given the plug-in instance.
	 * 
	 * @param plugin
	 *            The plugin instance.
	 */
	public MsgDialog(AbstractPlugin plugin) {
		this.plugin = plugin;
		this.pluginId = plugin.getId();
		this.logger = plugin.getLogger();
	}

	/**
	 * Displays the given error message in an error dialog without the error
	 * reason and Details button.
	 * <p>
	 * Note: The error message will be written to the log file.
	 * 
	 * @param title
	 *            The title for the error dialog.
	 * @param msg
	 *            The error message.
	 */
	public void displayError(String title, String msg) {
		display(IStatus.ERROR, title, msg, null, null, null);
	}

	/**
	 * Displays the given error message in an error dialog without the error
	 * reason and Details button.
	 * <p>
	 * Note: The error message and the exception stack trace will be written to
	 * the log file.
	 * 
	 * @param title
	 *            The title for the error dialog.
	 * @param msg
	 *            The error message.
	 * @param ex
	 *            The exception associated with the error.
	 */
	public void displayError(String title, String msg, Throwable ex) {
		display(IStatus.ERROR, title, msg, null, null, ex);
	}

	/**
	 * Displays the given error message in an error dialog without the Details
	 * button.
	 * <p>
	 * Note: The error message will be written to the log file.
	 * 
	 * @param title
	 *            The title for the error dialog.
	 * @param msg
	 *            The error message.
	 * @param reason
	 *            The reason for the error.
	 */
	public void displayError(String title, String msg, String reason) {
		display(IStatus.ERROR, title, msg, reason, null, null);
	}

	/**
	 * Displays the given error message in an error dialog without the Details
	 * button.
	 * <p>
	 * Note: The error message and the exception stack trace will be written to
	 * the log file.
	 * 
	 * @param title
	 *            The title for the error dialog.
	 * @param msg
	 *            The error message.
	 * @param reason
	 *            The reason for the error.
	 * @param ex
	 *            The exception associated with the error.
	 */
	public void displayError(String title, String msg, String reason,
			Throwable ex) {
		display(IStatus.ERROR, title, msg, reason, null, ex);
	}

	/**
	 * Displays the given error message in an error dialog. The Details button
	 * will be displayed if the <code>details</code> parameter it not null or
	 * empty.
	 * <p>
	 * Note: The error message will be written to the log file.
	 * 
	 * @param title
	 *            The title for the error dialog.
	 * @param msg
	 *            The error message.
	 * @param reason
	 *            The reason for the error.
	 * @param details
	 *            The error details.
	 */
	public void displayError(String title, String msg, String reason,
			String details) {
		display(IStatus.ERROR, title, msg, reason, details, null);
	}

	/**
	 * Displays the given error message in an error dialog. The Details button
	 * will be displayed if the <code>details</code> parameter it not null or
	 * empty.
	 * <p>
	 * Note: The error message and the exception stack trace will be written to
	 * the log file.
	 * 
	 * @param title
	 *            The title for the error dialog.
	 * @param msg
	 *            The error message.
	 * @param reason
	 *            The reason for the error.
	 * @param details
	 *            The error details.
	 * @param ex
	 *            The exception associated with the error.
	 */
	public void displayError(String title, String msg, String reason,
			String details, Throwable ex) {
		display(IStatus.ERROR, title, msg, reason, details, ex);
	}

	/**
	 * Displays the given error status in an error dialog.
	 * <p>
	 * Note: The error message and the exception stack trace will be written to
	 * the log file.
	 * 
	 * @param title
	 *            The title for the error dialog.
	 * @param status
	 *            The error status.
	 */
	public int displayError(String title, IStatus status) {
		return display(title, null, status);
	}

	/**
	 * Displays the given error status in an error dialog.
	 * <p>
	 * Note: The error message and the exception stack trace will be written to
	 * the log file.
	 * 
	 * @param title
	 *            The title for the error dialog.
	 * @param msg
	 *            The error message.
	 * @param status
	 *            The error status.
	 */
	public int displayError(String title, String msg, IStatus status) {
		return display(title, msg, status);
	}

	/**
	 * Displays the given warning message in a warning dialog without the
	 * warning reason and Details button.
	 * <p>
	 * Note: The waning message will be written to the log file.
	 * 
	 * @param title
	 *            The title for the warning dialog.
	 * @param msg
	 *            The warning message.
	 */
	public void displayWarning(String title, String msg) {
		display(IStatus.WARNING, title, msg, null, null, null);
	}

	/**
	 * Displays the given warning message in a warning dialog without the
	 * warning reason and Details button.
	 * <p>
	 * Note: The warning message and the exception stack trace will be written
	 * to the log file.
	 * 
	 * @param title
	 *            The title for the warning dialog.
	 * @param msg
	 *            The warning message.
	 * @param ex
	 *            The exception associated with the warning.
	 */
	public void displayWarning(String title, String msg, Throwable ex) {
		display(IStatus.WARNING, title, msg, null, null, ex);
	}

	/**
	 * Displays the given warning message in a warning dialog without the
	 * warning reason and Details button.
	 * <p>
	 * Note: The waning message will be written to the log file.
	 * 
	 * @param title
	 *            The title for the warning dialog.
	 * @param msg
	 *            The warning message.
	 * @param reason
	 *            The reason for the warning.
	 */
	public void displayWarning(String title, String msg, String reason) {
		display(IStatus.WARNING, title, msg, reason, null, null);
	}

	/**
	 * Displays the given warning message in a warning dialog without the
	 * warning reason and Details button.
	 * <p>
	 * Note: The warning message and the exception stack trace will be written
	 * to the log file.
	 * 
	 * @param title
	 *            The title for the warning dialog.
	 * @param msg
	 *            The warning message.
	 * @param reason
	 *            The reason for the warning.
	 * @param ex
	 *            The exception associated with the warning.
	 */
	public void displayWarning(String title, String msg, String reason,
			Throwable ex) {
		display(IStatus.WARNING, title, msg, reason, null, ex);
	}

	/**
	 * Displays the given warning message in a warning dialog. The Details
	 * button will be displayed if the <code>details</code> parameter it not
	 * null or empty.
	 * <p>
	 * Note: The waning message will be written to the log file.
	 * 
	 * @param title
	 *            The title for the error dialog.
	 * @param msg
	 *            The warning message.
	 * @param reason
	 *            The reason for the warning.
	 * @param details
	 *            The warning details.
	 */
	public void displayWarning(String title, String msg, String reason,
			String details) {
		display(IStatus.WARNING, title, msg, reason, details, null);
	}

	/**
	 * Displays the given warning message in a warning dialog. The Details
	 * button will be displayed if the <code>details</code> parameter it not
	 * null or empty.
	 * <p>
	 * Note: The warning message and the exception stack trace will be written
	 * to the log file.
	 * 
	 * @param title
	 *            The title for the error dialog.
	 * @param msg
	 *            The warning message.
	 * @param reason
	 *            The reason for the warning.
	 * @param details
	 *            The warning details.
	 * @param ex
	 *            The exception associated with the warning.
	 */
	public void displayWarning(String title, String msg, String reason,
			String details, Throwable ex) {
		display(IStatus.WARNING, title, msg, reason, details, ex);
	}

	/**
	 * Displays the given warning status in an error dialog.
	 * <p>
	 * Note: The warning message and the exception stack trace will be written
	 * to the log file.
	 * 
	 * @param title
	 *            The title for the error dialog.
	 * @param status
	 *            The error status.
	 */
	public void displayWarning(String title, IStatus status) {
		display(title, null, status);
	}

	/**
	 * Displays the given warning status in an error dialog.
	 * <p>
	 * Note: The warning message and the exception stack trace will be written
	 * to the log file.
	 * 
	 * @param title
	 *            The title for the error dialog.
	 * @param msg
	 *            The error message.
	 * @param status
	 *            The error status.
	 */
	public void displayWarning(String title, String msg, IStatus status) {
		display(title, msg, status);
	}

	/**
	 * Displays the given error or warning message in an error or warning
	 * dialog. The Details button will be displayed if the <code>details</code>
	 * parameter it not null or empty.
	 * 
	 * @param severity
	 *            The severity, either IStatus.ERROR or IStatus.WARNING.
	 * @param title
	 *            The title for the error dialog.
	 * @param msg
	 *            The error message.
	 * @param reason
	 *            The reason for the error.
	 * @param details
	 *            The error details.
	 * @param ex
	 *            The exception associated with the error.
	 */
	public synchronized void display(int severity, String title, String msg,
			String reason, String details, Throwable ex) {
		if (msg == null && ex != null) {
			msg = ex.getMessage();
		}

		if (msg == null) {
			msg = ""; //$NON-NLS-1$
		}

		if (severity == IStatus.ERROR || severity == IStatus.WARNING) {
			logger.logMsg(severity, msg, ex);
		} else {
			throw new IllegalArgumentException(
					"severity argument must be IStatus.ERROR or IStatus.WARNING"); //$NON-NLS-1$
		}

		Image oldImage = org.eclipse.jface.dialogs.ErrorDialog
				.getDefaultImage();
		Image shellImage = getShellImage();
		if (shellImage != null) {
			ErrorDialog.setDefaultImage(shellImage);
		}

		Shell shell = plugin.getWorkbench().getDisplay().getActiveShell();

		if (details != null && details.length() > 0) {
			MultiStatus mStatus = new MultiStatus(pluginId, IStatus.OK, reason,
					ex);
			Status status = new Status(severity, pluginId, IStatus.OK, details,
					ex);
			mStatus.add(status);
			org.eclipse.jface.dialogs.ErrorDialog.openError(shell, title, msg,
					mStatus);
		} else if (reason != null && reason.length() > 0) {
			Status status = new Status(severity, pluginId, IStatus.OK, reason,
					ex);
			org.eclipse.jface.dialogs.ErrorDialog.openError(shell, title, msg,
					status);
		} else {
			if (severity == IStatus.ERROR) {
				WrappedMessageDialog.openError(shell, title, msg);
			} else if (severity == IStatus.WARNING) {
				WrappedMessageDialog.openWarning(shell, title, msg);
			}
		}

		if (shellImage != null) {
			ErrorDialog.setDefaultImage(oldImage);
		}
	}

	/**
	 * Displays the given error or warning message in an error or warning
	 * dialog. The Details button will be displayed if the <code>details</code>
	 * parameter it not null or empty.
	 * 
	 * @param title
	 *            The title for the error dialog.
	 * @param status
	 *            The error status.
	 */
	public synchronized int display(String title, IStatus status) {
		return display(title, null, status);
	}

	/**
	 * Displays the given error or warning message in an error or warning
	 * dialog. The Details button will be displayed if the <code>details</code>
	 * parameter it not null or empty.
	 * 
	 * @param title
	 *            The title for the error dialog.
	 * @param msg
	 *            The error message.
	 * @param status
	 *            The error status.
	 */
	public synchronized int display(String title, String msg, IStatus status) {
		if (status == null) {
			throw new IllegalArgumentException("status argument cannot be null"); //$NON-NLS-1$
		}

		if (msg == null) {
			msg = status.getMessage();
		}
		if (msg == null) {
			msg = ""; //$NON-NLS-1$
		}

		int severity = status.getSeverity();
		if (severity == IStatus.ERROR || severity == IStatus.WARNING) {
			logger.logMsg(severity, msg, status.getException());
		}

		Image oldImage = org.eclipse.jface.dialogs.ErrorDialog
				.getDefaultImage();
		Image shellImage = getShellImage();
		if (shellImage != null) {
			ErrorDialog.setDefaultImage(shellImage);
		}

		Shell shell = plugin.getWorkbench().getDisplay().getActiveShell();

		int rc = org.eclipse.jface.dialogs.ErrorDialog.openError(shell, title,
				msg, status);

		if (shellImage != null) {
			ErrorDialog.setDefaultImage(oldImage);
		}

		return rc;
	}

	/**
	 * Displays the given message in a informational dialog with an "OK" button.
	 * 
	 * @param title
	 *            The title for the information dialog.
	 * @param msg
	 *            The message to display.
	 */
	public void displayInfo(String title, String msg) {
		if (msg == null) {
			msg = ""; //$NON-NLS-1$
		}

		Image oldImage = WrappedMessageDialog.getDefaultImage();
		Image shellImage = getShellImage();
		if (shellImage != null) {
			WrappedMessageDialog.setDefaultImage(shellImage);
		}

		Shell shell = plugin.getWorkbench().getDisplay().getActiveShell();
		WrappedMessageDialog.openInformation(shell, title, msg);

		if (shellImage != null) {
			WrappedMessageDialog.setDefaultImage(oldImage);
		}
	}

	/**
	 * Displays the given message in a question dialog with a "Yes" and "No"
	 * button.
	 * 
	 * @param title
	 *            The title for the information dialog.
	 * @param msg
	 *            The message to display.
	 */
	public boolean displayPrompt(String title, String msg) {
		if (msg == null) {
			msg = ""; //$NON-NLS-1$
		}

		Image oldImage = WrappedMessageDialog.getDefaultImage();
		Image shellImage = getShellImage();
		if (shellImage != null) {
			WrappedMessageDialog.setDefaultImage(shellImage);
		}

		Shell shell = plugin.getWorkbench().getDisplay().getActiveShell();
		boolean result = WrappedMessageDialog.openQuestion(shell, title, msg);

		if (shellImage != null) {
			WrappedMessageDialog.setDefaultImage(oldImage);
		}

		return result;
	}

	/**
	 * Displays the given message in a confirmation dialog with a "Yes" and
	 * "Cancel" button.
	 * 
	 * @param title
	 *            The title for the information dialog.
	 * @param msg
	 *            The message to display.
	 */
	public boolean displayConfirmation(String title, String msg) {
		if (msg == null) {
			msg = ""; //$NON-NLS-1$
		}

		Image oldImage = WrappedMessageDialog.getDefaultImage();
		Image shellImage = getShellImage();
		if (shellImage != null) {
			WrappedMessageDialog.setDefaultImage(shellImage);
		}

		Shell shell = plugin.getWorkbench().getDisplay().getActiveShell();
		boolean result = WrappedMessageDialog.openConfirm(shell, title, msg);

		if (shellImage != null) {
			WrappedMessageDialog.setDefaultImage(oldImage);
		}

		return result;
	}

	public int displayConfirmation(String title, String msg, IStatus status) {
		if (status == null) {
			throw new IllegalArgumentException("status argument cannot be null"); //$NON-NLS-1$
		}

		if (msg == null) {
			msg = status.getMessage();
		}
		if (msg == null) {
			msg = ""; //$NON-NLS-1$
		}

		Image shellImage = getShellImage();
		if (shellImage != null) {
			ErrorDialogNoReason.setDefaultImage(shellImage);
		}

		Shell shell = plugin.getWorkbench().getDisplay().getActiveShell();

		int rc = ErrorDialogNoReason.openError(shell, title, msg, status);

		return rc;

	}

	/**
	 * Returns the image for the current shell.
	 * 
	 * @return The current shell image.
	 */
	private Image getShellImage() {
		IWorkbench workbench = PlatformUI.getWorkbench();
		if (workbench != null) {
			IWorkbenchWindow workbenchWindow = workbench
					.getActiveWorkbenchWindow();
			if (workbenchWindow != null) {
				Shell shell = workbenchWindow.getShell();
				if (shell != null) {
					return shell.getImage();
				}
			}
		}
		return null;
	}

}