/*******************************************************************************
 * Copyright (c) 2006 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Sebastian Davids <sdavids@gmx.de> - bug 132479 - [FieldAssist] Field assist example improvements
 *******************************************************************************/
package org.eclipse.ui.examples.fieldassist;

import java.text.MessageFormat;

import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.bindings.keys.KeyStroke;
import org.eclipse.jface.bindings.keys.ParseException;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.StatusDialog;
import org.eclipse.jface.fieldassist.ComboContentAdapter;
import org.eclipse.jface.fieldassist.ContentProposalAdapter;
import org.eclipse.jface.fieldassist.DecoratedField;
import org.eclipse.jface.fieldassist.FieldAssistColors;
import org.eclipse.jface.fieldassist.FieldDecoration;
import org.eclipse.jface.fieldassist.FieldDecorationRegistry;
import org.eclipse.jface.fieldassist.IContentProposal;
import org.eclipse.jface.fieldassist.IContentProposalProvider;
import org.eclipse.jface.fieldassist.IControlContentAdapter;
import org.eclipse.jface.fieldassist.IControlCreator;
import org.eclipse.jface.fieldassist.TextContentAdapter;
import org.eclipse.jface.fieldassist.TextControlCreator;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Group;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Spinner;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.examples.fieldassist.preferences.PreferenceConstants;

/**
 * Example dialog that shows different field assist capabilities.
 */
public class ExampleDialog extends StatusDialog {

	class SpinnerContentAdapter implements IControlContentAdapter {
		// We are only implementing this for our internal use, not for
		// content assist, so many of the methods are ignored.
		public String getControlContents(Control control) {
			return new Integer(((Spinner) control).getSelection()).toString();
		}

		public void setControlContents(Control control, String text,
				int cursorPosition) {
			// ignore
		}

		public void insertControlContents(Control control, String text,
				int cursorPosition) {
			// ignore
		}

		public int getCursorPosition(Control control) {
			// ignore
			return 0;
		}

		public Rectangle getInsertionBounds(Control control) {
			return control.getBounds();
		}
		public void setCursorPosition(Control control, int index) {
			// ignore
		}
	}

	abstract class SmartField {
		DecoratedField field;

		IControlContentAdapter contentAdapter;

		FieldDecoration errorDecoration, warningDecoration;

		SmartField(DecoratedField field, IControlContentAdapter adapter) {
			this.field = field;
			this.contentAdapter = adapter;
		}

		String getContents() {
			return contentAdapter.getControlContents(field.getControl());
		}

		boolean isRequiredField() {
			return true;
		}

		FieldDecoration getErrorDecoration() {
			if (errorDecoration == null) {
				FieldDecoration standardError = FieldDecorationRegistry
						.getDefault().getFieldDecoration(
								FieldDecorationRegistry.DEC_ERROR);
				if (getErrorMessage() == null) {
					errorDecoration = standardError;
				} else {
					errorDecoration = new FieldDecoration(standardError
							.getImage(), getErrorMessage());
				}
			}
			return errorDecoration;

		}

		FieldDecoration getWarningDecoration() {
			if (warningDecoration == null) {
				FieldDecoration standardWarning = FieldDecorationRegistry
						.getDefault().getFieldDecoration(
								FieldDecorationRegistry.DEC_WARNING);
				if (getWarningMessage() == null) {
					warningDecoration = standardWarning;
				} else {
					warningDecoration = new FieldDecoration(standardWarning
							.getImage(), getWarningMessage());
				}
			}
			return warningDecoration;

		}

		abstract boolean isValid();

		abstract boolean isWarning();

		String getErrorMessage() {
			return null;
		}

		String getWarningMessage() {
			return null;
		}

	}

	class UserField extends SmartField {

		UserField(DecoratedField field, IControlContentAdapter adapter) {
			super(field, adapter);
		}

		boolean isValid() {
			String contents = getContents();
			for (int i = 0; i < contents.length(); i++) {
				if (!Character.isLetter(contents.charAt(i))) {
					return false;
				}
			}
			return true;
		}

