/*******************************************************************************
 * Copyright (c) 2007, 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.internal.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import org.eclipse.core.runtime.Assert;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;

/**
 * This class is responsible to set a preferred width on the registered widgets
 * (either <code>Control</code> or <code>ControlAligner</code>) based on the
 * widest widget.
 * <p>
 * Important: The layout data has to be a <code>GridData</code>. If none is set,
 * then a new <code>GridData</code> is automatically created.
 * <p>
 * Here an example of the result if this aligner is used to align controls
 * within either one or two group boxes, the controls added are the labels in
 * this case. It is also possible to align controls on the right side of the
 * main component, a spacer can be used for extra space.
 * <p>
 * Here's an example:
 * <pre>
 * - Group Box 1 ---------------------------------------------------------------
 * |                     -------------------------------------- -------------- |
 * | Name:               | I                                  | | Browsse... | |
 * |                     -------------------------------------- -------------- |
 * |                     ---------                                             |
 * | Preallocation Size: |     |I|                                             |
 * |                     ---------                                             |
 * |                     --------------------------------------                |
 * | Descriptor:         |                                  |v|                |
 * |                     --------------------------------------                |
 * -----------------------------------------------------------------------------
 *
 * - Group Box 2 ---------------------------------------------------------------
 * |                     --------------------------------------                |
 * | Mapping Type:       |                                  |V|                |
 * |                     --------------------------------------                |
 * |                     --------------------------------------                |
 * | Check in Script:    | I                                  |                |
 * |                     --------------------------------------                |
 * -----------------------------------------------------------------------------</pre>
 *
 * @version 2.0
 * @since 2.0
 */
@SuppressWarnings("nls")
public final class ControlAligner
{
	/**
	 * Flag used to prevent a validation so it can be done after an operation
	 * completed.
	 */
	private boolean autoValidate;

	/**
	 * The utility class used to support bound properties.
	 */
	private Collection<Listener> changeSupport;

	/**
	 * The listener added to each of the controls that listens only to a text
	 * change.
	 */
	private Listener listener;

	/**
	 * Prevents infinite recursion when recalculating the preferred width.
	 * This happens in an hierarchy of <code>ControlAligner</code>s. The lock
	 * has to be placed here and not in the {@link ControlAlignerWrapper}.
	 */
	private boolean locked;

	/**
	 * The length of the widest control. If the length was not calculated, then
	 * this value is 0.
	 */
	private int maximumWidth;

	/**
	 * The collection of {@link Wrapper}s encapsulating either <code>Control</code>s
	 * or {@link ControlAligner}s.
	 */
	private Collection<Wrapper> wrappers;

	/**
	 * A null-<code>Point</code> object used to clear the preferred size.
	 */
	private static final Point DEFAULT_SIZE = new Point(SWT.DEFAULT, SWT.DEFAULT);

	/**
	 * The types of events to listen in order to properly adjust the size of all
	 * the widgets.
	 */
	private static final int[] EVENT_TYPES = {
		SWT.Dispose,
		SWT.Hide,
		SWT.Resize,
		SWT.Show
	};

	/**
	 * Creates a new <code>ControlAligner</code>.
	 */
	public ControlAligner() {
		super();
		initialize();
	}

	/**
	 * Creates a new <code>ControlAligner</code>.
	 *
	 * @param controls The collection of <code>Control</code>s
	 */
	public ControlAligner(Collection<? extends Control> controls) {
		this();
		addAllControls(controls);
	}

	/**
	 * Adds the given control. Its width will be used along with the width of all
	 * the other registered controls in order to get the greater witdh and use
	 * it as the width for all the controls.
	 *
	 * @param control The <code>Control</code> to be added
	 */
	public void add(Control control) {

		Assert.isNotNull(control, "Can't add null to this ControlAligner");

		Wrapper wrapper = buildWrapper(control);
		wrapper.addListener(listener);
		wrappers.add(wrapper);

		revalidate(false);
	}

