/*******************************************************************************
 * Copyright (c) 2007 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 ******************************************************************************/

package org.eclipse.ui.internal.forms;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;

import org.eclipse.jface.dialogs.IMessageProvider;
import org.eclipse.jface.fieldassist.ControlDecoration;
import org.eclipse.jface.fieldassist.FieldDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Label;
import org.eclipse.ui.forms.IMessage;
import org.eclipse.ui.forms.IMessageManager;
import org.eclipse.ui.forms.IMessagePrefixProvider;
import org.eclipse.ui.forms.widgets.Hyperlink;
import org.eclipse.ui.forms.widgets.ScrolledForm;

/**
 * @see IMessageManager
 */

public class MessageManager implements IMessageManager {
	private static final DefaultPrefixProvider DEFAULT_PREFIX_PROVIDER = new DefaultPrefixProvider();
	private ArrayList messages = new ArrayList();
	private Hashtable decorators = new Hashtable();
	private boolean autoUpdate = true;
	private ScrolledForm scrolledForm;
	private IMessagePrefixProvider prefixProvider = DEFAULT_PREFIX_PROVIDER;
	private int decorationPosition = SWT.LEFT | SWT.BOTTOM;
	private static FieldDecoration standardError = FieldDecorationRegistry
			.getDefault().getFieldDecoration(FieldDecorationRegistry.DEC_ERROR);
	private static FieldDecoration standardWarning = FieldDecorationRegistry
			.getDefault().getFieldDecoration(
					FieldDecorationRegistry.DEC_WARNING);

	private static final String[] SINGLE_MESSAGE_SUMMARY_KEYS = {
			Messages.MessageManager_sMessageSummary,
			Messages.MessageManager_sMessageSummary,
			Messages.MessageManager_sWarningSummary,
			Messages.MessageManager_sErrorSummary };

	private static final String[] MULTIPLE_MESSAGE_SUMMARY_KEYS = {
			Messages.MessageManager_pMessageSummary,
			Messages.MessageManager_pMessageSummary,
			Messages.MessageManager_pWarningSummary,
			Messages.MessageManager_pErrorSummary };

	static class Message implements IMessage {
		Control control;
		Object data;
		Object key;
		String message;
		int type;
		String prefix;