		String getErrorMessage() {
			return TaskAssistExampleMessages.ExampleDialog_UserError;
		}

		boolean isWarning() {
			return getContents().equals(
					TaskAssistExampleMessages.ExampleDialog_WarningName);
		}

		String getWarningMessage() {
			return TaskAssistExampleMessages.ExampleDialog_UserWarning;
		}
	}

	class AgeField extends SmartField {

		AgeField(DecoratedField field, IControlContentAdapter adapter) {
			super(field, adapter);
		}

		boolean isValid() {
			// We seed the spinner with valid values always.
			return true;
		}

		boolean isWarning() {
			Spinner spinner = (Spinner) field.getControl();
			return spinner.getSelection() > 65;
		}

		String getWarningMessage() {
			return TaskAssistExampleMessages.ExampleDialog_AgeWarning;
		}
	}

	private String[] validUsers = { "tom", "dick", "harry", "ferdinand", "tim", //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$
			"teresa", "tori", "daniela" }; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$

	private String triggerKey;

	private String username;

	private boolean showErrorDecoration, showErrorMessage, showErrorColor,
			showWarningDecoration, showRequiredFieldColor,
			showRequiredFieldDecoration, showSecondaryPopup;

	private Color defaultTextColor, errorColor;

	/**
	 * Open the exapmle dialog.
	 * @param parent the parent shell
	 * @param username the default username
	 */
	public ExampleDialog(Shell parent, String username) {
		super(parent);
		setTitle(TaskAssistExampleMessages.ExampleDialog_Title);
		this.username = username;
		getPreferenceValues();
	}

