/*******************************************************************************
 * Copyright (c) 2004, 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.facesconfig.ui.dialog;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.resources.IProject;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.jdt.core.IType;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.window.Window;
import org.eclipse.jst.jsf.common.ui.internal.dialogfield.ClassButtonDialogField;
import org.eclipse.jst.jsf.common.ui.internal.dialogfield.ComboDialogField;
import org.eclipse.jst.jsf.common.ui.internal.dialogfield.DialogField;
import org.eclipse.jst.jsf.common.ui.internal.dialogfield.IDialogFieldApplyListener;
import org.eclipse.jst.jsf.common.ui.internal.dialogfield.IStringButtonAdapter;
import org.eclipse.jst.jsf.common.ui.internal.dialogfield.LayoutUtil;
import org.eclipse.jst.jsf.common.ui.internal.dialogfield.StringButtonDialogField;
import org.eclipse.jst.jsf.facesconfig.emf.FacesConfigFactory;
import org.eclipse.jst.jsf.facesconfig.emf.ListEntriesType;
import org.eclipse.jst.jsf.facesconfig.emf.ManagedBeanType;
import org.eclipse.jst.jsf.facesconfig.emf.ManagedPropertyType;
import org.eclipse.jst.jsf.facesconfig.emf.MapEntriesType;
import org.eclipse.jst.jsf.facesconfig.ui.EditorMessages;
import org.eclipse.jst.jsf.facesconfig.ui.EditorPlugin;
import org.eclipse.jst.jsf.facesconfig.ui.IFacesConfigConstants;
import org.eclipse.jst.jsf.facesconfig.ui.section.AbstractFacesConfigSection;
import org.eclipse.jst.jsf.facesconfig.ui.util.JavaBeanProperty;
import org.eclipse.jst.jsf.facesconfig.ui.util.JavaBeanUtils;
import org.eclipse.jst.jsf.facesconfig.ui.util.JavaClassUtils;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;

/**
 * The dialog is for adding and editing managed property.
 * 
 * @author sfshi
 * 
 */
public class AddEditManagedPropertyDialog extends Dialog {

	private static final int MIN_DIALOG_WIDTH = 300;

	private static final int DEFAULT_CONTROL_WIDTH = 200;

	private ComboDialogField nameField;

	private ClassButtonDialogField classField;

	private ComboDialogField valueTypeField;

	private StringButtonDialogField valueField;

	private IProject project;

	private String propertyName;

	private String propertyClass;

	private String valueType;

	/**
	 * the value could be a string, or instance of <code>NullValueType</code>,
	 * <code>MapEntriesType</code> and <code>ListEntriesType</code>.
	 */
	private Object valueObject;

	private ManagedBeanType managedBean;

	/**
	 * the list of this bean properties.
	 */
	private List beanPropertyList;

	/**
	 * the managed-property object that is editing, but it will be read-only.
	 */
	private ManagedPropertyType managedProperty;

	// private FormToolkit toolkit;

	private Composite parent;

	private static final String[] valueTypes = { IFacesConfigConstants.VALUE,
			IFacesConfigConstants.NULL_VALUE,
			IFacesConfigConstants.MAP_ENTRIES,
			IFacesConfigConstants.LIST_ENTRIES };

	private boolean isNew;

	private AbstractFacesConfigSection section;

	/**
	 * constructor for adding a managed property.
	 * 
	 * @param parentShell
	 * @param managedBean
	 * @param section 
	 */
	public AddEditManagedPropertyDialog(Shell parentShell,
			ManagedBeanType managedBean, AbstractFacesConfigSection section) {
		super(parentShell);
		this.isNew = true;
		this.managedBean = managedBean;
		this.section = section;
	}

	/**
	 * 
	 * @param parentShell
	 * @param managedProperty
	 * @param section
	 */
	public AddEditManagedPropertyDialog(Shell parentShell,
			ManagedPropertyType managedProperty, AbstractFacesConfigSection section) {
		super(parentShell);
		this.isNew = false;
		this.managedProperty = managedProperty;
		this.managedBean = (ManagedBeanType) managedProperty.eContainer();
		this.section = section;
	}

