/**
 * File:    SelectDatatypeWizardPage.java
 * Created: 04.01.2007
 *
 *
/*******************************************************************************
 * Copyright (c) 2005-2011
 * University of Augsburg, Germany <www.ds-lab.org>
 *
 * 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:
 *    Christian Seitz, Programming distributed Systems Lab, University of Augsburg 
 *    	- initial API and implementation
 *******************************************************************************/

package org.eclipse.jwt.we.misc.wizards.model;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;

import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.jface.wizard.WizardPage;
import org.eclipse.jwt.meta.model.data.DataType;
import org.eclipse.jwt.we.PluginProperties;
import org.eclipse.jwt.we.editors.WEEditor;
import org.eclipse.jwt.we.misc.util.GeneralHelper;
import org.eclipse.jwt.we.misc.wizards.NotResizableWizardDialog;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.PlatformUI;
import org.eclipse.jwt.meta.model.core.Package;


/**
 * WizardPage to specify DataType and Value of a new Data
 * 
 * @author Christian Seitz (chr.seitz@gmx.de), Programming distributed Systems Lab,
 *         University of Augsburg, Germany, www.ds-lab.org.
 */
public class SelectDatatypeWizardPage
		extends WizardPage
{

	/**
	 * The Combo for the DataType selection
	 */
	protected Combo typeCombo;

	/**
	 * The TextField to set a value
	 */
	protected Text valueField;

	/**
	 * The Button that opens a wizard to create new datatypes
	 */
	protected Button addButton;

	/**
	 * Hastable to store the relation between displayed name of a DataType and the
	 * DataType itself.
	 */
	protected Hashtable<String, DataType> typesTable = new Hashtable<String, DataType>();

	/**
	 * Remember the workbench during initialization.
	 */
	protected IWorkbench workbench;


	/**
	 * Create a new wizard page instance
	 * 
	 * @param pageId
	 *            The PageId
	 * @param workbench
	 *            The current workbench
	 */
	public SelectDatatypeWizardPage(String pageId, IWorkbench workbench)
	{
		super(pageId);
		this.workbench = workbench;
	}


	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.jface.dialogs.IDialogPage#createControl(org.eclipse.swt.widgets.Composite
	 * )
	 */
	public void createControl(Composite parent)
	{
		Composite composite = new Composite(parent, SWT.NONE);
		{
			GridLayout layout = new GridLayout();
			layout.numColumns = 3;
			composite.setLayout(layout);

			GridData data = new GridData();
			data.verticalAlignment = GridData.FILL;
			data.horizontalAlignment = GridData.FILL;
			data.grabExcessVerticalSpace = true;
			composite.setLayoutData(data);
		}

		// DataType selection
		Label typeLabel = new Label(composite, SWT.RIGHT);
		typeLabel
				.setText(org.eclipse.jwt.meta.PluginProperties.model_DataType_type + ":"); //$NON-NLS-1$
		typeCombo = new Combo(composite, SWT.READ_ONLY | SWT.DROP_DOWN);
		{
			GridData data = new GridData();
			data.horizontalAlignment = GridData.FILL;
			data.grabExcessHorizontalSpace = true;
			typeCombo.setLayoutData(data);
		}
		refreshDataTypes();

		// Creation of new data types
		addButton = new Button(composite, SWT.PUSH);
		addButton.setText(PluginProperties.wizards_AddDatatype_label);
		addButton.addSelectionListener(new SelectionAdapter()
		{

			@Override
			public void widgetSelected(SelectionEvent event)
			{
				CreateDatatypeWizard wizard = new CreateDatatypeWizard();
				wizard.init(PlatformUI.getWorkbench(), null);
				WizardDialog dialog = new NotResizableWizardDialog(GeneralHelper
						.getActiveShell(), wizard);
				dialog.create();
				dialog.open();

				refreshDataTypes();
			}
		});

		// Value selection
		Label valueLabel = new Label(composite, SWT.RIGHT);
		valueLabel.setText(org.eclipse.jwt.meta.PluginProperties.model_Data_value_name
				+ ":"); //$NON-NLS-1$
		valueField = new Text(composite, SWT.BORDER);
		{
			GridData data = new GridData();
			data.horizontalAlignment = GridData.FILL;
			data.grabExcessHorizontalSpace = true;
			data.horizontalSpan = 2;
			valueField.setLayoutData(data);
		}

		setPageComplete(validatePage());
		setControl(composite);
	}


	/**
	 * 
	 * @return The specified Value
	 */
	public String getValue()
	{
		return valueField.getText();
	}


	/**
	 * 
	 * @return The selected DataType
	 */
	public DataType getDataType()
	{
		return typesTable.get(typeCombo.getText());
	}


	/**
	 * Finish button is available if a DataType is selected
	 * 
	 * @return
	 */
	protected boolean validatePage()
	{
		if (typeCombo.getText() == "") //$NON-NLS-1$
		{
			setErrorMessage(null);
			return false;
		}
		return true;
	}

	/**
	 * 
	 */
	protected ModifyListener validator = new ModifyListener()
	{

		public void modifyText(ModifyEvent e)
		{
			setPageComplete(validatePage());
		}
	};


	/**
	 * Fills the combo with the available datatypes
	 */
	private void refreshDataTypes()
	{
		WEEditor editor = GeneralHelper.getActiveInstance();
		Object obj = editor.getModel();
		if (obj instanceof org.eclipse.jwt.meta.model.core.Package)
		{
			collectDataTypes((Package) obj);
		}
		ArrayList<String> names = new ArrayList<String>();
		for (Enumeration<String> en = typesTable.keys(); en.hasMoreElements();)
		{
			names.add(en.nextElement());

		}
		Collections.sort(names, new CaseInsensitiveComparator());
		String[] comboIn = new String[typesTable.size()];
		names.toArray(comboIn);
		typeCombo.setItems(comboIn);
		typeCombo.addModifyListener(validator);
	}


	/**
	 * Calls searchPackage for the "root" package and all of its subpackages
	 * 
	 * @param pack
	 *            The "root" package
	 */
	private void collectDataTypes(Package pack)
	{
		if (pack.getElements().size() != 0)
		{
			searchPackage(pack);
		}
		if (pack.getSubpackages().size() != 0)
		{
			List subPack = pack.getSubpackages();
			for (int i = 0; i < subPack.size(); i++)
			{
				collectDataTypes((Package) subPack.get(i));
			}
		}
	}


	/**
	 * Searches for DataTypes in a package and adds them to the hashtable
	 * 
	 * @param pack
	 */
	private void searchPackage(Package pack)
	{
		List elements = pack.getElements();
		for (int i = 0; i < elements.size(); i++)
		{
			if (elements.get(i) instanceof DataType)
			{
				DataType data = (DataType) elements.get(i);
				typesTable.put(data.getName(), data);
			}
		}
	}

	/**
	 * 
	 * Comparator which ignores casesensitivity
	 * 
	 * @author Christian Seitz (seitzchr@users.sourceforge.net)
	 */
	class CaseInsensitiveComparator
			implements java.util.Comparator
	{

		public int compare(Object o1, Object o2)
		{
			String s1 = o1.toString().toUpperCase();
			String s2 = o2.toString().toUpperCase();
			return s1.compareTo(s2);
		}
	}

}
