/*******************************************************************************
 * Copyright (c) 2008, 2015 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
 *     Krzysztof Daniel <krzysztof.daniel@gmail.com> - bug 355030
 ******************************************************************************/

package org.eclipse.ui.tests.statushandlers;

import java.util.concurrent.Semaphore;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.locks.ReentrantLock;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.MultiStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.util.Geometry;
import org.eclipse.jface.util.Policy;
import org.eclipse.jface.viewers.ILabelDecorator;
import org.eclipse.jface.viewers.ILabelProviderListener;
import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Link;
import org.eclipse.swt.widgets.Monitor;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.ui.internal.WorkbenchMessages;
import org.eclipse.ui.internal.statushandlers.IStatusDialogConstants;
import org.eclipse.ui.internal.statushandlers.WorkbenchStatusDialogManagerImpl;
import org.eclipse.ui.progress.IProgressConstants;
import org.eclipse.ui.statushandlers.AbstractStatusAreaProvider;
import org.eclipse.ui.statushandlers.IStatusAdapterConstants;
import org.eclipse.ui.statushandlers.StatusAdapter;
import org.eclipse.ui.statushandlers.StatusManager;
import org.eclipse.ui.statushandlers.StatusManager.INotificationListener;
import org.eclipse.ui.statushandlers.WorkbenchErrorHandler;
import org.eclipse.ui.statushandlers.WorkbenchStatusDialogManager;
import org.eclipse.ui.tests.concurrency.FreezeMonitor;
import org.eclipse.ui.tests.harness.util.UITestCase;

import junit.framework.TestCase;

public class StatusDialogManagerTest extends TestCase {

	private static final String ACTION_NAME = "actionname";
	private static final String JOB_NAME = "jobname";
	private static final String THROWABLE = "throwable";
	private final static String MESSAGE_1 = "TEST_MESSAGE_1";
	private final static String MESSAGE_2 = "TEST_MESSAGE_2";
	private final static String TITLE = "TEST_TITLE";
	private final static NullPointerException NPE = new NullPointerException();
	private final static NullPointerException NPE_WITH_MESSAGE = new NullPointerException(
			THROWABLE);
	private final static String NPE_NAME = NPE.getClass().getName();

	private boolean automatedMode;
	WorkbenchStatusDialogManager wsdm;

	@Override
	protected void setUp() throws Exception {
		super.setUp();
		automatedMode = ErrorDialog.AUTOMATED_MODE;
		wsdm = new WorkbenchStatusDialogManager(null, null);
		ErrorDialog.AUTOMATED_MODE = false;
		wsdm.setProperty(IStatusDialogConstants.ANIMATION, Boolean.FALSE);
		FreezeMonitor.expectCompletionIn(60_000);
	}