	/*
	 * @see org.eclipse.jface.window.Window#configureShell(org.eclipse.swt.widgets.Shell)
	 */
	protected void configureShell(Shell newShell) {
		super.configureShell(newShell);
		if (isNew)
			newShell.setText(EditorMessages.AddEditManagedPropertyDialog_Add);
		else
			newShell.setText(EditorMessages.AddEditManagedPropertyDialog_Edit);
	}

	/*
	 * @see org.eclipse.jface.dialogs.Dialog#createDialogArea(org.eclipse.swt.widgets.Composite)
	 */
	protected Control createDialogArea(Composite parent_) {
		Composite container = new Composite(parent_, SWT.FILL);
		this.parent = container;
		GridLayout layout = new GridLayout();
		layout.numColumns = 2;
		layout.marginWidth = layout.marginHeight = 5;
		container.setLayout(layout);
		GridData gd = new GridData(GridData.FILL_BOTH);
		container.setLayoutData(gd);

		nameField = new ComboDialogField(SWT.DROP_DOWN | SWT.READ_ONLY
				| SWT.BORDER);
		nameField.setLabelText(EditorMessages.ManagedBeanPropertyEditDialog_PropertyName);

		int propertyCount = 0;
		beanPropertyList = getBeanPropertyList(managedBean);
		if (beanPropertyList != null)
			propertyCount = beanPropertyList.size();

		if (propertyCount > 0) {
			String[] propertyNames = new String[propertyCount];

			for (int i = 0; i < propertyCount; i++) {
				JavaBeanProperty property = (JavaBeanProperty) beanPropertyList
						.get(i);
				propertyNames[i] = property.getName();
			}
			nameField.setItems(propertyNames);
		}

		nameField.setDialogFieldApplyListener(new IDialogFieldApplyListener() {
			public void dialogFieldApplied(DialogField field) {
				handleNameSelection(((ComboDialogField) field).getText());
			}
		});

		classField = new ClassButtonDialogField(null);
		classField.setProject(getProject());
		classField.setLabelText(EditorMessages.ManagedBeanPropertyEditDialog_PropertyClass);

		valueTypeField = new ComboDialogField(SWT.DROP_DOWN | SWT.READ_ONLY
				| SWT.BORDER);
		valueTypeField.setLabelText(EditorMessages.ManagedBeanPropertyEditDialog_ValueType);

		valueTypeField.setItems(valueTypes);
		valueTypeField
				.setDialogFieldApplyListener(new IDialogFieldApplyListener() {
					public void dialogFieldApplied(DialogField field) {
						updateValueStatus();
					}
				});

		valueField = new StringButtonDialogField(new IStringButtonAdapter() {
			public void changeControlPressed(DialogField field) {
				handleChangeValue(valueTypeField.getText(),
						((StringButtonDialogField) field).getText());
			}

		});

		valueField.setLabelText(EditorMessages.ManagedBeanPropertyEditDialog_Value);
		valueField.setButtonLabel(EditorMessages.UI_Button_Edit_more);

		valueField.setDialogFieldApplyListener(new IDialogFieldApplyListener() {

			public void dialogFieldApplied(DialogField field) {
				valueObject = ((StringButtonDialogField) field).getText();

			}
		});

		GridData data = new GridData(GridData.FILL_BOTH);
		container.setLayoutData(data);

		int numberOfColumns = 5;
		GridLayout gl = new GridLayout(numberOfColumns, false);
		container.setLayout(gl);

		nameField.doFillIntoGrid(null, container, numberOfColumns);
		LayoutUtil.setWidthHint(nameField.getComboControl(null, container),
				DEFAULT_CONTROL_WIDTH);

		classField.doFillIntoGrid(null, container, numberOfColumns - 1);
		data = new GridData(SWT.FILL, SWT.CENTER, false, false);
		data.horizontalSpan = 2;
		classField.getChangeControl(null, container).setLayoutData(data);
		LayoutUtil.setWidthHint(classField.getTextControl(null, container),
				DEFAULT_CONTROL_WIDTH);

		valueTypeField.doFillIntoGrid(null, container, numberOfColumns);

		valueField.doFillIntoGrid(null, container, numberOfColumns);

		LayoutUtil.setHorizontalGrabbing(classField.getTextControl(null,
				container));

		valueTypeField.selectItem(0);

		if (!isNew && managedProperty != null) {
			initFields();
		}

		return container;
	}