	/**
	 * Adds the given control. Its width will be used along with the width of all
	 * the other registered controls in order to get the greater witdh and use
	 * it as the width for all the controls.
	 *
	 * @param controlAligner The <code>ControlAligner</code> to be added
	 * @exception IllegalArgumentException Can't add the <code>ControlAligner</code>
	 * to itself
	 */
	public void add(ControlAligner controlAligner) {

		Assert.isNotNull(controlAligner, "Can't add null to this ControlAligner");
		Assert.isLegal(controlAligner != this, "Can't add the ControlAligner to itself");

		Wrapper wrapper = buildWrapper(controlAligner);
		wrapper.addListener(listener);
		wrappers.add(wrapper);

		if (!controlAligner.wrappers.isEmpty()) {
			revalidate(false);
		}
	}

	/**
	 * Adds the items contained in the given collection into this
	 * <code>ControlAligner</code>. The preferred width of each item will be
	 * used along with the width of all the other items in order to get the
	 * widest control and use its width as the width for all the controls.
	 *
	 * @param aligners The collection of <code>ControlAligner</code>s
	 */
	public void addAllControlAligners(Collection<ControlAligner> aligners) {

		// Deactivate the auto validation while adding all the Controls and/or
		// ControlAligners in order to improve performance
		boolean oldAutoValidate = autoValidate;
		autoValidate = false;

		for (ControlAligner aligner : aligners) {
			add(aligner);
		}

		autoValidate = oldAutoValidate;
		revalidate(false);
	}

   /**
	 * Adds the items contained in the given collection into this
	 * <code>ControlAligner</code>. The preferred width of each item will be
	 * used along with the width of all the other items in order to get the
	 * widest control and use its width as the width for all the controls.
	 *
	 * @param controls The collection of <code>Control</code>s
	 */
	public void addAllControls(Collection<? extends Control> controls) {

		// Deactivate the auto validation while adding all the Controls and/or
		// ControlAligners in order to improve performance
		boolean oldAutoValidate = autoValidate;
		autoValidate = false;

		for (Control control : controls) {
			add(control);
		}

		autoValidate = oldAutoValidate;
		revalidate(false);
	}

   /**
	 * Adds the given <code>ControListener</code>.
	 *
	 * @param listener The <code>Listener</code> to be added
	 */
	private void addListener(Listener listener) {

		if (changeSupport == null) {
		    changeSupport = new ArrayList<Listener>();
		}

		changeSupport.add(listener);
   }

	/**
	 * Creates a new <code>Wrapper</code> that encapsulates the given source.
	 *
	 * @param control The control to be wrapped
	 * @return A new {@link Wrapper}
	 */
	private Wrapper buildWrapper(Control control) {
		return new ControlWrapper(control);
	}

   /**
	 * Creates a new <code>Wrapper</code> that encapsulates the given source.
	 *
	 * @param ControlAligner The <code>ControlAligner</code> to be wrapped
	 * @return A new {@link ControlAlignerWrapper}
	 */
	private Wrapper buildWrapper(ControlAligner ControlAligner) {
		return new ControlAlignerWrapper(ControlAligner);
	}

	/**
	 * Calculates the width taken by the widgets and returns the maximum width.
	 *
	 * @param recalculateSize <code>true</code> to recalculate the preferred size
	 * of all the wrappers contained within them rather than using the cached
	 * size; <code>false</code> to use the cached size
	 */
	private int calculateWidth(boolean recalculateSize) {

		int width = 0;

		for (Wrapper wrapper : wrappers) {
			Point size = wrapper.cachedSize();

			// The size has not been calculated yet
			if (recalculateSize || (size.x == 0)) {
				size = wrapper.calculateSize();
			}

			// Only keep the greatest width
			width = Math.max(size.x, width);
		}

		return width;
	}