		Message(Object key, String message, int type, Object data) {
			this.key = key;
			this.message = message;
			this.type = type;
			this.data = data;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.jface.dialogs.IMessage#getKey()
		 */
		public Object getKey() {
			return key;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.jface.dialogs.IMessageProvider#getMessage()
		 */
		public String getMessage() {
			return message;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.jface.dialogs.IMessageProvider#getMessageType()
		 */
		public int getMessageType() {
			return type;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.ui.forms.messages.IMessage#getControl()
		 */
		public Control getControl() {
			return control;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.ui.forms.messages.IMessage#getData()
		 */
		public Object getData() {
			return data;
		}

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.ui.forms.messages.IMessage#getPrefix()
		 */
		public String getPrefix() {
			return prefix;
		}
	}

	static class DefaultPrefixProvider implements IMessagePrefixProvider {

		public String getPrefix(Control c) {
			Composite parent = c.getParent();
			Control[] siblings = parent.getChildren();
			for (int i = 0; i < siblings.length; i++) {
				if (siblings[i] == c) {
					// this is us - go backward until you hit
					// a label-like widget
					for (int j = i - 1; j >= 0; j--) {
						Control label = siblings[j];
						String ltext = null;
						if (label instanceof Label) {
							ltext = ((Label) label).getText();
						} else if (label instanceof Hyperlink) {
							ltext = ((Hyperlink) label).getText();
						} else if (label instanceof CLabel) {
							ltext = ((CLabel) label).getText();
						}
						if (ltext != null) {
							if (!ltext.endsWith(":")) //$NON-NLS-1$
								return ltext + ": "; //$NON-NLS-1$
							return ltext + " "; //$NON-NLS-1$
						}
					}
					break;
				}
			}
			return null;
		}
	}

	class ControlDecorator {
		private ControlDecoration decoration;
		private ArrayList controlMessages = new ArrayList();
		private String prefix;

		ControlDecorator(Control control) {
			this.decoration = new ControlDecoration(control, decorationPosition, scrolledForm.getBody());
		}

		public boolean isDisposed() {
			return decoration.getControl() == null;
		}

		void updatePrefix() {
			prefix = null;
		}

		void updatePosition() {
			Control control = decoration.getControl();
			decoration.dispose();
			this.decoration = new ControlDecoration(control, decorationPosition, scrolledForm.getBody());
			update();
		}

		String getPrefix() {
			if (prefix == null)
				createPrefix();
			return prefix;
		}

		private void createPrefix() {
			if (prefixProvider == null) {
				prefix = ""; //$NON-NLS-1$
				return;
			}
			prefix = prefixProvider.getPrefix(decoration.getControl());
			if (prefix == null)
				// make a prefix anyway
				prefix = ""; //$NON-NLS-1$
		}

		void addAll(ArrayList target) {
			target.addAll(controlMessages);
		}

		void addMessage(Object key, String text, Object data, int type) {
			Message message = MessageManager.this.addMessage(getPrefix(), key,
					text, data, type, controlMessages);
			message.control = decoration.getControl();
			if (isAutoUpdate())
				update();
		}

		boolean removeMessage(Object key) {
			Message message = findMessage(key, controlMessages);
			if (message != null) {
				controlMessages.remove(message);
				if (isAutoUpdate())
					update();
			}
			return message != null;
		}

		boolean removeMessages() {
			if (controlMessages.isEmpty())
				return false;
			controlMessages.clear();
			if (isAutoUpdate())
				update();
			return true;
		}

		public void update() {
			if (controlMessages.isEmpty()) {
				decoration.setDescriptionText(null);
				decoration.hide();
			} else {
				ArrayList peers = createPeers(controlMessages);
				int type = ((IMessage) peers.get(0)).getMessageType();
				String description = createDetails(createPeers(peers), true);
				if (type == IMessageProvider.ERROR)
					decoration.setImage(standardError.getImage());
				else if (type == IMessageProvider.WARNING)
					decoration.setImage(standardWarning.getImage());
				decoration.setDescriptionText(description);
				decoration.show();
			}
		}
	}

	/**
	 * Creates a new instance of the message manager that will work with the
	 * provided form.
	 * 
	 * @param scrolledForm
	 *            the form to control
	 */
	public MessageManager(ScrolledForm scrolledForm) {
		this.scrolledForm = scrolledForm;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.forms.IMessageManager#addMessage(java.lang.Object,
	 *      java.lang.String, int)
	 */
	public void addMessage(Object key, String messageText, Object data, int type) {
		addMessage(null, key, messageText, data, type, messages);
		if (isAutoUpdate())
			updateForm();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.forms.IMessageManager#addMessage(java.lang.Object,
	 *      java.lang.String, int, org.eclipse.swt.widgets.Control)
	 */
	public void addMessage(Object key, String messageText, Object data,
			int type, Control control) {
		ControlDecorator dec = (ControlDecorator) decorators.get(control);

		if (dec == null) {
			dec = new ControlDecorator(control);
			decorators.put(control, dec);
		}
		dec.addMessage(key, messageText, data, type);
		if (isAutoUpdate())
			updateForm();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.forms.IMessageManager#removeMessage(java.lang.Object)
	 */
	public void removeMessage(Object key) {
		Message message = findMessage(key, messages);
		if (message != null) {
			messages.remove(message);
			if (isAutoUpdate())
				updateForm();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.forms.IMessageManager#removeMessages()
	 */
	public void removeMessages() {
		if (!messages.isEmpty()) {
			messages.clear();
			if (isAutoUpdate())
				updateForm();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.forms.IMessageManager#removeMessage(java.lang.Object,
	 *      org.eclipse.swt.widgets.Control)
	 */
	public void removeMessage(Object key, Control control) {
		ControlDecorator dec = (ControlDecorator) decorators.get(control);
		if (dec == null)
			return;
		if (dec.removeMessage(key))
			if (isAutoUpdate())
				updateForm();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.forms.IMessageManager#removeMessages(org.eclipse.swt.widgets.Control)
	 */
	public void removeMessages(Control control) {
		ControlDecorator dec = (ControlDecorator) decorators.get(control);
		if (dec != null) {
			if (dec.removeMessages()) {
				if (isAutoUpdate())
					updateForm();
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.forms.IMessageManager#removeAllMessages()
	 */
	public void removeAllMessages() {
		boolean needsUpdate = false;
		for (Enumeration enm = decorators.elements(); enm.hasMoreElements();) {
			ControlDecorator control = (ControlDecorator) enm.nextElement();
			if (control.removeMessages())
				needsUpdate = true;
		}
		if (!messages.isEmpty()) {
			messages.clear();
			needsUpdate = true;
		}
		if (needsUpdate && isAutoUpdate())
			updateForm();
	}

	/*
	 * Adds the message if it does not already exist in the provided list.
	 */

	private Message addMessage(String prefix, Object key, String messageText,
			Object data, int type, ArrayList list) {
		Message message = findMessage(key, list);
		if (message == null) {
			message = new Message(key, messageText, type, data);
			message.prefix = prefix;
			list.add(message);
		} else {
			message.message = messageText;
			message.type = type;
			message.data = data;
		}
		return message;
	}

	/*
	 * Finds the message with the provided key in the provided list.
	 */

	private Message findMessage(Object key, ArrayList list) {
		for (int i = 0; i < list.size(); i++) {
			Message message = (Message) list.get(i);
			if (message.getKey().equals(key))
				return message;
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.forms.IMessageManager#update()
	 */
	public void update() {
		// Update decorations
		for (Iterator iter = decorators.values().iterator(); iter.hasNext();) {
			ControlDecorator dec = (ControlDecorator) iter.next();
			dec.update();
		}
		// Update the form
		updateForm();
	}

	/*
	 * Updates the container by rolling the messages up from the controls.
	 */

	private void updateForm() {
		ArrayList mergedList = new ArrayList();
		mergedList.addAll(messages);
		for (Enumeration enm = decorators.elements(); enm.hasMoreElements();) {
			ControlDecorator dec = (ControlDecorator) enm.nextElement();
			dec.addAll(mergedList);
		}
		update(mergedList);
	}

	private void update(ArrayList mergedList) {
		pruneControlDecorators();
		if (mergedList.isEmpty() || mergedList == null) {
			scrolledForm.setMessage(null, IMessageProvider.NONE);
			return;
		}
		ArrayList peers = createPeers(mergedList);
		int maxType = ((IMessage) peers.get(0)).getMessageType();
		String messageText;
		IMessage[] array = (IMessage[]) peers
				.toArray(new IMessage[peers.size()]);
		if (peers.size() == 1 && ((Message) peers.get(0)).prefix == null) {
			// a single message
			IMessage message = (IMessage) peers.get(0);
			messageText = message.getMessage();
			scrolledForm.setMessage(messageText, maxType, array);
		} else {
			// show a summary message for the message
			// and list of errors for the details
			if (peers.size() > 1)
				messageText = Messages.bind(
						MULTIPLE_MESSAGE_SUMMARY_KEYS[maxType],
						new String[] { peers.size() + "" }); //$NON-NLS-1$
			else
				messageText = SINGLE_MESSAGE_SUMMARY_KEYS[maxType];
			scrolledForm.setMessage(messageText, maxType, array);
		}
	}

	private static String getFullMessage(IMessage message) {
		if (message.getPrefix() == null)
			return message.getMessage();
		return message.getPrefix() + message.getMessage();
	}

	private ArrayList createPeers(ArrayList messages) {
		ArrayList peers = new ArrayList();
		int maxType = 0;
		for (int i = 0; i < messages.size(); i++) {
			Message message = (Message) messages.get(i);
			if (message.type > maxType) {
				peers.clear();
				maxType = message.type;
			}
			if (message.type == maxType)
				peers.add(message);
		}
		return peers;
	}

	private String createDetails(ArrayList messages, boolean excludePrefix) {
		StringWriter sw = new StringWriter();
		PrintWriter out = new PrintWriter(sw);

		for (int i = 0; i < messages.size(); i++) {
			if (i > 0)
				out.println();
			IMessage m = (IMessage) messages.get(i);
			out.print(excludePrefix ? m.getMessage() : getFullMessage(m));
		}
		out.flush();
		return sw.toString();
	}

	public static String createDetails(IMessage[] messages) {
		if (messages == null || messages.length == 0)
			return null;
		StringWriter sw = new StringWriter();
		PrintWriter out = new PrintWriter(sw);

		for (int i = 0; i < messages.length; i++) {
			if (i > 0)
				out.println();
			out.print(getFullMessage(messages[i]));
		}
		out.flush();
		return sw.toString();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.forms.IMessageManager#createSummary(org.eclipse.ui.forms.IMessage[])
	 */
	public String createSummary(IMessage[] messages) {
		return createDetails(messages);
	}

	private void pruneControlDecorators() {
		for (Iterator iter = decorators.values().iterator(); iter.hasNext();) {
			ControlDecorator dec = (ControlDecorator) iter.next();
			if (dec.isDisposed())
				iter.remove();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.forms.IMessageManager#getMessagePrefixProvider()
	 */
	public IMessagePrefixProvider getMessagePrefixProvider() {
		return prefixProvider;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.forms.IMessageManager#setMessagePrefixProvider(org.eclipse.ui.forms.IMessagePrefixProvider)
	 */
	public void setMessagePrefixProvider(IMessagePrefixProvider provider) {
		this.prefixProvider = provider;
		for (Iterator iter = decorators.values().iterator(); iter.hasNext();) {
			ControlDecorator dec = (ControlDecorator) iter.next();
			dec.updatePrefix();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.forms.IMessageManager#getDecorationPosition()
	 */
	public int getDecorationPosition() {
		return decorationPosition;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.forms.IMessageManager#setDecorationPosition(int)
	 */
	public void setDecorationPosition(int position) {
		this.decorationPosition = position;
		for (Iterator iter = decorators.values().iterator(); iter.hasNext();) {
			ControlDecorator dec = (ControlDecorator) iter.next();
			dec.updatePosition();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.forms.IMessageManager#isAutoUpdate()
	 */
	public boolean isAutoUpdate() {
		return autoUpdate;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.forms.IMessageManager#setAutoUpdate(boolean)
	 */
	public void setAutoUpdate(boolean autoUpdate) {
		boolean needsUpdate = !this.autoUpdate && autoUpdate;
		this.autoUpdate = autoUpdate;
		if (needsUpdate)
			update();
	}
}