package org.eclipse.jst.servlet.ui.internal.wizard;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.Widget;
import org.eclipse.wst.common.frameworks.datamodel.DataModelEvent;
import org.eclipse.wst.common.frameworks.datamodel.IDataModel;
import org.eclipse.wst.common.frameworks.internal.datamodel.ui.DataModelSynchHelper;

public class ServletDataModelSyncHelper extends DataModelSynchHelper {
	protected Map widgetToValueHash;
	protected MultipleCheckboxSelectionListener multipleCheckboxSelectionListener;

	public ServletDataModelSyncHelper(IDataModel model) {
		super(model);
	}
	
	/**
	 * Sets the UI to have the property value defined in the model
	 * 
	 * @param propertyName
	 * @link IDataModelListener for the flag values.
	 */
	public void synchUIWithModel(final String propertyName, final int flag) {
		if (null != propertyToWidgetHash && propertyToWidgetHash.containsKey(propertyName)) {
			Display.getDefault().syncExec(new Runnable() {
				public void run() {
					try {
						Object obj = propertyToWidgetHash.get(propertyName);
						if (obj != null) {
							if (obj instanceof List) {
								List widgets = (List) obj;
								for (int i = 0; i < widgets.size(); i++) {
									currentWidget = (Widget) widgets.get(i);
									synchUIWithModel(propertyName, flag, currentWidget);
								}
							} else {
								currentWidget = (Widget) obj;
								synchUIWithModel(propertyName, flag, currentWidget);
							}
						}
					} finally {
						currentWidget = null;
					}
				}
			});
		}
	}
	
	protected void synchUIWithModel(final String propertyName, final int flag, Widget currentWidget) {
		if (currentWidget != null && currentWidget != currentWidgetFromEvent) {
			//We must hold a copy in a temp variable because setting the widget value
			//may trigger an event that will cause this method to be called again.
			Widget widget = currentWidget;
			try {
				ignoreModifyEvent = true;
				if (currentWidget instanceof Text)
					setWidgetValue(propertyName, flag, (Text) currentWidget);
				else if (currentWidget instanceof Combo) {
					setWidgetValue(propertyName, flag, (Combo) currentWidget);
				} else if (currentWidget instanceof Button)
					setWidgetValue(propertyName, flag, (Button) currentWidget);
				else if (currentWidget instanceof Label)
					setWidgetValue(propertyName, flag, (Label) currentWidget);
				else if (currentWidget instanceof List)
					setWidgetValue(propertyName, flag, (org.eclipse.swt.widgets.List) currentWidget);
				else if (currentWidget instanceof Table)
					setWidgetValue(propertyName, flag, (Table) currentWidget);
				else if (currentWidget instanceof Tree)
					setWidgetValue(propertyName, flag, (Tree) currentWidget);
			} finally {
				ignoreModifyEvent = false;
			}
			//Pass the copy of the currentWidget
			setEnablement((Control) widget, dataModel.isPropertyEnabled(propertyName));
		}
	}
	
	protected void setWidgetValue(String propertyName, int flag, Button button) {
		if ((button.getStyle() & SWT.CHECK) == SWT.CHECK) {
			Object propertyValue = dataModel.getProperty(propertyName);
			if (propertyValue instanceof java.util.List) {
				List value = (List) propertyValue;
				Object buttonValue = widgetToValueHash.get(button);
				boolean exists = value.contains(buttonValue);
				if (button.getSelection() != exists) {
					button.setSelection(exists);
				}
				return;
			}
		}
	}
	
	private class MultipleCheckboxSelectionListener implements SelectionListener {
		public void widgetSelected(SelectionEvent e) {
			Button button = (Button) e.getSource();
			if (currentWidget == button)
				return;
			try {
				currentWidgetFromEvent = button;
				String propertyName = (String) widgetToPropertyHash.get(button);
				Object propertyValue = widgetToValueHash.get(button);
				
				Object contents = dataModel.getProperty(propertyName);
				
				if (contents == null) {
					contents = new ArrayList();
				}
				if (contents instanceof java.util.List) {
					List list = (List) contents;
					if (button.getSelection()) {
						if (!list.contains(propertyValue)) 
							list.add(propertyValue);
					} else {
						list.remove(propertyValue);
					}
					setProperty(propertyName, list);
					dataModel.notifyPropertyChange(propertyName, DataModelEvent.VALUE_CHG);
				}
			} finally {
				currentWidgetFromEvent = null;
			}
		}

		

		public void widgetDefaultSelected(SelectionEvent e) {
		}
	}
	
	public void synchCheckbox(Button checkbox, String textValue, String propertyName, Control[] dependentControls) {
		setCompositeValue(checkbox, textValue);
		synchComposite(checkbox, propertyName, dependentControls);
		if (multipleCheckboxSelectionListener == null) {
			multipleCheckboxSelectionListener = new MultipleCheckboxSelectionListener();
		}
		checkbox.addSelectionListener(multipleCheckboxSelectionListener);
	}
	
	protected void setCompositeValue(Widget widget, Object value) {
		if (widgetToValueHash == null)
			widgetToValueHash = new HashMap();
		widgetToValueHash.put(widget, value);
	}
	
	protected void synchComposite(Widget widget, String propertyName, Control[] depControls) {
		if (null == widgetToPropertyHash)
			widgetToPropertyHash = new HashMap();
		if (propertyToWidgetHash == null)
			propertyToWidgetHash = new HashMap();
		widgetToPropertyHash.put(widget, propertyName);
		Object value = propertyToWidgetHash.get(propertyName);
		List widgets;
		if (value == null || !(value instanceof List)) {
			widgets = new ArrayList();
		} else {
			widgets = (List) value;
		}
		widgets.add(widget);
		propertyToWidgetHash.put(propertyName, widgets);
		
		if (depControls != null) {
			if (widgetToDepControls == null)
				widgetToDepControls = new HashMap();
			widgetToDepControls.put(widget, depControls);
		}
		synchUIWithModel(propertyName, DataModelEvent.VALUE_CHG);
	}
}
