/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.epic.debug.util;

import java.util.ArrayList;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.InputDialog;
import org.eclipse.jface.preference.FieldEditor;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.util.Assert;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.List;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Widget;
import org.epic.debug.PerlLaunchConfigurationConstants;

/**
 * An abstract field editor that manages a list of input values.
 * The editor displays a list containing the values, buttons for
 * adding and removing values, and Up and Down buttons to adjust
 * the order of elements in the list.
 * <p>
 * Subclasses must implement the <code>parseString</code>,
 * <code>createList</code>, and <code>getNewInputObject</code>
 * framework methods.
 * </p>
 */
public class ListEditor extends FieldEditor
{

	private IPropertyChangeListener mTab;

	//ILaunchConfigurationWorkingCopy mLaunch ;
	/**
	 * The list widget; <code>null</code> if none
	 * (before creation or after disposal).
	 */
	private List list;

	/**
	 * The button box containing the Add, Remove, Up, and Down buttons;
	 * <code>null</code> if none (before creation or after disposal).
	 */
	private Composite buttonBox;

	/**
	 * The Add button.
	 */
	private Button addButton;
	private Button editButton;
	/**
	 * The Remove button.
	 */
	private Button removeButton;

	/**
	 * The Up button.
	 */
	private Button upButton;

	/**
	 * The Down button.
	 */
	private Button downButton;

	/**
	 * The selection listener.
	 */
	private SelectionListener selectionListener;


	
	

	/**
	 * Creates a new list field editor
	 */
	protected ListEditor()
	{
	}
	/**
	 * Creates a list field editor.
	 *
	 * @param name the name of the preference this field editor works on
	 * @param labelText the label text of the field editor
	 * @param parent the parent of the field editor's control
	 */
	public ListEditor(
		String name,
		Composite parent,
		IPropertyChangeListener tab)
	{
		init(name, "CGI-Script Environment Variables");
		createControl(parent);
		mTab = tab;
		
	
	}
	/**
	 * Notifies that the Add button has been pressed.
	 */
	private void addPressed()
	{
		setPresentsDefaultValue(false);
		String input = getNewInputObject();

		if (input != null)
		{

			int index = list.getSelectionIndex();
			if (index >= 0)
				index++;
			else
				index = 0;
				
			list.add(input, index);
			list.select(index);

			selectionChanged();
			listHasChanged();
			firePropertyChange();

		}
	}

	private void editPressed()
	{
		int index = list.getSelectionIndex();

		setPresentsDefaultValue(false);
		String input = list.getItem(index);
		if (index < 0)
			return;

		InputDialog dialog =
			new InputDialog(
				getShell(),
				"Edit Envirement Variable ",
				"Envirement Variable",
				input,
				null);
		int returnCode = dialog.open();

		if (returnCode == Window.OK)
		{
			input = dialog.getValue();
		} else
			return;

		if (input != null)
		{
			list.setItem(index, input);
			selectionChanged();
			firePropertyChange();
			listHasChanged();
		}
	}
	/* (non-Javadoc)
	 * Method declared on FieldEditor.
	 */
	protected void adjustForNumColumns(int numColumns)
	{
		Control control = getLabelControl();
		((GridData) control.getLayoutData()).horizontalSpan = numColumns;
		((GridData) list.getLayoutData()).horizontalSpan = numColumns - 1;
	}
	/**
	 * Creates the Add, Remove, Up, and Down button in the given button box.
	 *
	 * @param buttonBox the box for the buttons
	 */
	private void createButtons(Composite buttonBox)
	{
		addButton = createPushButton(buttonBox, "ListEditor.add"); //$NON-NLS-1$
		removeButton = createPushButton(buttonBox, "ListEditor.remove");
		editButton = createPushButton(buttonBox, "Edit"); //$NON-NLS-1$
		upButton = createPushButton(buttonBox, "ListEditor.up"); //$NON-NLS-1$
		downButton = createPushButton(buttonBox, "ListEditor.down"); //$NON-NLS-1$
	}