	protected Control createDialogArea(Composite parent) {
		Composite outer = (Composite) super.createDialogArea(parent);
		
		initializeDialogUnits(outer);
		
		Group main = new Group(outer, SWT.NONE);
		main.setLayoutData(new GridData(GridData.FILL_BOTH));
		main.setText(TaskAssistExampleMessages.ExampleDialog_SecurityGroup);
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
		layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
		layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
		layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
		main.setLayout(layout);

		Label label = new Label(main, SWT.LEFT);
		label.setText(TaskAssistExampleMessages.ExampleDialog_UserName);

		IPreferenceStore store = FieldAssistPlugin.getDefault()
				.getPreferenceStore();

		// Create a field representing a user name
		DecoratedField field = new DecoratedField(main, SWT.BORDER,
				new TextControlCreator());
		final SmartField textField = new UserField(field,
				new TextContentAdapter());
		if (store.getBoolean(PreferenceConstants.PREF_SHOWCONTENTPROPOSALCUE)) {
			field.addFieldDecoration(getCueDecoration(), SWT.TOP | SWT.LEFT,
					true);
		}

		if (showRequiredFieldDecoration && textField.isRequiredField()) {
			field.addFieldDecoration(getRequiredFieldDecoration(), SWT.BOTTOM
					| SWT.LEFT, false);
		}

		Text text = (Text) field.getControl();
		defaultTextColor = text.getBackground();
		text.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent event) {
				handleModify(textField);
			}
		});
		text.addFocusListener(new FocusListener() {
			public void focusGained(FocusEvent event) {
				handleFocusGained(textField);
			}

			public void focusLost(FocusEvent event) {
				handleFocusLost(textField);
			}

		});

		text.setText(username);
		installContentProposalAdapter(text, new TextContentAdapter());
		field.getLayoutControl().setLayoutData(getDecoratedFieldGridData());
		// prime the required field color by calling the focus lost handler.
		handleFocusLost(textField);

		label = new Label(main, SWT.LEFT);
		label.setText(TaskAssistExampleMessages.ExampleDialog_ComboUserName);

		// Create a combo field representing a user name
		field = new DecoratedField(main, SWT.BORDER | SWT.DROP_DOWN,
				new IControlCreator() {
					public Control createControl(Composite parent, int style) {
						return new Combo(parent, style);
					}
				});
		final SmartField comboField = new UserField(field,
				new ComboContentAdapter());
		if (store.getBoolean(PreferenceConstants.PREF_SHOWCONTENTPROPOSALCUE)) {
			field.addFieldDecoration(getCueDecoration(), SWT.TOP | SWT.LEFT,
					true);
		}
		if (showRequiredFieldDecoration) {
			field.addFieldDecoration(getRequiredFieldDecoration(), SWT.BOTTOM
					| SWT.LEFT, false);
		}

		Combo combo = (Combo) field.getControl();
		combo.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent event) {
				handleModify(comboField);
			}
		});
		combo.addFocusListener(new FocusListener() {
			public void focusGained(FocusEvent event) {
				handleFocusGained(comboField);
			}

			public void focusLost(FocusEvent event) {
				handleFocusLost(comboField);
			}

		});
		combo.setText(username);
		combo.setItems(validUsers);
		field.getLayoutControl().setLayoutData(getDecoratedFieldGridData());
		installContentProposalAdapter(combo, new ComboContentAdapter());
		// prime the required field color by calling the focus lost handler.
		handleFocusLost(comboField);

		// Create a spinner representing a user age
		label = new Label(main, SWT.LEFT);
		label.setText(TaskAssistExampleMessages.ExampleDialog_Age);

		field = new DecoratedField(main, SWT.BORDER, new IControlCreator() {
			public Control createControl(Composite parent, int style) {
				return new Spinner(parent, style);
			}
		});
		if (showRequiredFieldDecoration) {
			field.addFieldDecoration(getRequiredFieldDecoration(), SWT.BOTTOM
					| SWT.LEFT, false);
		}
		final SmartField spinnerField = new AgeField(field,
				new SpinnerContentAdapter());

		Spinner spinner = (Spinner) field.getControl();
		spinner.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent event) {
				handleModify(spinnerField);
			}
		});
		combo.addFocusListener(new FocusListener() {
			public void focusGained(FocusEvent event) {
				handleFocusGained(spinnerField);
			}

			public void focusLost(FocusEvent event) {
				handleFocusLost(spinnerField);
			}

		});
		spinner.setSelection(40);
		field.getLayoutControl().setLayoutData(getDecoratedFieldGridData());

		// prime the required field color by calling the focus lost handler.
		handleFocusLost(spinnerField);

		// This field is not managed by a decorated field
		label = new Label(main, SWT.LEFT);
		label.setText(TaskAssistExampleMessages.ExampleDialog_Password);
		// We need to indent the field by the size of the decoration.
		text = new Text(main, SWT.BORDER);
		text.setText("******"); //$NON-NLS-1$
		text.setLayoutData(getNonDecoratedFieldGridData());

		Dialog.applyDialogFont(outer);
		
		return main;
	}

	private void getPreferenceValues() {
		IPreferenceStore store = FieldAssistPlugin.getDefault()
				.getPreferenceStore();
		showErrorMessage = store
				.getBoolean(PreferenceConstants.PREF_SHOWERRORMESSAGE);
		showErrorDecoration = store
				.getBoolean(PreferenceConstants.PREF_SHOWERRORDECORATION);
		showErrorColor = store
				.getBoolean(PreferenceConstants.PREF_SHOWERRORCOLOR);
		showWarningDecoration = store
				.getBoolean(PreferenceConstants.PREF_SHOWWARNINGDECORATION);
		showRequiredFieldColor = store
				.getBoolean(PreferenceConstants.PREF_SHOWREQUIREDFIELDCOLOR);
		showRequiredFieldDecoration = store
				.getBoolean(PreferenceConstants.PREF_SHOWREQUIREDFIELDDECORATION);
		showSecondaryPopup = store
				.getBoolean(PreferenceConstants.PREF_SHOWSECONDARYPOPUP);
		triggerKey = store.getString(PreferenceConstants.PREF_CONTENTASSISTKEY);

	}

	private FieldDecoration getCueDecoration() {
		// We use our own decoration which is based on the JFace version.
		FieldDecorationRegistry registry = FieldDecorationRegistry.getDefault();
		FieldDecoration dec = registry
				.getFieldDecoration(FieldAssistPlugin.DEC_CONTENTASSIST);
		if (dec == null) {
			// Get the standard one. We use its image and our own customized
			// text.
			FieldDecoration standardDecoration = registry
					.getFieldDecoration(FieldDecorationRegistry.DEC_CONTENT_PROPOSAL);
			registry.registerFieldDecoration(
					FieldAssistPlugin.DEC_CONTENTASSIST, NLS.bind(
							TaskAssistExampleMessages.Decorator_ContentAssist,
							triggerKey), standardDecoration.getImage());
			dec = registry
					.getFieldDecoration(FieldAssistPlugin.DEC_CONTENTASSIST);
		}
		return dec;
	}

	private FieldDecoration getWarningDecoration() {
		return FieldDecorationRegistry.getDefault().getFieldDecoration(
				FieldDecorationRegistry.DEC_WARNING);
	}

	private FieldDecoration getRequiredFieldDecoration() {
		return FieldDecorationRegistry.getDefault().getFieldDecoration(
				FieldDecorationRegistry.DEC_REQUIRED);
	}

	private void handleModify(SmartField smartField) {
		// Error indicator supercedes all others
		if (!smartField.isValid()) {
			showError(smartField);
		} else {
			hideError(smartField);
			if (smartField.isWarning()) {
				showWarning(smartField);
			} else {
				hideWarning(smartField);
				if (smartField.isRequiredField()) {
					smartField.field.addFieldDecoration(
							getRequiredFieldDecoration(),
							SWT.BOTTOM | SWT.LEFT, false);
				}
			}
		}
	}

	private void handleFocusGained(SmartField smartField) {
		// only set color if error color not already showing
		if (showErrorColor && !smartField.isValid())
			return;
		if (showRequiredFieldColor && smartField.isRequiredField()) {
			smartField.field.getControl().setBackground(defaultTextColor);
		}
	}

	private void handleFocusLost(SmartField smartField) {
		// only set color if error color not showing
		if (showErrorColor && !smartField.isValid())
			return;
		if (showRequiredFieldColor && smartField.isRequiredField()
				&& smartField.getContents().length() == 0) {
			smartField.field.getControl().setBackground(
					FieldAssistColors
							.getRequiredFieldBackgroundColor(smartField.field
									.getControl()));
		}
	}

	private void showError(SmartField smartField) {
		FieldDecoration dec = smartField.getErrorDecoration();
		if (showErrorMessage) {
			updateStatus(new Status(IStatus.ERROR,
					"org.eclipse.examples.contentassist", 0, dec //$NON-NLS-1$
							.getDescription(), null));
		}
		if (showErrorDecoration) {
			smartField.field.addFieldDecoration(dec, SWT.BOTTOM | SWT.LEFT,
					false);
		}
		if (showErrorColor) {
			smartField.field.getControl().setBackground(
					getErrorColor(smartField.field.getControl()));
		}
	}

	private void hideError(SmartField smartField) {
		FieldDecoration dec = smartField.getErrorDecoration();
		if (showErrorMessage) {
			this.updateStatus(Status.OK_STATUS);
		}
		if (showErrorDecoration) {
			smartField.field.hideDecoration(dec);
		}
		if (showErrorColor) {
			smartField.field.getControl().setBackground(defaultTextColor);
		}
	}

	private void showWarning(SmartField smartField) {
		if (showWarningDecoration) {
			FieldDecoration dec = smartField.getWarningDecoration();
			smartField.field.addFieldDecoration(dec, SWT.BOTTOM | SWT.LEFT,
					false);
		}
	}

	private void hideWarning(SmartField smartField) {
		if (showWarningDecoration) {
			smartField.field.hideDecoration(getWarningDecoration());
		}
	}

	private void installContentProposalAdapter(Control control, IControlContentAdapter contentAdapter) {
		IPreferenceStore store = FieldAssistPlugin.getDefault()
				.getPreferenceStore();
		boolean propagate = store
				.getBoolean(PreferenceConstants.PREF_CONTENTASSISTKEY_PROPAGATE);
		KeyStroke keyStroke;
		char[] autoActivationCharacters = null;
		int autoActivationDelay = store
				.getInt(PreferenceConstants.PREF_CONTENTASSISTDELAY);

		if (triggerKey.equals(PreferenceConstants.PREF_CONTENTASSISTKEYAUTO)) {
			// null means automatically assist when character typed
			keyStroke = null;
		} else if (triggerKey
				.equals(PreferenceConstants.PREF_CONTENTASSISTKEYAUTOSUBSET)) {
			keyStroke = null;
			autoActivationCharacters = new char[] { 't', 'd' };
		} else {
			try {
				keyStroke = KeyStroke.getInstance(triggerKey);
			} catch (ParseException e) {
				keyStroke = KeyStroke.getInstance(SWT.F10);
			}
		}

		ContentProposalAdapter adapter = new ContentProposalAdapter(control,
				contentAdapter, getContentProposalProvider(),
				keyStroke, autoActivationCharacters);
		adapter.setAutoActivationDelay(autoActivationDelay);
		adapter.setPropagateKeys(propagate);
		adapter.setFilterStyle(getContentAssistFilterStyle());
		adapter.setProposalAcceptanceStyle(getContentAssistAcceptance());
	}

	private IContentProposalProvider getContentProposalProvider() {
		return new IContentProposalProvider() {
			public IContentProposal[] getProposals(String contents, int position) {
				IContentProposal[] proposals = new IContentProposal[validUsers.length];
				for (int i = 0; i < validUsers.length; i++) {
					final String user = validUsers[i];
					proposals[i] = new IContentProposal() {
						public String getContent() {
							return user;
						}

						public String getLabel() {
							return user;
						}

						public String getDescription() {
							if (showSecondaryPopup)
								return MessageFormat
										.format(
												TaskAssistExampleMessages.ExampleDialog_ProposalDescription,
												new String[] { user });
							return null;
						}

						public int getCursorPosition() {
							return user.length();
						}
					};
				}
				return proposals;
			}
		};
	}

	private int getContentAssistAcceptance() {
		IPreferenceStore store = FieldAssistPlugin.getDefault()
				.getPreferenceStore();
		String acceptanceStyle = store
				.getString(PreferenceConstants.PREF_CONTENTASSISTRESULT);
		if (acceptanceStyle
				.equals(PreferenceConstants.PREF_CONTENTASSISTRESULT_INSERT))
			return ContentProposalAdapter.PROPOSAL_INSERT;
		if (acceptanceStyle
				.equals(PreferenceConstants.PREF_CONTENTASSISTRESULT_REPLACE))
			return ContentProposalAdapter.PROPOSAL_REPLACE;
		return ContentProposalAdapter.PROPOSAL_IGNORE;
	}

	private int getContentAssistFilterStyle() {
		IPreferenceStore store = FieldAssistPlugin.getDefault()
				.getPreferenceStore();
		String acceptanceStyle = store
				.getString(PreferenceConstants.PREF_CONTENTASSISTFILTER);
		if (acceptanceStyle
				.equals(PreferenceConstants.PREF_CONTENTASSISTFILTER_CHAR))
			return ContentProposalAdapter.FILTER_CHARACTER;
		if (acceptanceStyle
				.equals(PreferenceConstants.PREF_CONTENTASSISTFILTER_CUMULATIVE))
			return ContentProposalAdapter.FILTER_CUMULATIVE;
		return ContentProposalAdapter.FILTER_NONE;
	}

	private GridData getDecoratedFieldGridData() {
		return new GridData(IDialogConstants.ENTRY_FIELD_WIDTH, SWT.DEFAULT);

	}

	private GridData getNonDecoratedFieldGridData() {
		GridData data = new GridData();
		data.horizontalAlignment = SWT.FILL;
		data.horizontalIndent = FieldDecorationRegistry.getDefault()
				.getMaximumDecorationWidth();
		return data;
	}

	private Color getErrorColor(Control control) {
		if (errorColor == null) {
			RGB rgb = FieldAssistColors.computeErrorFieldBackgroundRGB(control);
			errorColor = new Color(control.getDisplay(), rgb);
		}
		return errorColor;
	}

	public boolean close() {
		if (errorColor != null) {
			errorColor.dispose();
		}
		return super.close();
	}

}
