/*******************************************************************************
 * Copyright (c) 2008 Oracle. 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:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.ui.tests.internal.util;

import org.eclipse.jface.dialogs.TitleAreaDialog;
import org.eclipse.jpt.ui.internal.util.ControlAligner;
import org.eclipse.jpt.ui.internal.util.SWTUtil;
import org.eclipse.jpt.utility.internal.ClassTools;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
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.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Shell;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import static org.junit.Assert.*;

@SuppressWarnings("nls")
public final class ControlAlignerTest {

	private ControlAligner controlAligner;
	private Composite parent;
	private Shell shell;

	private Layout buildSpacerLayout() {
		return new Layout() {
			@Override
			protected Point computeSize(Composite composite,
			                            int widthHint,
			                            int heightHint,
			                            boolean flushCache) {

				return new Point(widthHint, heightHint);
			}

			@Override
			protected void layout(Composite composite, boolean flushCache) {
				GridData data = (GridData) composite.getLayoutData();
				composite.setBounds(0, 0, data.widthHint, data.heightHint);
			}
		};
	}

	@Before
	public void setUp() {

		controlAligner = new ControlAligner();

		shell  = new Shell(Display.getCurrent());
		shell.setLayout(new GridLayout(1, false));

		parent = new Composite(shell, SWT.NONE);
		parent.setLayout(new GridLayout(1, false));
		parent.setLayoutData(new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
	}

	@After
	public void tearDown() {

		if (controlAligner != null) {
			controlAligner.dispose();
			controlAligner = null;
		}

		if (shell != null) {
			shell.dispose();
			shell = null;
		}
	}

	@Test
	public void testAddControl1() throws Exception {

		Composite pane = new Composite(parent, SWT.NULL);
		pane.setLayout(new GridLayout(3, false));
		pane.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		Label label = new Label(pane, SWT.NULL);
		updateGridData(label);

		controlAligner.add(label);

		assertEquals(
			"The maximum width should be 0,",
			0,
			controlAligner.getMaximumWidth()
		);

		label.setText("This is a ControlAligner");
//		parent.layout(true, true);

		Point size = label.getSize();

		assertEquals(
			"The width should be " + size.x + ",",
			size.x,
			controlAligner.getMaximumWidth()
		);
	}

	@Test
	public void testAddControl2() throws Exception {

		Composite pane = new Composite(parent, SWT.NULL);
		pane.setLayout(new GridLayout(3, false));
		pane.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		Button button = new Button(pane, SWT.NULL);
		button.setText("This is a ControlAligner");
		updateGridData(button);

		controlAligner.add(button);
		parent.layout(true, true);

		Point size = button.getSize();

		assertEquals(
			"The width should be " + size.x + ",",
			size.x,
			controlAligner.getMaximumWidth()
		);
	}

	@Test
	public void testAddControl3() throws Exception {

		Composite pane = new Composite(parent, SWT.NULL);
		pane.setLayout(new GridLayout(3, false));
		pane.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		Label label = new Label(pane, SWT.NULL);
		label.setText("This is very long text");
		updateGridData(label);

		Button button = new Button(pane, SWT.NULL);
		button.setText("Short text");
		updateGridData(button);

//		parent.layout(true, true);

		controlAligner.add(label);
		controlAligner.add(button);

		Point labelSize  = label.getSize();
		Point buttonSize = button.getSize();
		int max = Math.max(labelSize.x, buttonSize.x);

		assertEquals(
			"The width should be " + max + ",",
			max,
			controlAligner.getMaximumWidth()
		);
	}

	@Test
	public void testAddControlAligner1() throws Exception {

		Label label1 = new Label(parent, SWT.NULL);
		Label label2 = new Label(parent, SWT.NULL);

		updateGridData(label1);
		updateGridData(label2);

		controlAligner.add(label1);

		ControlAligner controlAligner2 = new ControlAligner();
		controlAligner.add(controlAligner2);
		controlAligner2.add(label2);

		label1.setText("This is a ControlAligner");
		label2.setText("This is a very long ControlAligner");
//		parent.layout(true, true);

		Point size1 = label1.getSize();
		Point size2 = label2.getSize();
		int width = Math.max(size1.x, size2.x);

		assertEquals(
			"The width should be " + width + ",",
			width,
			controlAligner.getMaximumWidth()
		);

		assertEquals(
			"The width should be " + width + ",",
			width,
			controlAligner2.getMaximumWidth()
		);
	}

	@Test
	public void testAddControlAligner2() throws Exception {

		Label label1 = new Label(parent, SWT.NULL);
		Label label2 = new Label(parent, SWT.NULL);

		updateGridData(label1);
		updateGridData(label2);

		controlAligner.add(label1);

		ControlAligner controlAligner2 = new ControlAligner();
		controlAligner2.add(label2);

		label1.setText("This is a ControlAligner");
		label2.setText("This is a very long ControlAligner");

		controlAligner.add(controlAligner2);
//		parent.layout(true, true);

		Point size1 = label1.getSize();
		Point size2 = label2.getSize();
		int width = Math.max(size1.x, size2.x);

		assertEquals(
			"The width should be " + width + ",",
			width,
			controlAligner.getMaximumWidth()
		);

		assertEquals(
			"The width should be " + width + ",",
			width,
			controlAligner2.getMaximumWidth()
		);
	}

	@Test(expected=IllegalArgumentException.class)
	public void testAddControlAlignerToItself() throws Exception {
		controlAligner.add(controlAligner);
		fail("A ControlAligner can't be added to itself");
	}

	@Test
	public void testDialog_AddControl1() throws Exception {

		final int[] maximumWidth = new int[1];
		final int[] size = new int[1];

		TitleAreaDialog dialog = new TitleAreaDialog(SWTUtil.getShell()) {

			private Label label;

			@Override
			protected Control createDialogArea(Composite parent) {

				Composite pane = new Composite(parent, SWT.NULL);
				pane.setLayout(new GridLayout(3, false));
				pane.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

				label = new Label(pane, SWT.LEFT);
				label.setText("This is a ControlAligner");
				updateGridData(label);

				controlAligner.add(label);

				return parent;
			}

			@Override
			protected void initializeBounds() {
				super.initializeBounds();
				size[0] = label.getSize().x;
				maximumWidth[0] = controlAligner.getMaximumWidth();
			}
		};

		dialog.create();
		dialog.close();

		assertEquals(
			"The width should be " + size[0] + ",",
			size[0],
			maximumWidth[0]
		);
	}

	@Test
	public void testDialog_AddControl2() throws Exception {

		final int[] maximumWidth = new int[1];
		final int[] sizes = new int[2];

		TitleAreaDialog dialog = new TitleAreaDialog(SWTUtil.getShell()) {

			private Button button;
			private Label label;

			@Override
			protected Control createDialogArea(Composite parent) {

				Composite pane = new Composite(parent, SWT.NULL);
				pane.setLayout(new GridLayout(3, false));
				pane.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

				label = new Label(pane, SWT.NULL);
				label.setText("This is a ControlAligner");
				updateGridData(label);

				controlAligner.add(label);

				button = new Button(pane, SWT.NULL);
				button.setText("Short text");
				updateGridData(button);

				controlAligner.add(button);

				return parent;
			}

			@Override
			protected void initializeBounds() {
				super.initializeBounds();
				sizes[0] = label.getSize().x;
				sizes[1] = button.getSize().x;
				maximumWidth[0] = controlAligner.getMaximumWidth();
			}
		};

		dialog.create();
		dialog.close();

		int labelSize  = sizes[0];
		int buttonSize = sizes[1];
		int max = Math.max(labelSize, buttonSize);

		assertEquals(
			"The width should be " + max + ",",
			max,
			maximumWidth[0]
		);
	}

	@Test
	public void testDispose() throws Exception {

		Composite pane = new Composite(parent, SWT.NULL);
		pane.setLayout(new GridLayout(3, false));
		pane.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		Label label = new Label(pane, SWT.NULL);
		label.setText("This is very long text");
		updateGridData(label);

		Button button = new Button(pane, SWT.NULL);
		button.setText("Short text");
		updateGridData(button);

		controlAligner.add(label);
		controlAligner.add(button);

		Point labelSize  = label.getSize();
		Point buttonSize = button.getSize();
		int max = Math.max(labelSize.x, buttonSize.x);

		assertEquals(
			"The width should be " + max + ",",
			max,
			controlAligner.getMaximumWidth()
		);

		label.dispose();

		Point newButtonSize = button.getSize();

		assertNotSame(
			"The old max and new max should not be the same",
			max,
			newButtonSize.x
		);

		assertEquals(
			"The ControlAligner doesn't have the right maximum width",
			newButtonSize.x,
			controlAligner.getMaximumWidth()
		);
	}

	@Test
	public void testHierarchyOfControlAligners() throws Exception {

		// Aligner1
		//  ^
		//  |-Aligner2
		//     ^
		//     |-Aligner3
		ControlAligner controlAligner2 = new ControlAligner();
		controlAligner.add(controlAligner2);

		ControlAligner controlAligner3 = new ControlAligner();
		controlAligner2.add(controlAligner3);

		// Test 1
		Label label1 = new Label(parent, SWT.NULL);
		label1.setText("This is a label widget");
		parent.layout(true, true);

		int labelWidth1 = label1.getSize().x;
		controlAligner3.add(label1);

		assertEquals(controlAligner3.getMaximumWidth(), labelWidth1);
		assertEquals(controlAligner2.getMaximumWidth(), labelWidth1);
		assertEquals(controlAligner.getMaximumWidth(), labelWidth1);

		// Test 2
		Label label2 = new Label(parent, SWT.NULL);
		label2.setText("ShortLabel");
		controlAligner2.add(label2);
		parent.layout(true);

		int newLabelWidth1 = label1.getSize().x;
		int newLabelWidth2 = label2.getSize().x;

		assertEquals(controlAligner3.getMaximumWidth(), controlAligner2.getMaximumWidth());
		assertEquals(controlAligner2.getMaximumWidth(), controlAligner.getMaximumWidth());
		assertEquals(newLabelWidth1, newLabelWidth2);
		assertEquals(newLabelWidth1, controlAligner.getMaximumWidth());

		// Test 3
		Label label3 = new Label(parent, SWT.NULL);
		label3.setText("A very long label that takes a lot of horizontal space");
//		parent.layout(true);
		controlAligner.add(label3);

		newLabelWidth1 = label1.getSize().x;
		newLabelWidth2 = label2.getSize().x;
		int newLabelWidth3 = label3.getSize().x;

		assertEquals(controlAligner3.getMaximumWidth(), controlAligner2.getMaximumWidth());
		assertEquals(controlAligner2.getMaximumWidth(), controlAligner.getMaximumWidth());
		assertEquals(newLabelWidth1, newLabelWidth2);
		assertEquals(newLabelWidth2, newLabelWidth3);
		assertEquals(newLabelWidth1, controlAligner.getMaximumWidth());

		// Make sure all the locked are removed
		assertEquals(ClassTools.attemptToGetFieldValue(controlAligner, "locked"), Boolean.FALSE);
		assertEquals(ClassTools.attemptToGetFieldValue(controlAligner2, "locked"), Boolean.FALSE);
		assertEquals(ClassTools.attemptToGetFieldValue(controlAligner3, "locked"), Boolean.FALSE);

		// Change the text of label2
		label2.setText("mm");
//		parent.layout(true);

		newLabelWidth1 = label1.getSize().x;
		newLabelWidth2 = label2.getSize().x;
		newLabelWidth3 = label3.getSize().x;

		assertEquals(controlAligner3.getMaximumWidth(), controlAligner2.getMaximumWidth());
		assertEquals(controlAligner2.getMaximumWidth(), controlAligner.getMaximumWidth());
		assertEquals(newLabelWidth1, newLabelWidth2);
		assertEquals(newLabelWidth2, newLabelWidth3);
		assertEquals(newLabelWidth1, controlAligner.getMaximumWidth());

		assertEquals(ClassTools.attemptToGetFieldValue(controlAligner, "locked"), Boolean.FALSE);
		assertEquals(ClassTools.attemptToGetFieldValue(controlAligner2, "locked"), Boolean.FALSE);
		assertEquals(ClassTools.attemptToGetFieldValue(controlAligner3, "locked"), Boolean.FALSE);

		// Change the text of label1
		label1.setText("a");
//		parent.layout(true);

		Composite parent1 = new Composite(SWTUtil.getShell(), SWT.NULL);
		parent1.setLayout(new GridLayout());

		Label tempLabel = new Label(parent1, SWT.NULL);
		tempLabel.setText("a");
//		parent1.layout(true);

		int realWidth = tempLabel.getSize().x;

		newLabelWidth1 = label1.getSize().x;
		newLabelWidth2 = label2.getSize().x;
		newLabelWidth3 = label3.getSize().x;

		assertEquals(controlAligner3.getMaximumWidth(), controlAligner2.getMaximumWidth());
		assertEquals(controlAligner2.getMaximumWidth(), controlAligner.getMaximumWidth());
		assertEquals(newLabelWidth1, newLabelWidth2);
		assertEquals(newLabelWidth2, newLabelWidth3);
		assertEquals(newLabelWidth1, controlAligner.getMaximumWidth());
		assertFalse(newLabelWidth1 == realWidth);

		assertEquals(ClassTools.attemptToGetFieldValue(controlAligner, "locked"), Boolean.FALSE);
		assertEquals(ClassTools.attemptToGetFieldValue(controlAligner2, "locked"), Boolean.FALSE);
		assertEquals(ClassTools.attemptToGetFieldValue(controlAligner3, "locked"), Boolean.FALSE);

		// Change the text of label1
		label1.setText("Yes another big long long text so that all the labels will have to take the size of this label to make sure ControlAligner works correctly");
//		parent.layout(true);

		// Weird: It seems no notification is sent, fire one manually
		Event event  = new Event();
		event.widget = label1;
		event.type   = SWT.Resize;
		label1.notifyListeners(SWT.Resize, event);

		Composite parent2 = new Composite(SWTUtil.getShell(), SWT.NULL);
		parent2.setLayout(new GridLayout());

		tempLabel = new Label(parent2, SWT.NULL);
		tempLabel.setText(label1.getText());
		parent2.layout(true);

		realWidth = tempLabel.getSize().x;

		newLabelWidth1 = label1.getSize().x;
		newLabelWidth2 = label2.getSize().x;
		newLabelWidth3 = label3.getSize().x;

		assertEquals(controlAligner3.getMaximumWidth(), controlAligner2.getMaximumWidth());
		assertEquals(controlAligner2.getMaximumWidth(), controlAligner.getMaximumWidth());
		assertEquals(newLabelWidth1, newLabelWidth2);
		assertEquals(newLabelWidth2, newLabelWidth3);
		assertEquals(controlAligner.getMaximumWidth(), newLabelWidth1);
		assertEquals(realWidth, newLabelWidth1);

		assertEquals(ClassTools.attemptToGetFieldValue(controlAligner, "locked"), Boolean.FALSE);
		assertEquals(ClassTools.attemptToGetFieldValue(controlAligner2, "locked"), Boolean.FALSE);
		assertEquals(ClassTools.attemptToGetFieldValue(controlAligner3, "locked"), Boolean.FALSE);
	}

	@Test
	public void testRemoveControl1() throws Exception {

		Composite pane = new Composite(parent, SWT.NULL);
		pane.setLayout(new GridLayout(3, false));
		pane.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		Button button = new Button(pane, SWT.NULL);
		button.setText("This is a ControlAligner");
		updateGridData(button);

		controlAligner.add(button);
		parent.layout(true, true);

		Point size = button.getSize();

		assertEquals(
			"The width should be " + size.x + ",",
			size.x,
			controlAligner.getMaximumWidth()
		);

		controlAligner.remove(button);

		assertEquals(
			"The width should be 0, ",
			0,
			controlAligner.getMaximumWidth()
		);
	}

	@Test
	public void testRemoveControl2() throws Exception {

		Composite pane = new Composite(parent, SWT.NULL);
		pane.setLayout(new GridLayout(3, false));
		pane.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		Label label = new Label(pane, SWT.NULL);
		label.setText("This is very long text");
		updateGridData(label);

		Button button = new Button(pane, SWT.NULL);
		button.setText("Short text");
		updateGridData(button);
//		parent.layout(true, true);

		controlAligner.add(label);
		controlAligner.add(button);

		Point labelSize  = label.getSize();
		Point buttonSize = button.getSize();
		int max = Math.max(labelSize.x, buttonSize.x);

		assertEquals(
			"The width should be " + max + ",",
			max,
			controlAligner.getMaximumWidth()
		);

		controlAligner.remove(label);

		Point newButtonSize = button.getSize();

		assertNotSame(
			"The old max and new max should not be the same",
			max,
			newButtonSize.x
		);

		assertEquals(
			"The ControlAligner doesn't have the right maximum width",
			newButtonSize.x,
			controlAligner.getMaximumWidth()
		);
	}

	@Test
	public void testRemoveControl4() throws Exception {

		Composite pane = new Composite(parent, SWT.NULL);
		pane.setLayout(new GridLayout(3, false));
		pane.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		// Widget 1
		Label label = new Label(pane, SWT.NULL);
		label.setText("This is very long text");
		updateGridData(label);
		controlAligner.add(label);

		// Widget 2
		Composite spacer = new Composite(pane, SWT.NULL);
		spacer.setLayout(buildSpacerLayout());
		updateGridData(spacer);
		controlAligner.add(spacer);

		// Widget 3
		Button button = new Button(pane, SWT.NULL);
		button.setText("Short text");
		updateGridData(button);
		controlAligner.add(button);

//		parent.layout(true, true);

		// Make sure the 3 widgets have the same width
		Point labelSize  = label.getSize();
		Point spacerSize = spacer.getSize();
		Point buttonSize = button.getSize();
		int max = Math.max(labelSize.x, buttonSize.x);
		max = Math.max(max, spacerSize.x);

		assertEquals(
			"The width should be " + max + ",",
			max,
			controlAligner.getMaximumWidth()
		);

		assertEquals(
			"The spacer's width should be " + max + ",",
			max,
			spacerSize.x
		);

		// Remove the label (the widest widget) and make sure the width was
		// correctly calculated
		controlAligner.remove(label);

		spacerSize = spacer.getSize();
		buttonSize = button.getSize();
		int max2 = Math.max(spacerSize.x, buttonSize.x);

		assertNotSame(
			"The old max and new max should not be the same",
			max,
			max2
		);

		assertEquals(
			"The ControlAligner doesn't have the right maximum width",
			max2,
			controlAligner.getMaximumWidth()
		);

		assertEquals(
			"The spacer's width should have been adjusted",
			max2,
			spacerSize.x
		);
	}

	@Test
	public void testRemoveControlAligner1() throws Exception {

		Label label1 = new Label(parent, SWT.NULL);
		Label label2 = new Label(parent, SWT.NULL);

		updateGridData(label1);
		updateGridData(label2);

		controlAligner.add(label1);

		ControlAligner controlAligner2 = new ControlAligner();
		controlAligner.add(controlAligner2);
		controlAligner2.add(label2);

		label1.setText("This is a ControlAligner");
		label2.setText("This is a very long ControlAligner");
//		parent.layout(true, true);

		Point size1 = label1.getSize();
		Point size2 = label2.getSize();
		int width = Math.max(size1.x, size2.x);

		// Test 1
		assertEquals(
			"The width should be " + width + ",",
			width,
			controlAligner.getMaximumWidth()
		);

		assertEquals(
			"The width should be " + width + ",",
			width,
			controlAligner2.getMaximumWidth()
		);

		// Test 2
		controlAligner.remove(label1);

		width = label2.getSize().x;

		assertEquals(
			"The width should be " + width + ",",
			width,
			controlAligner.getMaximumWidth()
		);

		assertEquals(
			"The width should be " + width + ",",
			width,
			controlAligner2.getMaximumWidth()
		);
	}

	@Test
	public void testRemoveControlAligner2() throws Exception {

		Label label1 = new Label(parent, SWT.NULL);
		Label label2 = new Label(parent, SWT.NULL);

		updateGridData(label1);
		updateGridData(label2);

		controlAligner.add(label1);

		ControlAligner controlAligner2 = new ControlAligner();
		controlAligner.add(controlAligner2);
		controlAligner2.add(label2);

		label1.setText("This is a ControlAligner");
		label2.setText("This is a very long ControlAligner");
//		parent.layout(true, true);

		Point size1 = label1.getSize();
		Point size2 = label2.getSize();
		int width = Math.max(size1.x, size2.x);

		// Test 1
		assertEquals(
			"The width should be " + width + ",",
			width,
			controlAligner.getMaximumWidth()
		);

		assertEquals(
			"The width should be " + width + ",",
			width,
			controlAligner2.getMaximumWidth()
		);

		// Test 2
		controlAligner2.remove(label2);

		width = label1.getSize().x;

		assertEquals(
			"The width should be " + width + ",",
			width,
			controlAligner.getMaximumWidth()
		);

		assertEquals(
			"The width should be " + width + ",",
			width,
			controlAligner2.getMaximumWidth()
		);
	}

	private void updateGridData(Control control) {
		GridData data = new GridData();
		data.horizontalAlignment       = GridData.FILL;
		data.grabExcessHorizontalSpace = false;
		control.setLayoutData(data);
	}
}