	private void initFields() {

		if (managedProperty.getPropertyName() != null)
			nameField.setText(managedProperty.getPropertyName()
					.getTextContent());

		if (managedProperty.getPropertyClass() != null)
			classField.setText(managedProperty.getPropertyClass()
					.getTextContent());

		if (managedProperty.getValue() != null) {
			valueTypeField.setText(valueTypes[0]);
			valueField.setText(managedProperty.getValue().getTextContent());
		} else if (managedProperty.getNullValue() != null)
			valueTypeField.setText(valueTypes[1]);
		else if (managedProperty.getMapEntries() != null)
			valueTypeField.setText(valueTypes[2]);
		else if (managedProperty.getListEntries() != null)
			valueTypeField.setText(valueTypes[3]);
		else
			valueTypeField.setText(valueTypes[0]);
		updateValueStatus();
	}

	/**
	 * @param text
	 */
	protected void handleNameSelection(String text) {
		int propertyCount = 0;
		if (beanPropertyList != null)
			propertyCount = beanPropertyList.size();

		if (propertyCount > 0) {
			for (int i = 0; i < propertyCount; i++) {
				JavaBeanProperty property = (JavaBeanProperty) beanPropertyList
						.get(i);

				if (property.getName().equals(text.trim())) {
					classField.setText(property.getQualifiedType());
					break;
				}
			}
		}

	}

	private void updateValueStatus() {
		if (valueField == null) {
			return;
		}
		valueObject = null;
		if (valueTypeField.getText().equalsIgnoreCase(
				IFacesConfigConstants.NULL_VALUE)) {
			valueField.setEnabled(false);
			valueObject = FacesConfigFactory.eINSTANCE.createNullValueType();
		} else if (valueTypeField.getText().equalsIgnoreCase(
				IFacesConfigConstants.MAP_ENTRIES)
				|| valueTypeField.getText().equalsIgnoreCase(
						IFacesConfigConstants.LIST_ENTRIES)) {
			valueField.getTextControl(null, parent).setEditable(false);
			valueField.setEnabled(true);
		} else {
			
			valueObject = valueField.getText(); //Bug 173831
			valueField.getTextControl(null, parent).setEditable(true);
			valueField.setEnabled(true);
		}
	}

	/**
	 * @param valueType_ 
	 * @param value 
	 */
	protected void handleChangeValue(String valueType_, String value) {
		if (valueType_.equalsIgnoreCase(IFacesConfigConstants.VALUE)) {
			handleChangeLongStringValue(value);
		} else if (valueType_
				.equalsIgnoreCase(IFacesConfigConstants.MAP_ENTRIES)) {
			handleChangeMapEntries();
		} else if (valueType_
				.equalsIgnoreCase(IFacesConfigConstants.LIST_ENTRIES)) {
			handleChangeListEntries();
		}
	}

	/**
	 * @param textControl
	 */
	private void handleChangeLongStringValue(String value) {
		EditValueDialog valueDialog = new EditValueDialog(EditorPlugin
				.getActiveShell(), value);
		if (valueDialog.open() == Window.OK) {
			valueField.setText((String) valueDialog.getResultData());
			valueObject = valueDialog.getResultData();
		}
	}