	/**
	 * Reports a bound property change.
	 *
	 * @param oldValue the old value of the property (as an int)
	 * @param newValue the new value of the property (as an int)
	 */
	private void controlResized(int oldValue, int newValue) {

		if ((changeSupport != null) && (oldValue != newValue)) {
			Event event  = new Event();
			event.widget = SWTUtil.getShell();
			event.data   = this;

			for (Listener listener : changeSupport) {
				listener.handleEvent(event);
			}
		}
	}

	/**
	 * Disposes this <code>ControlAligner</code>, this can improve the speed of
	 * disposing a pane. When a pane is disposed, this aligner doesn't need to
	 * revalidate its size upon dispose of its widgets.
	 */
	public void dispose() {

		for (Iterator<Wrapper> iter = wrappers.iterator(); iter.hasNext(); ) {
			Wrapper wrapper = iter.next();
			wrapper.removeListener(listener);
			iter.remove();
		}

		this.wrappers.clear();
	}

	/**
	 * Returns the length of the widest control. If the length was not
	 * calculated, then this value is 0.
	 *
	 * @return The width of the widest control or 0 if the length has not been
	 * calculated yet
	 */
	public int getMaximumWidth() {
		return maximumWidth;
	}

	/**
	 * Initializes this <code>ControlAligner</code>.
	 */
	private void initialize() {

		this.autoValidate = true;
		this.maximumWidth = 0;
		this.listener     = new ListenerHandler();
		this.wrappers     = new ArrayList<Wrapper>();
	}

	/**
	 * Invalidates the size of the given object.
	 *
	 * @param source The source object to be invalidated
	 */
	private void invalidate(Object source) {

		Wrapper wrapper = retrieveWrapper(source);

		if (!wrapper.locked()) {
			Point size = wrapper.cachedSize();
			size.x = size.y = 0;
			wrapper.setSize(DEFAULT_SIZE);
		}
	}

	/**
	 * Updates the maximum length based on the widest control. This methods
	 * does not update the width of the controls.
	 *
	 * @param recalculateSize <code>true</code> to recalculate the preferred size
	 * of all the wrappers contained within them rather than using the cached
	 * size; <code>false</code> to use the cached size
	 */
	private void recalculateWidth(boolean recalculateSize) {

		int width = calculateWidth(recalculateSize);

		try {
			locked = true;
			setMaximumWidth(width);
		}
		finally {
			locked = false;
		}
	}

	/**
	 * Removes the given control. Its preferred width will not be used when
	 * calculating the preferred width.
	 *
	 * @param control The control to be removed
	 * @exception AssertionFailedException If the given <code>Control</code> is
	 * <code>null</code>
	 */
	public void remove(Control control) {

		Assert.isNotNull(control, "The Control to remove cannot be null");

		Wrapper wrapper = retrieveWrapper(control);
		wrapper.removeListener(listener);
		wrappers.remove(wrapper);

		revalidate(true);
	}

	/**
	 * Removes the given <code>ControlAligner</code>. Its preferred width
	 * will not be used when calculating the preferred witdh.
	 *
	 * @param controlAligner The <code>ControlAligner</code> to be removed
	 * @exception AssertionFailedException If the given <code>ControlAligner</code>
	 * is <code>null</code>
	 */
	public void remove(ControlAligner controlAligner) {

		Assert.isNotNull(controlAligner, "The ControlAligner to remove cannot be null");

		Wrapper wrapper = retrieveWrapper(controlAligner);
		wrapper.removeListener(listener);
		wrappers.remove(wrapper);

		revalidate(true);
	}

	/**
	 * Removes the given <code>Listener</code>.
	 *
	 * @param listener The <code>Listener</code> to be removed
	 */
	private void removeListener(Listener listener) {

		changeSupport.remove(listener);

		if (changeSupport.isEmpty()) {
			changeSupport = null;
		}
	}