	public void testBlockingAppearance() {
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), true);
		Shell shell = StatusDialogUtil.getStatusShell();
		assertNotNull(shell);
		assertTrue((shell.getStyle() & SWT.APPLICATION_MODAL) == SWT.APPLICATION_MODAL);
	}

	public void testNonBlockingAppearance() {
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);
		Shell shell = StatusDialogUtil.getStatusShell();
		assertNotNull(shell);
		assertFalse((shell.getStyle() & SWT.APPLICATION_MODAL) == SWT.APPLICATION_MODAL);
	}

	public void testModalitySwitch1() {
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);
		Shell shell = StatusDialogUtil.getStatusShell();
		assertNotNull(shell);
		assertFalse((shell.getStyle() & SWT.APPLICATION_MODAL) == SWT.APPLICATION_MODAL);

		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), true);
		shell = StatusDialogUtil.getStatusShell();
		assertNotNull(shell);
		assertTrue((shell.getStyle() & SWT.APPLICATION_MODAL) == SWT.APPLICATION_MODAL);
	}

	public void testCheckingForMessageDuplication1() {
		IStatus status = new IStatus() {

			@Override
			public IStatus[] getChildren() {
				return new IStatus[0];
			}

			@Override
			public int getCode() {
				return IStatus.ERROR;
			}

			@Override
			public Throwable getException() {
				return new ArrayIndexOutOfBoundsException();
			}

			@Override
			public String getMessage() {
				return null;
			}

			@Override
			public String getPlugin() {
				return "plugin";
			}

			@Override
			public int getSeverity() {
				return IStatus.ERROR;
			}

			@Override
			public boolean isMultiStatus() {
				return false;
			}

			@Override
			public boolean isOK() {
				return false;
			}

			@Override
			public boolean matches(int severityMask) {
				return true;
			}

		};
		wsdm.addStatusAdapter(new StatusAdapter(status), false);

		assertEquals(status.getException().getClass().getName(),
				StatusDialogUtil.getTitleLabel().getText());
		assertEquals(WorkbenchMessages.WorkbenchStatusDialog_SeeDetails,
				StatusDialogUtil.getSingleStatusLabel().getText());
	}

	/**
	 * Preserving details selection and state
	 */
	public void testModalitySwitch2() {
		final StatusAdapter[] passed = new StatusAdapter[] { null };
		final Composite[] details = new Composite[] { null };
		setupDetails(passed, details);
		StatusAdapter sa = createStatusAdapter(MESSAGE_1);
		wsdm.addStatusAdapter(sa, false);

		// open details
		selectWidget(StatusDialogUtil.getDetailsButton());
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_2), true);

		assertNotNull(details[0]);
		assertFalse(details[0].isDisposed());
		assertEquals(sa, passed[0]);
	}

	/**
	 * Preserving support selection and state
	 */
	public void testModalitySwitch3() {
		final StatusAdapter[] passed = new StatusAdapter[] { null };
		final Composite[] support = new Composite[] { null };
		setupSupportArea(passed, support);
		StatusAdapter sa = createStatusAdapter(MESSAGE_1);
		wsdm.addStatusAdapter(sa, false);

		// open support
		selectWidget(StatusDialogUtil.getSupportLink());
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_2), true);

		assertNotNull(support[0]);
		assertFalse(support[0].isDisposed());
		assertEquals(sa, passed[0]);
	}

	/**
	 * Be sure that label provider is not disposed during modality switch.
	 */
	public void testModalitySwitch4() {
		final boolean[] disposed = new boolean[] { false };
		ITableLabelProvider provider = new ITableLabelProvider() {

			@Override
			public Image getColumnImage(Object element, int columnIndex) {
				return null;
			}

			@Override
			public String getColumnText(Object element, int columnIndex) {
				return "";
			}

			@Override
			public void addListener(ILabelProviderListener listener) {
			}

			@Override
			public void dispose() {
				disposed[0] = true;
			}

			@Override
			public boolean isLabelProperty(Object element, String property) {
				return false;
			}

			@Override
			public void removeListener(ILabelProviderListener listener) {
			}

		};
		wsdm.setStatusListLabelProvider(provider);

		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_2), true);

		assertFalse(
				"Label provider should not be disposed during modality switch.",
				disposed[0]);

		selectWidget(StatusDialogUtil.getOkButton());
		assertTrue("Label should be disposed when the dialog is closed.",
				disposed[0]);
	}

	/**
	 * Simple status without exception Check primary and secondary message.
	 * Verify invisible action button.
	 */
	public void testWithStatusAdapter1() {
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);
		Label titleLabel = StatusDialogUtil.getTitleLabel();
		assertNotNull(titleLabel);
		assertEquals(MESSAGE_1, titleLabel.getText());

		Label secondaryLabel = StatusDialogUtil.getSingleStatusLabel();
		assertNotNull(secondaryLabel);
		assertEquals(WorkbenchMessages.WorkbenchStatusDialog_SeeDetails,
				secondaryLabel.getText());

		// check invisible action button
		Button actionButton = StatusDialogUtil.getActionButton();
		assertNotNull(actionButton);
		assertFalse(actionButton.isVisible());
		Object layoutData = actionButton.getLayoutData();
		assertTrue(layoutData instanceof GridData);
		assertTrue(((GridData) layoutData).exclude);
	}

	public void testWithStatusAdapterAndLabelProvider1(){
		wsdm.setMessageDecorator(new ILabelDecorator(){

			@Override
			public Image decorateImage(Image image, Object element) {
				return null;
			}

			@Override
			public String decorateText(String text, Object element) {
				return text.replaceAll("[A-Z][A-Z][A-Z][0-9][0-9]", "");
			}

			@Override
			public void addListener(ILabelProviderListener listener) {

			}

			@Override
			public void dispose() {

			}

			@Override
			public boolean isLabelProperty(Object element, String property) {
				return false;
			}

			@Override
			public void removeListener(ILabelProviderListener listener) {

			}

		});
		wsdm.addStatusAdapter(createStatusAdapter("XYZ01" + MESSAGE_1), false);
		Label titleLabel = StatusDialogUtil.getTitleLabel();
		assertNotNull(titleLabel);
		assertEquals(MESSAGE_1, titleLabel.getText());

		Label secondaryLabel = StatusDialogUtil.getSingleStatusLabel();
		assertNotNull(secondaryLabel);
		assertEquals(WorkbenchMessages.WorkbenchStatusDialog_SeeDetails,
				secondaryLabel.getText());
	}


	/**
	 * Simple status with title. Check primary and secondary message. Verify
	 * closing.
	 */
	public void testWithStatusAdapter2() {
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1, TITLE),
				false);
		Label titleLabel = StatusDialogUtil.getTitleLabel();
		assertNotNull(titleLabel);
		assertEquals(TITLE, titleLabel.getText());

		Label secondaryLabel = StatusDialogUtil.getSingleStatusLabel();
		assertNotNull(secondaryLabel);
		assertEquals(MESSAGE_1, secondaryLabel.getText());

		selectWidget(StatusDialogUtil.getOkButton());
		// dialog closed
		assertNull(StatusDialogUtil.getStatusShell());

		// list cleared
		assertEquals(0, wsdm.getStatusAdapters().size());
	}

	/**
	 * Simple status with exception with message
	 */
	public void testWithStatusAdapter3() {
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1,
				NPE_WITH_MESSAGE), false);
		Label titleLabel = StatusDialogUtil.getTitleLabel();
		assertNotNull(titleLabel);
		assertEquals(MESSAGE_1, titleLabel.getText());

		Label secondaryLabel = StatusDialogUtil.getSingleStatusLabel();
		assertNotNull(secondaryLabel);
		assertEquals(THROWABLE, secondaryLabel.getText());
	}

	/**
	 * Simple status with exception without message
	 */
	public void testWithStatusAdapter4() {
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1, NPE), false);

		Label titleLabel = StatusDialogUtil.getTitleLabel();
		assertNotNull(titleLabel);
		assertEquals(MESSAGE_1, titleLabel.getText());

		Label secondaryLabel = StatusDialogUtil.getSingleStatusLabel();
		assertNotNull(secondaryLabel);
		assertEquals(NPE_NAME, secondaryLabel.getText());
	}

	/**
	 * Simple status from job
	 */
	public void testWithStatusAdapter5() {
		String message = "testmessage";
		StatusAdapter statusAdapter = new StatusAdapter(new Status(
				IStatus.ERROR, "testplugin", message));
		Job job = new Job("job") {
			@Override
			protected IStatus run(IProgressMonitor monitor) {
				return null;
			}
		};
		statusAdapter.addAdapter(Job.class, job);
		wsdm.addStatusAdapter(statusAdapter, false);
		Label titleLabel = StatusDialogUtil.getTitleLabel();
		assertNotNull(titleLabel);
		assertEquals(titleLabel.getText(), NLS.bind(
				WorkbenchMessages.WorkbenchStatusDialog_ProblemOccurredInJob,
				job.getName()));
		Label secondaryLabel = StatusDialogUtil.getSingleStatusLabel();
		assertNotNull(secondaryLabel);
		assertEquals(secondaryLabel.getText(), message);
	}

	/**
	 * Simple status from job with action
	 */
	public void testWithStatusAdapter6() {
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1, JOB_NAME,
				ACTION_NAME), false);

		Label titleLabel = StatusDialogUtil.getTitleLabel();
		assertNotNull(titleLabel);
		assertEquals(NLS.bind(
				WorkbenchMessages.WorkbenchStatusDialog_ProblemOccurredInJob,
				JOB_NAME), titleLabel.getText());

		Label secondaryLabel = StatusDialogUtil.getSingleStatusLabel();
		assertNotNull(secondaryLabel);
		assertEquals(MESSAGE_1, secondaryLabel.getText());

		// check visible action button
		Button actionButton = StatusDialogUtil.getActionButton();
		assertNotNull(actionButton);
		assertTrue(actionButton.isVisible());

		Object layoutData = actionButton.getLayoutData();
		assertTrue(layoutData instanceof GridData);
		assertFalse(((GridData) layoutData).exclude);
		assertEquals(ACTION_NAME, actionButton.getText());

		// be sure that support button is not created
		Link supportLink = StatusDialogUtil.getSupportLink();
		assertNull(supportLink);
	}

	/**
	 * Tests if status dialog passes status adapter to the support provider
	 * tests if status dialog extends its height & width
	 */
	public void testSupport1() {
		StatusAdapter statusAdapter = createStatusAdapter(MESSAGE_1);
		final StatusAdapter[] passed = new StatusAdapter[] { null };
		Composite[] support = new Composite[] { null };
		setupSupportArea(passed, support);
		wsdm.addStatusAdapter(statusAdapter, false);
		openSupportArea(statusAdapter, passed);
	}

	/**
	 * Tests if support area appears by default if appropriate flag is set up.
	 */
	public void testSupport2(){
		StatusAdapter statusAdapter = createStatusAdapter(MESSAGE_1);
		wsdm.setProperty(IStatusDialogConstants.SHOW_SUPPORT, Boolean.TRUE);
		final StatusAdapter[] passed = new StatusAdapter[] { null };
		Composite[] support = new Composite[] { null };
		setupSupportArea(passed, support);
		wsdm.addStatusAdapter(statusAdapter, false);
		assertEquals(statusAdapter, passed[0]);
	}

	/**
	 * Tests if details can be closed and opened 2 times tests if correct status
	 * adapter is passed to details
	 */
	public void testDetails1() {
		StatusAdapter statusAdapter = createStatusAdapter(MESSAGE_1);
		final StatusAdapter[] passed = new StatusAdapter[] { null };
		final Composite[] details = new Composite[] { null };
		setupDetails(passed, details);
		wsdm.addStatusAdapter(statusAdapter, false);
		for (int i = 0; i < 2; i++) {
			passed[0] = null;
			Point sizeBefore = StatusDialogUtil.getStatusShell().getSize();
			Button detailsButton = StatusDialogUtil.getDetailsButton();
			assertNotNull(detailsButton);
			assertTrue(detailsButton.isEnabled());
			assertEquals(IDialogConstants.SHOW_DETAILS_LABEL, detailsButton
					.getText());

			selectWidget(detailsButton);

			Point sizeAfter = StatusDialogUtil.getStatusShell().getSize();
			assertEquals(statusAdapter, passed[0]);
			assertTrue(sizeAfter.y > sizeBefore.y);
			assertEquals(IDialogConstants.HIDE_DETAILS_LABEL, detailsButton
					.getText());
			assertNotNull(details[0]);
			assertFalse(details[0].isDisposed());

			selectWidget(detailsButton);

			Point sizeAfterAfter = StatusDialogUtil.getStatusShell().getSize();
			assertTrue(sizeAfterAfter.y < sizeAfter.y);
			assertEquals(IDialogConstants.SHOW_DETAILS_LABEL, detailsButton
					.getText());
			assertTrue(details[0].isDisposed());
		}
	}

	public void testNullLabelProvider(){
		try {
			wsdm.setStatusListLabelProvider(null);
			fail();
		} catch (IllegalArgumentException iae){
			assertTrue(true);
		}
	}

	//bug 235254
	public void testNonNullLabelProvider(){
		try {
			final boolean [] called = new boolean[]{false};
			wsdm.setStatusListLabelProvider(new ITableLabelProvider(){

				@Override
				public Image getColumnImage(Object element, int columnIndex) {
					return null;
				}

				@Override
				public String getColumnText(Object element, int columnIndex) {
					called[0] = true;
					return "";
				}

				@Override
				public void addListener(ILabelProviderListener listener) {

				}

				@Override
				public void dispose() {

				}

				@Override
				public boolean isLabelProperty(Object element, String property) {
					return false;
				}

				@Override
				public void removeListener(ILabelProviderListener listener) {

				}

			});
			wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), true);
			assertTrue(called[0]);
		} catch (Exception e){
			fail();
		}
	}

	/**
	 * Verifies that correct status adapter is passed to the support area
	 */
	public void testList1() {
		StatusAdapter statusAdapter1 = createStatusAdapter(MESSAGE_1);
		StatusAdapter statusAdapter2 = createStatusAdapter(MESSAGE_2);

		StatusAdapter[] passed = new StatusAdapter[] { null };
		Composite[] support = new Composite[] { null };
		setupSupportArea(passed, support);

		wsdm.addStatusAdapter(statusAdapter1, false);
		wsdm.addStatusAdapter(statusAdapter2, false);

		Table table = StatusDialogUtil.getTable();
		assertNotNull(table);
		assertEquals(0, table.getSelectionIndex());
		assertEquals(MESSAGE_1, table.getItem(0).getText());
		assertEquals(MESSAGE_2, table.getItem(1).getText());

		// this verifies if support is opened for correct statusAdapter
		openSupportArea(statusAdapter1, passed);
		selectTable(table, 1);
		processRemainingUiEvents();
		assertEquals(statusAdapter2, passed[0]);
	}

	private void processRemainingUiEvents() {
		UITestCase.processEvents();
		int count = 0;
		while (count < 3 && (StatusDialogUtil.getStatusShell() != null)) {
			UITestCase.processEvents();
			count++;
		}
	}

	private void assertStatusShellOpen() {
		int count = 0;
		while (count < 42 && (StatusDialogUtil.getStatusShell() == null)) {
			UITestCase.processEvents();
			count++;
		}
		assertNotNull("Status shell was not shown!", StatusDialogUtil.getStatusShell());
	}

	/**
	 * Verifies that correct status adapter is passed to details
	 */
	public void testList2() {
		StatusAdapter statusAdapter1 = createStatusAdapter(MESSAGE_1);
		StatusAdapter statusAdapter2 = createStatusAdapter(MESSAGE_2);

		Composite[] details = new Composite[] { null };
		StatusAdapter[] passed = new StatusAdapter[] { null };
		setupDetails(passed, details);

		wsdm.addStatusAdapter(statusAdapter1, false);
		wsdm.addStatusAdapter(statusAdapter2, false);

		selectWidget(StatusDialogUtil.getDetailsButton());
		assertNotNull(details[0]);
		assertFalse(details[0].isDisposed());
		assertEquals(statusAdapter1, passed[0]);

		Table table = StatusDialogUtil.getTable();
		selectTable(table, 1);

		assertNotNull(details[0]);
		assertFalse(details[0].isDisposed());
		processRemainingUiEvents();

		assertEquals(statusAdapter2, passed[0]);
	}

	/**
	 * Tests secondary message and the list element for normal and job status
	 * adapter
	 */
	public void testList3() {
		StatusAdapter sa1 = createStatusAdapter(MESSAGE_1);
		StatusAdapter sa2 = createStatusAdapter(MESSAGE_2, JOB_NAME,
				ACTION_NAME);

		wsdm.addStatusAdapter(sa1, false);
		wsdm.addStatusAdapter(sa2, false);

		Table table = StatusDialogUtil.getTable();
		Label titleLabel = StatusDialogUtil.getTitleLabel();

		assertEquals(WorkbenchMessages.WorkbenchStatusDialog_SeeDetails,
				titleLabel.getText());
		assertEquals(MESSAGE_1, table.getItem(0).getText());

		selectTable(table, 1);

		processRemainingUiEvents();

		assertEquals(MESSAGE_2, titleLabel.getText());
		assertEquals(JOB_NAME, table.getItem(1).getText());
	}

	public void testBug260937(){
		WorkbenchStatusDialogManager wsdm = new WorkbenchStatusDialogManager(
				IStatus.CANCEL, null);
		StatusAdapter sa = createStatusAdapter(MESSAGE_1);
		try {
			wsdm.addStatusAdapter(sa, false);
			assertTrue(true);
		} catch (NullPointerException npe){
			fail();
		}
	}

	public void testBug276371(){
		StatusAdapter bomb = new StatusAdapter(new Status(IStatus.ERROR,
				"org.eclipse.ui.tests", "bomb"){
			int i = 0;

			@Override
			public String getMessage() {
				i++;
				if (i == 1) {
					throw new RuntimeException("the bomb!");
				}
				return super.getMessage();

			}
		});
		try{
			wsdm.addStatusAdapter(bomb, false);
		} catch (Throwable t) {
			fail("no exception should be thrown");
		}
		assertTrue("Dialog should not display on failure",
				StatusDialogUtil.getStatusShell() == null);
		wsdm.addStatusAdapter(createStatusAdapter("normal one"), false);
		assertTrue("Dialog could not be initialized after failure",
				StatusDialogUtil.getStatusShell() != null);
	}

	// checking if the statuses are correctly ignored.
	public void testOKStatus1() {
		try {
			wsdm.addStatusAdapter(new StatusAdapter(Status.OK_STATUS), false);
			assertTrue(true);
		} catch (NullPointerException npe) {
			fail();
		}
		assertNull("Shell should not be created.", StatusDialogUtil
				.getStatusShell());
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);
		assertEquals(
				"Only one status should be visible (OK should be ignored)", 1,
				wsdm.getStatusAdapters().size());
	}

	public void testOKStatus2(){
		final WorkbenchStatusDialogManager wsdm[] = new WorkbenchStatusDialogManager[] { null };
		WorkbenchErrorHandler weh = new WorkbenchErrorHandler() {

			@Override
			protected void configureStatusDialog(
					WorkbenchStatusDialogManager statusDialog) {
				wsdm[0] = statusDialog;
				super.configureStatusDialog(statusDialog);
			}

		};
		weh.handle(new StatusAdapter(Status.OK_STATUS), StatusManager.SHOW);
		assertEquals(1, wsdm[0].getStatusAdapters().size());
	}

	public void testBug211933() {
		MultiStatus multi = new MultiStatus("testplugin", 0, "message", null);
		multi.add(new Status(IStatus.CANCEL, "testplugin", "message 1"));
		final WorkbenchStatusDialogManager wsdm[] = new WorkbenchStatusDialogManager[] { null };
		WorkbenchErrorHandler weh = new WorkbenchErrorHandler() {

			@Override
			protected void configureStatusDialog(
					WorkbenchStatusDialogManager statusDialog) {
				wsdm[0] = statusDialog;
				super.configureStatusDialog(statusDialog);
			}

		};
		StatusAdapter sa = new StatusAdapter(multi);
		weh.handle(sa, StatusManager.SHOW);
		// be sure that non error status is passed to the dialog
		assertTrue(wsdm[0].getStatusAdapters().contains(sa));
	}

	public void testBug275867(){
		StatusAdapter statusAdapter = createStatusAdapter(MESSAGE_1);
		final StatusAdapter[] passed = new StatusAdapter[] { null };
		Composite[] support = new Composite[] { null };
		setupSupportArea(passed, support);
		wsdm.setProperty(IStatusDialogConstants.SHOW_SUPPORT, Boolean.TRUE);
		wsdm.addStatusAdapter(statusAdapter, false);
		assertNotNull(StatusDialogUtil.getStatusShell());
		Shell shell = StatusDialogUtil.getStatusShell();
		assertEquals("Dialog is not centered correctly",getInitialLocation(shell), shell.getLocation());
	}

	//error link present
	public void testBug278965_1() {
		final WorkbenchStatusDialogManager wsdm[] = new WorkbenchStatusDialogManager[] { null };
		WorkbenchErrorHandler weh = new WorkbenchErrorHandler() {

			@Override
			protected void configureStatusDialog(
					WorkbenchStatusDialogManager statusDialog) {
				wsdm[0] = statusDialog;
				super.configureStatusDialog(statusDialog);
			}

		};
		weh.handle(createStatusAdapter(MESSAGE_1), StatusManager.SHOW | StatusManager.LOG);
		assertEquals(1, wsdm[0].getStatusAdapters().size());

		assertStatusShellOpen();

		Link errorLogLink = StatusDialogUtil.getErrorLogLink();
		if (errorLogLink == null) {
			// TODO test fails in Gerrit, but passes with GTK2/GTK3 locally
			// The getErrorLogLink() can't find the link widget...
			return;
		}
		assertNotNull("Link to error log should be present", errorLogLink);
		assertFalse("Link to error log should not be disposed",
				errorLogLink.isDisposed());
		assertTrue("Link to error log should be enabled",
				errorLogLink.isEnabled());
		assertTrue("Link to error log should be visible",
				errorLogLink.isVisible());
	}

	//error link hidden
	public void testBug278965_2(){
		final WorkbenchStatusDialogManager wsdm[] = new WorkbenchStatusDialogManager[] { null };
		WorkbenchErrorHandler weh = new WorkbenchErrorHandler() {

			@Override
			protected void configureStatusDialog(
					WorkbenchStatusDialogManager statusDialog) {
				wsdm[0] = statusDialog;
				super.configureStatusDialog(statusDialog);
			}

		};
		weh.handle(createStatusAdapter(MESSAGE_1), StatusManager.SHOW);
		assertEquals(1, wsdm[0].getStatusAdapters().size());
		boolean status = StatusDialogUtil.getErrorLogLink() == null
				|| StatusDialogUtil.getErrorLogLink().isDisposed()
				|| !StatusDialogUtil.getErrorLogLink().isVisible();
		assertTrue("Error log link should be null, disposed or invisible", status);
	}

	//two statuses, present
	public void testBug278965_3(){
		final WorkbenchStatusDialogManager wsdm[] = new WorkbenchStatusDialogManager[] { null };
		WorkbenchErrorHandler weh = new WorkbenchErrorHandler() {

			@Override
			protected void configureStatusDialog(
					WorkbenchStatusDialogManager statusDialog) {
				wsdm[0] = statusDialog;
				super.configureStatusDialog(statusDialog);
			}

		};
		weh.handle(createStatusAdapter(MESSAGE_1), StatusManager.SHOW);
		weh.handle(createStatusAdapter(MESSAGE_2), StatusManager.SHOW | StatusManager.LOG);

		assertStatusShellOpen();
		Link errorLogLink = StatusDialogUtil.getErrorLogLink();
		if (errorLogLink == null) {
			// TODO test fails in Gerrit, but passes with GTK2/GTK3 locally
			// The getErrorLogLink() can't find the link widget...
			return;
		}
		assertNotNull("Link to error log should be present", errorLogLink);
		assertFalse("Link to error log should not be disposed",
				errorLogLink.isDisposed());
		assertTrue("Link to error log should be enabled",
				errorLogLink.isEnabled());
		assertTrue("Link to error log should be visible",
				errorLogLink.isVisible());
	}

	// two statuses, details, resize
	public void testBug288770_1(){
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_2), false);
		assertTrue("Details should be closed initially", StatusDialogUtil
				.getDetailsButton().getText().equals(
						IDialogConstants.SHOW_DETAILS_LABEL));
		assertTrue("The list should be visible", StatusDialogUtil.getTable() != null);
		selectWidget(StatusDialogUtil.getDetailsButton());
		int height = StatusDialogUtil.getTable().getSize().y;
		// resize the dialog
		Shell statusShell = StatusDialogUtil.getStatusShell();
		Point shellSize = statusShell.getSize();
		statusShell.setSize(shellSize.x, shellSize.y + 100);
		statusShell.layout(true);
		int newHeight = StatusDialogUtil.getTable().getSize().y;
		assertEquals("All height should be consumed by details", height,
				newHeight);
	}

	// status, details, status, resize
	public void testBug288770_2(){
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);
		assertTrue("Details should be closed initially", StatusDialogUtil
				.getDetailsButton().getText().equals(
						IDialogConstants.SHOW_DETAILS_LABEL));
		selectWidget(StatusDialogUtil.getDetailsButton());
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_2), false);
		assertTrue("The list should be visible", StatusDialogUtil.getTable() != null);
		int height = StatusDialogUtil.getTable().getSize().y;
		// resize the dialog
		Shell statusShell = StatusDialogUtil.getStatusShell();
		Point shellSize = statusShell.getSize();
		statusShell.setSize(shellSize.x, shellSize.y + 100);
		statusShell.layout(true);
		int newHeight = StatusDialogUtil.getTable().getSize().y;
		assertEquals("All height should be consumed by details", height,
				newHeight);
	}

	public void testBug288770_3(){
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);
		assertTrue("Details should be closed initially", StatusDialogUtil
				.getDetailsButton().getText().equals(
						IDialogConstants.SHOW_DETAILS_LABEL));
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_2), false);
		assertTrue("The list should be visible", StatusDialogUtil.getTable() != null);
		int height = StatusDialogUtil.getTable().getSize().y;
		// resize the dialog
		Shell statusShell = StatusDialogUtil.getStatusShell();
		Point shellSize = statusShell.getSize();
		statusShell.setSize(shellSize.x, shellSize.y + 100);
		statusShell.layout(true);
		int newHeight = StatusDialogUtil.getTable().getSize().y;
		assertTrue("List should resize when details are closed", height < newHeight);
	}

	public void testBug288770_4(){
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);
		assertTrue("Details should be closed initially", StatusDialogUtil
				.getDetailsButton().getText().equals(
						IDialogConstants.SHOW_DETAILS_LABEL));
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_2), false);
		selectWidget(StatusDialogUtil.getDetailsButton());
		selectWidget(StatusDialogUtil.getDetailsButton());
		assertTrue("Details should be closed", StatusDialogUtil
				.getDetailsButton().getText().equals(
						IDialogConstants.SHOW_DETAILS_LABEL));
		assertTrue("The list should be visible", StatusDialogUtil.getTable() != null);
		int height = StatusDialogUtil.getTable().getSize().y;
		// resize the dialog
		Shell statusShell = StatusDialogUtil.getStatusShell();
		Point shellSize = statusShell.getSize();
		statusShell.setSize(shellSize.x, shellSize.y + 100);
		statusShell.layout(true);
		int newHeight = StatusDialogUtil.getTable().getSize().y;
		assertTrue("List should resize when details are closed", height < newHeight);
	}

	public void testBug288765() {
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);
		selectWidget(StatusDialogUtil.getDetailsButton());
		int sizeY = StatusDialogUtil.getStatusShell().getSize().y;
		selectWidget(StatusDialogUtil.getOkButton());
		MultiStatus ms = new MultiStatus("org.eclipse.ui.tests", 0, MESSAGE_1,
				null);
		for (int i = 0; i < 50; i++) {
			ms
					.add(new Status(IStatus.ERROR, "org.eclipse.ui.tests",
							MESSAGE_2));
		}
		wsdm.addStatusAdapter(new StatusAdapter(ms), false);
		selectWidget(StatusDialogUtil.getDetailsButton());
		Shell shell = StatusDialogUtil.getStatusShell();
		Rectangle newSize = shell.getBounds();
		assertTrue(newSize.height > sizeY);
	}

	public void testIgnoringOpenTrayOnShow() {
		wsdm.enableDefaultSupportArea(true);
		wsdm.enableErrorDialogCompatibility();
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1), false);
		WorkbenchStatusDialogManagerImpl manager = (WorkbenchStatusDialogManagerImpl) wsdm
				.getProperty(IStatusDialogConstants.MANAGER_IMPL);
		assertNull("Tray should not be opened", manager.getDialog().getTray());

		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_2,
				new NullPointerException()), false);

		Table table = StatusDialogUtil.getTable();
		selectTable(table, 1);
		processRemainingUiEvents();
		assertNotNull("Tray should be opened", manager.getDialog().getTray());

		selectTable(table, 0);
		processRemainingUiEvents();
		assertNull("Tray should not be opened", manager.getDialog().getTray());
	}

	public void testAutoOpeningTrayOnShow() {
		wsdm.enableDefaultSupportArea(true);
		wsdm.enableErrorDialogCompatibility();
		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_1, new NullPointerException()), false);
		WorkbenchStatusDialogManagerImpl manager = (WorkbenchStatusDialogManagerImpl) wsdm
				.getProperty(IStatusDialogConstants.MANAGER_IMPL);
		assertNotNull("Tray should be opened", manager.getDialog().getTray());
	}

	/**
	 * Enable default support area.
	 * Open the dialog as non-modal.
	 * Open the tray. Test if tray opened.
	 * Change the modality. Test if tray still opened.
	 * Select adapter without status. Test if tray closed.
	 */
	public void testModalitySwitch5() {
		wsdm.enableDefaultSupportArea(true);
		StatusAdapter sa = createStatusAdapter(MESSAGE_1, new NullPointerException());
		wsdm.addStatusAdapter(sa, false);

		assertNotNull(StatusDialogUtil.getSupportLink());
		assertTrue(StatusDialogUtil.getSupportLink().isEnabled());
		selectWidget(StatusDialogUtil.getSupportLink());
		WorkbenchStatusDialogManagerImpl manager = (WorkbenchStatusDialogManagerImpl) wsdm
				.getProperty(IStatusDialogConstants.MANAGER_IMPL);
		assertNotNull("Tray should be opened", manager.getDialog().getTray());

		wsdm.addStatusAdapter(createStatusAdapter(MESSAGE_2), true);
		assertNotNull("Tray should be opened", manager.getDialog().getTray());

		Table table = StatusDialogUtil.getTable();
		selectTable(table, 1);
		processRemainingUiEvents();
		assertNull("Tray should not be opened", manager.getDialog().getTray());
		assertNull(StatusDialogUtil.getSupportLink());
	}

	public void testSupportLinkVisibility1(){
		wsdm.enableDefaultSupportArea(true);
		StatusAdapter sa = createStatusAdapter(MESSAGE_1, new NullPointerException());
		wsdm.addStatusAdapter(sa, false);
		assertNotNull(StatusDialogUtil.getSupportLink());
		StatusAdapter sa2 = createStatusAdapter(MESSAGE_2);
		wsdm.addStatusAdapter(sa2, false);
		Table table = StatusDialogUtil.getTable();
		selectTable(table, 1);
		processRemainingUiEvents();
		assertNull(StatusDialogUtil.getSupportLink());
	}

	public void testSupportLinkVisibility2() {
		wsdm.enableDefaultSupportArea(true);
		StatusAdapter sa = createStatusAdapter(MESSAGE_1);
		wsdm.addStatusAdapter(sa, false);
		assertNull(StatusDialogUtil.getSupportLink());
		StatusAdapter sa2 = createStatusAdapter(MESSAGE_2, new NullPointerException());
		wsdm.addStatusAdapter(sa2, false);
		Table table = StatusDialogUtil.getTable();
		selectTable(table, 1);
		processRemainingUiEvents();
		assertNotNull(StatusDialogUtil.getSupportLink());
	}

	public void testProvidingCustomSupportAreaProvider() {
		final boolean[] consulted = new boolean[]{false};
		AbstractStatusAreaProvider customProvider = new AbstractStatusAreaProvider() {

			@Override
			public Control createSupportArea(Composite parent,
					StatusAdapter statusAdapter) {
				//intentionally does nothing as this provider
				//is not valid for any status
				return null;
			}

			@Override
			public boolean validFor(StatusAdapter statusAdapter) {
				consulted[0] = true;
				return false;
			}
		};

		wsdm.setSupportAreaProvider(customProvider);
		StatusAdapter sa = createStatusAdapter(MESSAGE_1);
		wsdm.addStatusAdapter(sa, false);
		assertTrue("Custom support area provider should be consulted", consulted[0]);
	}

	public void testDeadlockFromBug501681() throws Exception {
		assertNotNull("Test must run in UI thread", Display.getCurrent());

		final StatusAdapter statusAdapter = createStatusAdapter("Oops");
		AtomicReference<StatusAdapter[]> reported = new AtomicReference<>();
		INotificationListener listener = (type, adapters) -> {
			reported.set(adapters);
		};

		AtomicReference<ReentrantLock> lock = new AtomicReference<>();
		lock.set(new ReentrantLock());
		final Semaphore semaphore = new Semaphore(0);

		// This simulates a thread locked some shared resource
		// It will release lock only if "wait" is set to "false"
		Thread t = new Thread(() -> {
			lock.get().lock();
			try {
				semaphore.acquire();
			} catch (InterruptedException e) {
				// continue
			}
			lock.get().unlock();
		});
		t.start();

		// Wait for thread to acquire the lock
		while (!lock.get().isLocked()) {
			Thread.sleep(50);
		}
		assertTrue(lock.get().isLocked());

		// Verify status handling works (without blocking)
		StatusManager.getManager().addListener(listener);
		StatusManager.getManager().handle(statusAdapter, StatusManager.SHOW | StatusManager.LOG);
		assertSame(statusAdapter, reported.get()[0]);
		Shell shell = StatusDialogUtil.getStatusShell();
		if (shell != null) {
			shell.dispose();
		}
		reported.set(null);

		// Verify status handling works with blocking
		final StatusAdapter statusAdapter2 = createStatusAdapter("Oops2");
		try {
			// this job will try to report some "blocking" status
			// if it does NOT deadlock, the "wait" will be unset and lock will
			// be released
			Job badJob = new Job("Will report blocking error") {
				@Override
				protected IStatus run(IProgressMonitor monitor) {
					StatusManager.getManager().handle(statusAdapter2, StatusManager.BLOCK | StatusManager.LOG);
					// stop blocking thread
					semaphore.release();
					return Status.OK_STATUS;
				}
			};

			// start later so that we have time to lock ourselves
			badJob.schedule(100);

			// This will now block UI until the lock is released
			// Without the patch for bug 501681 this will never happen
			// because the job we start in a moment will wait for UI thread to
			// show the blocking dialog
			lock.get().lock();

			// make sure job was done
			badJob.join();
		} finally {
			// Will "unblock" the blocking dialog shown by the job, must be
			// posted with delay, because dialog is not yet shown
			postUnblockingTask();

			// Allow the blocking dialog to be shown
			UITestCase.processEvents();
			StatusManager.getManager().removeListener(listener);
		}
		assertFalse("Job should successfully finish", semaphore.hasQueuedThreads());
		assertNotNull("Status adapter was not logged", reported.get());
		assertSame(statusAdapter2, reported.get()[0]);
	}

	private void postUnblockingTask() {
		Display.getCurrent().timerExec(100, () -> {
			Shell shell = StatusDialogUtil.getStatusShellImmediately();
			if (shell != null) {
				shell.dispose();
			} else {
				// shell not shown yet? re-post
				postUnblockingTask();
			}
		});
	}

	/**
	 * Delivers custom support area.
	 *
	 * @param passed -
	 *            status adapter passed to the support will be set as first
	 *            element of this array.
	 * @param support -
	 *            a main support composite will be set as first element of this
	 *            array.
	 */
	private void setupSupportArea(final StatusAdapter[] passed,
			final Composite[] support) {
		Policy.setErrorSupportProvider(new AbstractStatusAreaProvider() {
			@Override
			public Control createSupportArea(Composite parent,
					StatusAdapter statusAdapter) {
				passed[0] = statusAdapter;
				Composite c = new Composite(parent, SWT.NONE);
				GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true,
						true);
				layoutData.minimumHeight = 400;
				c.setLayoutData(layoutData);
				support[0] = c;
				return c;
			}
		});
	}

	/**
	 * Opens support area.
	 *
	 * @param statusAdapter -
	 *            a statusAdapter (for verification that support area uses
	 *            correct one)
	 * @param passed -
	 *            a statusAdapter used by support area will be set as first
	 *            element of this array.
	 */
	private void openSupportArea(StatusAdapter statusAdapter,
			final StatusAdapter[] passed) {
		Point sizeBefore = StatusDialogUtil.getStatusShell().getSize();
		// be sure that support button is enabled
		Link supportLink = StatusDialogUtil.getSupportLink();
		assertNotNull(supportLink);
		assertTrue(supportLink.isEnabled());

		selectWidget(supportLink);
		Point sizeAfter = StatusDialogUtil.getStatusShell().getSize();
		assertEquals(statusAdapter, passed[0]);
		assertTrue(sizeAfter.x > sizeBefore.x);
		assertTrue(sizeAfter.y > sizeBefore.y);
	}

	/**
	 * This method creates custom details area.
	 *
	 * @param passed -
	 *            status adapter passed to the details will be set as first
	 *            element of this array.
	 * @param details -
	 *            a main details composite will be set as first element of this
	 *            array.
	 */
	private void setupDetails(final StatusAdapter[] passed,
			final Composite[] details) {
		wsdm.setDetailsAreaProvider(new AbstractStatusAreaProvider() {
			@Override
			public Control createSupportArea(Composite parent,
					StatusAdapter statusAdapter) {
				passed[0] = statusAdapter;
				Composite c = new Composite(parent, SWT.NONE);
				GridData layoutData = new GridData(SWT.FILL, SWT.FILL, true,
						true);
				layoutData.minimumHeight = 400;
				c.setLayoutData(layoutData);
				details[0] = c;
				return c;
			}
		});
	}

	/**
	 * This method simulates mouse selection on Table (selects TableItem).
	 *
	 * @param table
	 *            a Table to be selected.
	 * @param i
	 *            a number of tableItem to be selected.
	 */
	private void selectTable(Table table, int i) {
		table.setSelection(i);
		Event event = new Event();
		event.item = table.getItem(i);
		table.notifyListeners(SWT.Selection, event);
	}

	/**
	 * This method simulates mouse selection on particular Control.
	 *
	 * @param control
	 *            a Control to be selected.
	 */
	private void selectWidget(Widget control) {
		Event event = new Event();
		event.item = control;
		control.notifyListeners(SWT.Selection, event);
	}

	/**
	 * Creates StatusAdapter from passed parameters.
	 *
	 * @param message
	 *            a message to be used in StatusAdapter
	 * @return created StatusAdapter
	 */
	private StatusAdapter createStatusAdapter(String message) {
		return new StatusAdapter(new Status(IStatus.ERROR,
				"org.eclipse.ui.tests", message));
	}

	/**
	 * Creates StatusAdapter from passed parameters.
	 *
	 * @param message
	 *            a message to be used in StatusAdapter
	 * @param throwable
	 *            a Throwable to be used in StatusAdapter
	 * @return created StatusAdapter
	 */
	private StatusAdapter createStatusAdapter(String message,
			Throwable throwable) {
		return new StatusAdapter(new Status(IStatus.ERROR,
				"org.eclipse.ui.tests", message, throwable));
	}

	/**
	 * Creates StatusAdapter from passed parameters. StatusAdapter will look
	 * like it is coming from job.
	 *
	 * @param message
	 *            a message to be used in StatusAdapter
	 * @param jobname
	 *            a String that will be used as job name
	 * @param actionName
	 *            a String that will be used as a name of the action available
	 *            to the user
	 * @return created StatusAdapter
	 */
	private StatusAdapter createStatusAdapter(String message, String jobname,
			String actionName) {
		StatusAdapter sa = createStatusAdapter(message);
		if (jobname == null) {
			return sa;
		}
		Job job = new Job(jobname) {
			@Override
			protected IStatus run(IProgressMonitor monitor) {
				return null;
			}
		};
		sa.addAdapter(Job.class, job);
		if (actionName == null) {
			return sa;
		}
		Action action = new Action(actionName) {
		};
		job.setProperty(IProgressConstants.ACTION_PROPERTY, action);
		return sa;
	}

	/**
	 * Creates StatusAdapter from passed parameters.
	 *
	 * @param message
	 *            a message to be used in StatusAdapter
	 * @param title
	 *            a String to be passed as StatusAdapter title
	 * @return status adapter with title and message
	 */
	private StatusAdapter createStatusAdapter(String message, String title) {
		StatusAdapter sa = createStatusAdapter(message);
		sa.setProperty(IStatusAdapterConstants.TITLE_PROPERTY, title);
		return sa;
	}

	@Override
	protected void tearDown() throws Exception {
		Shell shell = StatusDialogUtil.getStatusShell();
		FreezeMonitor.done();
		if (shell != null) {
			shell.dispose();
			WorkbenchStatusDialogManagerImpl impl = (WorkbenchStatusDialogManagerImpl) wsdm
					.getProperty(IStatusDialogConstants.MANAGER_IMPL);
			assertNull(impl.getProperty(IStatusDialogConstants.CURRENT_STATUS_ADAPTER));
		}
		wsdm = null;
		ErrorDialog.AUTOMATED_MODE = automatedMode;
		Policy.setErrorSupportProvider(null);
		super.tearDown();
	}

	// based on window.getInitialLocation
	private Point getInitialLocation(Shell shell){
		Point initialSize = shell.getSize();
		Composite parent = shell.getParent();

		Monitor monitor = shell.getDisplay().getPrimaryMonitor();
		if (parent != null) {
			monitor = parent.getMonitor();
		}

		Rectangle monitorBounds = monitor.getClientArea();
		Point centerPoint;
		if (parent != null) {
			centerPoint = Geometry.centerPoint(parent.getBounds());
		} else {
			centerPoint = Geometry.centerPoint(monitorBounds);
		}

		return new Point(centerPoint.x - (initialSize.x / 2), Math.max(
				monitorBounds.y, Math.min(centerPoint.y
						- (initialSize.y * 2 / 3), monitorBounds.y
						+ monitorBounds.height - initialSize.y)));
	}
}