	/**
	 * Helper method to create a push button.
	 *
	 * @param parent the parent control
	 * @param key the resource name used to supply the button's label text
	 */
	private Button createPushButton(Composite parent, String key)
	{
		Button button = new Button(parent, SWT.PUSH);
		button.setText(JFaceResources.getString(key));
		button.setFont(parent.getFont());
		GridData data = new GridData(GridData.FILL_HORIZONTAL);
		data.heightHint =
			convertVerticalDLUsToPixels(button, IDialogConstants.BUTTON_HEIGHT);
		int widthHint =
			convertHorizontalDLUsToPixels(
				button,
				IDialogConstants.BUTTON_WIDTH);
		data.widthHint =
			Math.max(
				widthHint,
				button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
		button.setLayoutData(data);
		button.addSelectionListener(getSelectionListener());
		return button;
	}
	/**
	 * Creates a selection listener.
	 */
	public void createSelectionListener()
	{
		selectionListener = new SelectionAdapter()
		{
			public void widgetSelected(SelectionEvent event)
			{
				Widget widget = event.widget;
				if (widget == addButton)
				{
					addPressed();
				} else
					if (widget == removeButton)
					{
						removePressed();
					} else
						if (widget == upButton)
						{
							upPressed();
						} else
							if (widget == downButton)
							{
								downPressed();
							} else
								if (widget == editButton)
								{
									editPressed();
								} else
									if (widget == list)
									{
										selectionChanged();
									}
			}
		};
	}
	/* (non-Javadoc)
	 * Method declared on FieldEditor.
	 */
	protected void doFillIntoGrid(Composite parent, int numColumns)
	{
		Control control = getLabelControl(parent);
		GridData gd = new GridData();
		gd.horizontalSpan = numColumns;
		control.setLayoutData(gd);

		list = getListControl(parent);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		//gd.verticalAlignment = GridData.FILL;
		gd.heightHint = 100;
		gd.horizontalSpan = numColumns - 1;
		gd.grabExcessHorizontalSpace = true;
		list.setLayoutData(gd);

		buttonBox = getButtonBoxControl(parent);

		gd = new GridData();
		gd.verticalAlignment = GridData.BEGINNING;
		buttonBox.setLayoutData(gd);
	}
	/* (non-Javadoc)
	 * Method declared on FieldEditor.
	 */
	public void initilizeFrom(ILaunchConfiguration fLaunch)
	{
		if (list != null)
		{

			int count = 0;
			String res = null;
			list.removeAll();
			count = 0;

			ArrayList envs = null;

			try
			{
				envs =
					(ArrayList) fLaunch.getAttribute(
						PerlLaunchConfigurationConstants.ATTR_CGI_ENV,
						(ArrayList) null);
			} catch (CoreException e1)
			{
				// TODO Auto-generated catch block
				e1.printStackTrace();
			}

			if (envs != null)
				for (int x = 0; x < envs.size(); ++x)
					list.add((String) envs.get(x));
		}
	}

	/* (non-Javadoc)
	 * Method declared on FieldEditor.
	 */
	protected void doLoadDefault()
	{
		if (list != null)
		{
			list.removeAll();

		}

	}
	/* (non-Javadoc)
	 * Method declared on FieldEditor.
	 */
	public void doApply(ILaunchConfigurationWorkingCopy fLaunch)
	{

		if (list != null)
		{

			String[] vars = list.getItems();
			ArrayList al = new ArrayList();

			for (int i = 0; i < vars.length; i++)
			{
				al.add(vars[i]);
			}
			fLaunch.setAttribute(
				PerlLaunchConfigurationConstants.ATTR_CGI_ENV,
				al);
			//				try
			//				{
			//					//fLaunch.doSave();
			//				} catch (CoreException e)
			//				{
			//					// TODO Auto-generated catch block
			//					e.printStackTrace();
			//				}
		}
	}
	/**
	 * Notifies that the Down button has been pressed.
	 */
	private void downPressed()
	{
		swap(false);
		listHasChanged();
		firePropertyChange();
	}
	/**
	 * Returns this field editor's button box containing the Add, Remove,
	 * Up, and Down button.
	 *
	 * @param parent the parent control
	 * @return the button box
	 */
	public Composite getButtonBoxControl(Composite parent)
	{
		if (buttonBox == null)
		{
			buttonBox = new Composite(parent, SWT.NULL);
			GridLayout layout = new GridLayout();
			layout.numColumns = 3;
			layout.marginWidth = 0;
			buttonBox.setLayout(layout);
			createButtons(buttonBox);
			buttonBox.addDisposeListener(new DisposeListener()
			{
				public void widgetDisposed(DisposeEvent event)
				{
					addButton = null;
					removeButton = null;
					upButton = null;
					downButton = null;
					buttonBox = null;
				}
			});

		} else
		{
			checkParent(buttonBox, parent);
		}

		selectionChanged();
		return buttonBox;
	}
	/**
	 * Returns this field editor's list control.
	 *
	 * @param parent the parent control
	 * @return the list control
	 */
	public List getListControl(Composite parent)
	{
		if (list == null)
		{
			list =
				new List(
					parent,
					SWT.BORDER | SWT.SINGLE | SWT.V_SCROLL | SWT.H_SCROLL);
			list.setFont(parent.getFont());
			list.addSelectionListener(getSelectionListener());
			list.addDisposeListener(new DisposeListener()
			{
				public void widgetDisposed(DisposeEvent event)
				{
					list = null;
				}
			});
		} else
		{
			checkParent(list, parent);
		}
		return list;
	}

	public String[] getItems()
	{
		return list.getItems();
	}

	/**
	 * Creates and returns a new item for the list.
	 * <p>
	 * Subclasses must implement this method.
	 * </p>
	 *
	 * @return a new item
	 */
	String getNewInputObject()
	{

		InputDialog dialog =
			new InputDialog(
				getShell(),
				"Add Envirement Variable ",
				"Envirement Variable",
				null,
				null);
		int returnCode = dialog.open();

		if (returnCode == Window.OK)
		{

			return (dialog.getValue());

		}
		return (null);
	}

	void firePropertyChange()
	{
		mTab.propertyChange(new PropertyChangeEvent(this, " ", " ", " "));
	}
	/* (non-Javadoc)
	 * Method declared on FieldEditor.
	 */
	public int getNumberOfControls()
	{
		return 2;
	}
	/**
	 * Returns this field editor's selection listener.
	 * The listener is created if nessessary.
	 *
	 * @return the selection listener
	 */
	private SelectionListener getSelectionListener()
	{
		if (selectionListener == null)
			createSelectionListener();
		return selectionListener;
	}
	/**
	 * Returns this field editor's shell.
	 * <p>
	 * This method is internal to the framework; subclassers should not call
	 * this method.
	 * </p>
	 *
	 * @return the shell
	 */
	protected Shell getShell()
	{
		if (addButton == null)
			return null;
		return addButton.getShell();
	}
	/**
	 * Splits the given string into a list of strings.
	 * This method is the converse of <code>createList</code>.
	 * <p>
	 * Subclasses must implement this method.
	 * </p>
	 *
	 * @param stringList the string
	 * @return an array of <code>String</code>
	 * @see #createList
	 */
	String[] parseString(String stringList)
	{
		return null;
	}
	/**
	 * Notifies that the Remove button has been pressed.
	 */
	private void removePressed()
	{
		setPresentsDefaultValue(false);
		int index = list.getSelectionIndex();
		if (index >= 0)
		{
			list.remove(index);
			int max_index = list.getItems().length - 1;

			if (max_index >= 0)
			{

				if (index > max_index)
					index = max_index;

				list.setSelection(index);
			}

			selectionChanged();
			firePropertyChange();
		}
	}
	/**
	 * Notifies that the list selection has changed.
	 */
	private void selectionChanged()
	{

		int index = list.getSelectionIndex();
		int size = list.getItemCount();

		removeButton.setEnabled(index >= 0);
		editButton.setEnabled(index >= 0);
		upButton.setEnabled(size > 1 && index > 0);
		downButton.setEnabled(size > 1 && index >= 0 && index < size - 1);
		//is.fireValueChanged("nix","nix","nix");
	}
	/* (non-Javadoc)
	 * Method declared on FieldEditor.
	 */
	public void setFocus()
	{
		if (list != null)
		{
			list.setFocus();
		}
	}
	/**
	 * Moves the currently selected item up or down.
	 *
	 * @param up <code>true</code> if the item should move up,
	 *  and <code>false</code> if it should move down
	 */
	private void swap(boolean up)
	{
		setPresentsDefaultValue(false);
		int index = list.getSelectionIndex();
		int target = up ? index - 1 : index + 1;

		if (index >= 0)
		{
			String[] selection = list.getSelection();
			Assert.isTrue(selection.length == 1);
			list.remove(index);
			list.add(selection[0], target);
			list.setSelection(target);
		}
		selectionChanged();
	}
	/**
	 * Notifies that the Up button has been pressed.
	 */
	private void upPressed()
	{
		swap(true);
		firePropertyChange();
		listHasChanged();
	}

	/*
	 * @see FieldEditor.setEnabled(boolean,Composite).
	 */
	public void setEnabled(boolean enabled, Composite parent)
	{
		super.setEnabled(enabled, parent);
		getListControl(parent).setEnabled(enabled);
		addButton.setEnabled(enabled);
		removeButton.setEnabled(enabled);
		upButton.setEnabled(enabled);
		downButton.setEnabled(enabled);
	}
	/* (non-Javadoc)
	 * @see org.eclipse.jface.preference.FieldEditor#doLoad()
	 */
	protected void doLoad()
	{
		// TODO Auto-generated method stub

	}
	/* (non-Javadoc)
	 * @see org.eclipse.jface.preference.FieldEditor#doStore()
	 */
	protected void doStore()
	{
		// TODO Auto-generated method stub

	}

	void listHasChanged()
	{

	}
	
	
	

}