	/**
	 * 
	 */
	private void handleChangeMapEntries() {

		MapEntriesType mapEntries;

		if (valueObject instanceof MapEntriesType)
			mapEntries = (MapEntriesType) valueObject;
		else if (isNew || managedProperty.getMapEntries() == null) {
			mapEntries = FacesConfigFactory.eINSTANCE.createMapEntriesType();
		} else {
			mapEntries = EcoreUtil.copy(managedProperty
					.getMapEntries());
		}

		EditMapEntriesDialog dialog = new EditMapEntriesDialog(EditorPlugin
				.getActiveShell(), mapEntries, section);
		if (dialog.open() == Dialog.OK) {
			valueObject = dialog.getMapEntries();
		} else {
			//user cancel the dialog, then restore.
			if (!isNew && managedProperty.getMapEntries() != null)
				valueObject = EcoreUtil.copy(managedProperty
						.getMapEntries());
			// else
			//				valueObject = null;
		}
	}

	private void handleChangeListEntries() {
		ListEntriesType listEntries;

		if (valueObject instanceof ListEntriesType)
			listEntries = (ListEntriesType) valueObject;
		else if (isNew || managedProperty.getListEntries() == null) {
			listEntries = FacesConfigFactory.eINSTANCE.createListEntriesType();
		} else {
			listEntries = EcoreUtil.copy(managedProperty
					.getListEntries());
		}

		EditListEntriesDialog dialog = new EditListEntriesDialog(EditorPlugin
				.getActiveShell(), listEntries, section);
		if (dialog.open() == Dialog.OK) {
			valueObject = dialog.getListEntries();
		} else {
			//user cancel the dialog, then restore.
			if (!isNew && managedProperty.getListEntries() != null)
				valueObject = EcoreUtil.copy(managedProperty
						.getListEntries());
			// else
			// valueObject = null;
		}
	}

	/**
	 * Get a list of JavaBeanProperty that from the managed bean class.
	 * 
	 * @return
	 */
	private List getBeanPropertyList(ManagedBeanType managedBean_) {
		if (managedBean_.getManagedBeanClass() == null)
			return null;
		String beanClassName = managedBean_.getManagedBeanClass()
				.getTextContent();
		IType classType = JavaClassUtils.getType(getProject(), beanClassName);
		if (classType == null) {
			return null;
		}
		List list = new ArrayList();
		JavaBeanProperty[] properties = JavaBeanUtils
				.getBeanProperties(classType);
		if (properties != null) {
			for (int i = 0; i < properties.length; i++) {
				list.add(properties[i]);
			}
		}
		return list;
	}

	/*
	 * @see org.eclipse.jface.window.Window#getInitialSize()
	 */
	protected Point getInitialSize() {
		Point shellSize = super.getInitialSize();
		return new Point(Math.max(
				convertHorizontalDLUsToPixels(MIN_DIALOG_WIDTH), shellSize.x),
				shellSize.y);
	}

	/**
	 * @return the project
	 */
	public IProject getProject() {
		if (project == null) {
			project = (IProject) section.getPage().getEditor().getAdapter(
					IProject.class);
		}
		return project;
	}

	/**
	 * 
	 */
	protected void okPressed() {
		propertyName = nameField.getText();
		propertyClass = classField.getText();
		valueType = valueTypeField.getText();

		super.okPressed();
	}

	/**
	 * @return the property class
	 */
	public String getPropertyClass() {
		return propertyClass;
	}

	/**
	 * @param attributeClass
	 */
	public void setAttributeClass(String attributeClass) {
		this.propertyClass = attributeClass;
	}

	/**
	 * @return the property name
	 */
	public String getPropertyName() {
		return propertyName;
	}

	/**
	 * @param attributeName
	 */
	public void setAttributeName(String attributeName) {
		this.propertyName = attributeName;
	}

	/**
	 * @return the value type
	 */
	public String getValueType() {
		return valueType;
	}

	/**
	 * @param defaultValue
	 */
	public void setValueType(String defaultValue) {
		this.valueType = defaultValue;
	}

	/**
	 * @param project
	 */
	public void setProject(IProject project) {
		this.project = project;
	}

	/**
	 * @return the value object
	 */
	public Object getValueObject() {
		return valueObject;
	}

	/**
	 * @param valueObject
	 */
	public void setValueObject(Object valueObject) {
		this.valueObject = valueObject;
	}

}
