/*******************************************************************************
 * Copyright (c) 2006 Sybase, Inc. 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:
 *     Sybase, Inc. - initial API and implementation
 *******************************************************************************/
package org.eclipse.jst.jsf.common.ui.internal.dialogfield;

import java.util.Map;
import java.util.TreeMap;
import java.util.Map.Entry;

import org.eclipse.jst.jsf.common.ui.internal.utils.StyleCombo;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.forms.FormColors;
import org.eclipse.ui.forms.widgets.FormToolkit;

public class StyleComboDialogField extends DialogFieldBase implements
		ISupportTextValue {
	final static private int WIDTH_HINT = 10;

	private String _text;

	private int _selectionIndex;

	private String[] _items;

	private StyleCombo _comboControl;

	private ModifyListener _modifyListener;

	private int _flags;

	private boolean _pending = false;

	private Map _entryMap;

	private String _defaultValue;

	public String getDefaultValue() {
		return _defaultValue;
	}

	public void setDefaultValue(String defaultValue) {
		this._defaultValue = defaultValue;
	}

	public StyleComboDialogField(int flags) {
		super();
		_text = ""; //$NON-NLS-1$
		_items = new String[0];
		_flags = flags;
		_selectionIndex = -1;
	}

	// ------- layout helpers

	/*
	 * @see DialogField#doFillIntoGrid
	 */
	public Control[] doFillIntoGrid(FormToolkit toolkit, Composite parent,
			int nColumns) {
		assertEnoughColumns(nColumns);

		Control requiredLabel = getRequiredLabelControl(toolkit, parent);
		requiredLabel.setLayoutData(gridDataForLabel(1));

		Control label = getLabelControl(toolkit, parent);
		label.setLayoutData(gridDataForLabel(1));

		StyleCombo combo = getComboControl(toolkit, parent);
		combo.setLayoutData(gridDataForCombo(nColumns - 2));

		return new Control[] { requiredLabel, label, combo };
	}

	/*
	 * @see DialogField#getNumberOfControls
	 */
	public int getNumberOfControls() {
		return 3;
	}

	protected static GridData gridDataForCombo(int span) {
		GridData gd = new GridData();
		gd.horizontalAlignment = GridData.FILL;
		gd.grabExcessHorizontalSpace = false;
		gd.horizontalSpan = span;
		gd.widthHint = WIDTH_HINT;
		return gd;
	}

	// ------- focus methods

	/*
	 * @see DialogField#setFocus
	 */
	public boolean setFocus() {
		if (isOkToUse(_comboControl)) {
			_comboControl.setFocus();
		}
		return true;
	}

	// ------- ui creation

	/**
	 * Creates or returns the created combo control.
	 * 
	 * @param parent
	 *            The parent composite or <code>null</code> when the widget
	 *            has already been created.
	 */
	public StyleCombo getComboControl(FormToolkit toolkit,
			final Composite parent) {
		if (_comboControl == null) {
			assertCompositeNotNull(parent);
			_modifyListener = new ModifyListener() {
				public void modifyText(ModifyEvent e) {
					doModifyText(e);
				}
			};
			SelectionListener selectionListener = new SelectionListener() {
				public void widgetSelected(SelectionEvent e) {
					doSelectionChanged(e);
				}

				public void widgetDefaultSelected(SelectionEvent e) {
					handleDefaultSelection(e);
				}
			};

			if (toolkit != null) {
				_comboControl = new StyleCombo(parent, _flags);
				parent.addPaintListener(new PaintListener() {
					FormColors colors = new FormColors(parent.getDisplay());

					public void paintControl(PaintEvent event) {
						Composite composite = (Composite) event.widget;
						Control[] children = composite.getChildren();
						for (int i = 0; i < children.length; i++) {
							Control c = children[i];
							if (!(c instanceof StyleCombo) || !c.isVisible()) {
								continue;
							}
							Rectangle b = c.getBounds();
							GC gc = event.gc;
							gc.setForeground(colors.getBorderColor());
							gc.drawRectangle(b.x - 1, b.y - 1, b.width + 1,
									b.height + 1);
						}
					}
				});
				toolkit.adapt(_comboControl);
			} else {
				_comboControl = new StyleCombo(parent, _flags | SWT.BORDER);
				_comboControl.setBackground(Display.getCurrent()
						.getSystemColor(SWT.COLOR_LIST_BACKGROUND));
			}

			// moved up due to 1GEUNW2
			_comboControl.setItems(_items);
			_comboControl.setDefaultValue(_defaultValue);
			if (_selectionIndex != -1) {
				_comboControl.select(_selectionIndex);
			} else {
				_comboControl.setText(_text);
			}
			_comboControl.setFont(parent.getFont());
			_comboControl.addModifyListener(_modifyListener);
			_comboControl.addSelectionListener(selectionListener);
			_comboControl.addFocusListener(new FocusAdapter() {
				public void focusLost(FocusEvent e) {
					doFocusLost(e);
				}
			});
			_comboControl.setEnabled(isEnabled());
			_comboControl.setToolTipText(getToolTip());
		}
		return _comboControl;
	}

	protected void handleDefaultSelection(SelectionEvent e) {
		// commit value
		if (_pending) {
			_pending = false;
			dialogFieldApplied();
		}
	}

	protected void doFocusLost(FocusEvent e) {
		if (_pending) {
			_pending = false;
			dialogFieldApplied();
		}
	}

	private void doModifyText(ModifyEvent e) {
		if (isOkToUse(_comboControl)) {
			_text = getEntryKey(_comboControl.getText());
			_selectionIndex = _comboControl.getSelectionIndex();
		}
		_pending = true;
		dialogFieldChanged();
	}

	private void doSelectionChanged(SelectionEvent e) {
		if (isOkToUse(_comboControl)) {
			_items = _comboControl.getItems();
			_text = getEntryKey(_comboControl.getText());
			_selectionIndex = _comboControl.getSelectionIndex();
		}
		_pending = false;
		dialogFieldChangedAndApplied();
	}

	// ------ enable / disable management

	/*
	 * @see DialogField#updateEnableState
	 */
	protected void updateEnableState() {
		super.updateEnableState();
		if (isOkToUse(_comboControl)) {
			_comboControl.setEnabled(isEnabled());
		}
	}

	// ------ text access

	/**
	 * Gets the combo items.
	 */
	public String[] getItems() {
		return _items;
	}

	/**
	 * Sets the combo items. Triggers a dialog-changed event.
	 */
	public void setItems(String[] items) {
		_items = items;
		if (isOkToUse(_comboControl)) {
			_comboControl.setItems(items);
		}
		_pending = false;
		// dialogFieldChangedAndApplied();
	}

	public void setEntryMap(Map map) {
		this._entryMap = map;
		if (_entryMap == null) {
			_entryMap = new TreeMap();
		}
		Entry[] entries = (Entry[]) _entryMap.entrySet().toArray(new Entry[0]);
		String[] items = new String[entries.length];
		for (int i = 0; i < entries.length; i++) {
			items[i] = entries[i].getValue().toString();
		}
		setItems(items);
	}

	/**
	 * Gets the text.
	 */
	public String getText() {
		return _text;
	}

	/**
	 * Sets the text. Triggers a dialog-changed event.
	 */
	public void setText(String text) {
		setTextWithoutUpdate(text);
		_pending = false;
		dialogFieldChangedAndApplied();
	}

	/**
	 * Selects an item.
	 */
	public void selectItem(int index) {
		if (isOkToUse(_comboControl)) {
			_comboControl.select(index);
		} else {
			if (index >= 0 && index < _items.length) {
				_text = getEntryKey(_items[index]);
				_selectionIndex = index;
			}
		}
		dialogFieldChangedAndApplied();
	}

	public int getSelectionIndex() {
		return _selectionIndex;
	}

	/**
	 * Sets the text without triggering a dialog-changed event.
	 */
	public void setTextWithoutUpdate(String text) {
		_pending = false;
		if (text == null) {
			text = "";//$NON-NLS-1$
		}
		_text = text;
		if (isOkToUse(_comboControl)) {
			_comboControl.removeModifyListener(_modifyListener);
			_comboControl.setText(getEntryValue(text));
			_comboControl.addModifyListener(_modifyListener);
		}
	}

	private String getEntryValue(String key) {
		if (_entryMap == null || !_entryMap.containsKey(key)) {
			return key;
		}
		return _entryMap.get(key).toString();
	}

	private String getEntryKey(String value) {
		if (_entryMap == null || !_entryMap.containsValue(value)) {
			return value;
		}

		Entry[] entries = (Entry[]) _entryMap.entrySet().toArray(new Entry[0]);
		for (int i = 0; i < entries.length; i++) {
			if (entries[i].getValue() == value
					|| (value != null && value.equals(entries[i].getValue()))) {
				return entries[i].getKey().toString();
			}
		}
		return value;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jst.jsf.common.ui.internal.dialogfield.DialogField#handleGrabHorizontal()
	 */
	public void handleGrabHorizontal() {
		LayoutUtil.setGrabHorizontal(_comboControl, true);
	}
}