	/**
	 * Retrieves the <code>Wrapper</code> that is encapsulating the given object.
	 *
	 * @param source Either a <code>Control</code> or a <code>ControlAligner</code>
	 * @return Its <code>Wrapper</code>
	 */
	private Wrapper retrieveWrapper(Object source) {

		for (Wrapper wrapper : wrappers) {
			if (wrapper.source() == source) {
				return wrapper;
			}
		}

		throw new IllegalArgumentException("Can't retrieve the Wrapper for " + source);
	}

	/**
	 * If the count of control is greater than one and {@link #isAutoValidate()}
	 * returns <code>true</code>, then the size of all the registered
	 * <code>Control</code>s will be udpated.
	 *
	 * @param recalculateSize <code>true</code> to recalculate the preferred size
	 * of all the wrappers contained within them rather than using the cached
	 * size; <code>false</code> to use the cached size
	 */
	private void revalidate(boolean recalculateSize) {

		if (autoValidate) {
			recalculateWidth(recalculateSize);
			updateWrapperSize(recalculateSize);
		}
	}

	/**
	 * Bases on the information contained in the given <code>Event</code>,
	 * resize the controls.
	 *
	 * @param event The <code>Event</code> sent by the UI thread when the state
	 * of a widget changed
	 */
	private void revalidate(Event event) {

		// We don't need to revalidate during a revalidation process
		if (locked) {
			return;
		}

		Object source;

		if (event.widget != SWTUtil.getShell()) {
			source = event.widget;
			Control control = (Control) source;

			// When a dialog is opened, we need to actually force a layout of
			// the controls, this is required because the control is actually
			// not visible when the preferred width is caculated
			if (control == control.getShell()) {
				if (event.type == SWT.Dispose) {
					return;
				}

				source = null;
			}
		}
		else {
			source = event.data;
		}

		// Either remove the ControlWrapper if the widget was disposed or
		// invalidate the widget in order to recalculate the preferred size
		if (source != null) {
			if (event.type == SWT.Dispose) {
				Wrapper wrapper = retrieveWrapper(source);
				wrappers.remove(wrapper);
			}
			else {
				invalidate(source);
			}
		}

		// Now revalidate all the Controls and ControlAligners
		revalidate(true);
	}

	/**
	 * Sets the length of the widest control. If the length was not calulcated,
	 * then this value is 0.
	 *
	 * @param maximumWidth The width of the widest control
	 */
	private void setMaximumWidth(int maximumWidth) {

		int oldMaximumWidth = this.maximumWidth;
		this.maximumWidth = maximumWidth;
		controlResized(oldMaximumWidth, maximumWidth);
	}

	/**
	 * Returns a string representation of this <code>ControlAligner</code>.
	 *
	 * @return Information about this object
	 */
	@Override
	public String toString() {

		StringBuffer sb = new StringBuffer();
		sb.append("maximumWidth=");
		sb.append(maximumWidth);
		sb.append(", wrappers=");
		sb.append(wrappers);
		return StringTools.buildToStringFor(this, sb);
	}

	/**
	 * Updates the size of every <code>Wrapper</code> based on the maximum width.
	 *
	 * @param forceRevalidate <code>true</code> to revalidate the wrapper's size
	 * even though its current size might be the same as the maximum width;
	 * <code>false</code> to only revalidate the wrappers with a different width
	 */
	private void updateWrapperSize(boolean forceRevalidate) {

		for (Wrapper wrapper : wrappers) {
			Point cachedSize = wrapper.cachedSize();

			// No need to change the size of the wrapper since it's always using
			// the maximum width
			if (forceRevalidate || (cachedSize.x != maximumWidth)) {
				Point size = new Point(maximumWidth, cachedSize.y);
				wrapper.setSize(size);
			}
		}
	}

	/**
	 * This <code>Wrapper</code> encapsulates a {@link ControlAligner}.
	 */
	private class ControlAlignerWrapper implements Wrapper {
		/**
		 * The cached size, which is {@link ControlAligner#maximumWidth}.
		 */
		private final Point cachedSize;

		/**
		 * The <code>ControlAligner</code> encapsulated by this
		 * <code>Wrapper</code>.
		 */
		private final ControlAligner controlAligner;

		/**
		 * Creates a new <code>ControlAlignerWrapper</code> that encapsulates
		 * the given <code>ControlAligner</code>.
		 *
		 * @param controlAligner The <code>ControlAligner</code> to be
		 * encapsulated by this <code>Wrapper</code>
		 */
		private ControlAlignerWrapper(ControlAligner controlAligner) {
			super();
			this.controlAligner = controlAligner;
			this.cachedSize     = new Point(controlAligner.maximumWidth, 0);
		}

		/*
		 * (non-Javadoc)
		 */
		public void addListener(Listener listener) {
			controlAligner.addListener(listener);
		}

		/*
		 * (non-Javadoc)
		 */
		public Point cachedSize() {
			cachedSize.x = controlAligner.maximumWidth;
			return cachedSize;
		}

		/*
		 * (non-Javadoc)
		 */
		public Point calculateSize() {

			Point size = new Point(controlAligner.calculateWidth(false), 0);

			if (size.x != SWT.DEFAULT) {
				cachedSize.x = size.x;
			}
			else {
				cachedSize.x = 0;
			}

			if (size.y != SWT.DEFAULT) {
				cachedSize.y = size.y;
			}
			else {
				cachedSize.y = 0;
			}

			return size;
		}

		/*
		 * (non-Javadoc)
		 */
		public boolean locked() {
			return controlAligner.locked;
		}

		/*
		 * (non-Javadoc)
		 */
		public void removeListener(Listener listener) {
			controlAligner.removeListener(listener);
		}

		/*
		 * (non-Javadoc)
		 */
		public void setSize(Point size) {

			if (size == DEFAULT_SIZE) {
				controlAligner.maximumWidth = 0;
			}
			else if (controlAligner.maximumWidth != size.x) {
				controlAligner.maximumWidth = size.x;
				controlAligner.updateWrapperSize(true);
			}
		}

		/*
		 * (non-Javadoc)
		 */
		public Object source() {
			return controlAligner;
		}

		/*
		 * (non-Javadoc)
		 */
		@Override
		public String toString() {

			StringBuffer sb = new StringBuffer();
			sb.append("Cached size=");
			sb.append(cachedSize);
			sb.append(", ControlAligner=");
			sb.append(controlAligner);
			return StringTools.buildToStringFor(this, sb);
		}
	}

	/**
	 * This <code>Wrapper</code> encapsulates a {@link Control}.
	 */
	private class ControlWrapper implements Wrapper {
		/**
		 * The cached size, which is control's size.
		 */
		private Point cachedSize;

		/**
		 * The control to be encapsulated by this <code>Wrapper</code>.
		 */
		private final Control control;

		/**
		 * Creates a new <code>controlWrapper</code> that encapsulates the given
		 * control.
		 *
		 * @param control The control to be encapsulated by this <code>Wrapper</code>
		 */
		private ControlWrapper(Control control) {
			super();

			this.control    = control;
			this.cachedSize = new Point(0, 0);
		}

		/*
		 * (non-Javadoc)
		 */
		public void addListener(Listener listener) {

			for (int eventType : EVENT_TYPES) {
				control.addListener(eventType, listener);
			}
		}

		/*
		 * (non-Javadoc)
		 */
		public Point cachedSize() {
			return cachedSize;
		}

		/*
		 * (non-Javadoc)
		 */
		public Point calculateSize() {

			cachedSize = control.computeSize(SWT.DEFAULT, SWT.DEFAULT, true);

			// Update right away the control's GridData
			GridData gridData = (GridData) control.getLayoutData();

			if (gridData == null) {
				gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
				control.setLayoutData(gridData);
			}

			gridData.widthHint  = cachedSize.x;
			gridData.heightHint = cachedSize.y;

			// Make sure the size is not -1
			if (cachedSize.x == SWT.DEFAULT) {
				cachedSize.x = 0;
			}

			if (cachedSize.y == SWT.DEFAULT) {
				cachedSize.y = 0;
			}

			return cachedSize;
		}

		/*
		 * (non-Javadoc)
		 */
		public boolean locked() {
			return false;
		}

		/*
		 * (non-Javadoc)
		 */
		public void removeListener(Listener listener) {

			for (int eventType : EVENT_TYPES) {
				control.removeListener(eventType, listener);
			}
		}

		/*
		 * (non-Javadoc)
		 */
		public void setSize(Point size) {

			if (control.isDisposed()) {
				return;
			}

			// Update the GridData with the new size
			GridData gridData = (GridData) control.getLayoutData();

			if (gridData == null) {
				gridData = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
				control.setLayoutData(gridData);
			}

			gridData.widthHint  = size.x;
			gridData.heightHint = size.y;

			// Force the control to be resized, and tell its parent to layout
			// its widgets
			if (size.x > 0) {
//				locked = true;
//				try  {
////					control.getParent().layout(new Control[] { control });
//					control.getParent().layout(true);
//				}
//				finally {
//					locked = false;
//				}
				Rectangle bounds = control.getBounds();

				// Only update the control's width if it's
				// different from the current size
				if (bounds.width != size.x) {
					locked = true;

					try {
//						control.setBounds(bounds.x, bounds.y, size.x, size.y);
						control.getParent().layout(true);
					}
					finally
					{
						locked = false;
					}
				}
			}
		}

		/*
		 * (non-Javadoc)
		 */
		public Control source() {
			return control;
		}

		/*
		 * (non-Javadoc)
		 */
		@Override
		public String toString() {

			StringBuffer sb = new StringBuffer();
			sb.append("Cached size=");
			sb.append(cachedSize);
			sb.append(", Control=");
			sb.append(control);
			return StringTools.buildToStringFor(this, sb);
		}
	}

	/**
	 * The listener added to each of the control that is notified in order to
	 * revalidate the preferred size.
	 */
	private class ListenerHandler implements Listener {
		public void handleEvent(Event event) {
			ControlAligner.this.revalidate(event);
		}
	}

	/**
	 * This <code>Wrapper</code> helps to encapsulate heterogeneous objects and
	 * apply the same behavior on them.
	 */
	private interface Wrapper {
	   /**
		 * Adds the given <code>Listener</code> to wrapped object in order to
		 * receive notification when its property changed.
		 *
		 * @param listener The <code>Listener</code> to be added
		 */
		void addListener(Listener listener);

		/**
		 * Returns the cached size of the encapsulated source.
		 *
		 * @return A non-<code>null</code> <code>Point</code> where the x is the
		 * width and the y is the height of the widget
		 */
		Point cachedSize();

		/**
		 * Calculates the preferred size the wrapped object would take by itself.
		 *
		 * @return The calculated size
		 */
		Point calculateSize();

		/**
		 * Prevents infinite recursion when recalculating the preferred width.
		 * This happens in an hierarchy of <code>ControlAligner</code>s.
		 *
		 * @return <code>true</code> to prevent this <code>Wrapper</code> from
		 * being invalidated; otherwise <code>false</code>
		 */
		boolean locked();

		/**
		 * Removes the given <code>Listener</code>.
		 *
		 * @param listener The <code>Listener</code> to be removed
		 */
		void removeListener(Listener listener);

		/**
		 * Sets the size on the encapsulated source.
		 *
		 * @param size The new size
		 */
		void setSize(Point size);

		/**
		 * Returns the encapsulated object.
		 *
		 * @return The object that is been wrapped
		 */
		Object source();
	}
}