/*******************************************************************************
 * Copyright (c) 2011, 2012 Ericsson AB 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
 * 
 * Description:
 * 
 * This class implements an editable List-like widget 
 * 
 * Contributors:
 *   Sebastien Dubois - Created for Mylyn Review R4E project
 *   
 ******************************************************************************/
package org.eclipse.mylyn.reviews.r4e.ui.internal.utils;

import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.mylyn.reviews.r4e.core.model.R4EParticipant;
import org.eclipse.mylyn.reviews.r4e.ui.R4EUIPlugin;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.custom.TableEditor;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
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.Event;
import org.eclipse.swt.widgets.Item;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ScrollBar;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.forms.widgets.FormToolkit;

/**
 * @author Sebastien Dubois
 * @version $Revision: 1.0 $
 */
public class EditableListWidget {

	// ------------------------------------------------------------------------
	// Member variables
	// ------------------------------------------------------------------------

	/**
	 * Field fMainComposite.
	 */
	protected Composite fMainComposite = null;

	/**
	 * Field fMainTable.
	 */
	protected Table fMainTable = null;

	/**
	 * Field fAddButton.
	 */
	protected Button fAddButton = null;

	/**
	 * Field fRemoveButton.
	 */
	protected Button fRemoveButton = null;

	/**
	 * Field fListener.
	 */
	protected IEditableListListener fListener = null;

	/**
	 * Field fInstanceId.
	 */
	protected int fInstanceId = 0;

	/**
	 * Field fValues.
	 */
	protected String[] fValues = null;

	/**
	 * Field fEditableControl.
	 */
	Control fEditableControl = null;

	/**
	 * Field fEnabled.
	 */
	protected boolean fEnabled;

	// ------------------------------------------------------------------------
	// Constructor
	// ------------------------------------------------------------------------

	//TODO:  This should be made more generic to accept various tables.  Right now it is very hard-coded to our stuff...
	/**
	 * Constructor for EditableListWidget.
	 * 
	 * @param aToolkit
	 *            - FormToolkit
	 * @param aParent
	 *            - Composite
	 * @param aLayoutData
	 *            - Object
	 * @param aListener
	 *            - IEditableListListener
	 * @param aInstanceId
	 *            - int
	 * @param aEditableWidgetClass
	 *            - Class<?>
	 * @param aEditableValues
	 *            - String[]
	 */
	public EditableListWidget(FormToolkit aToolkit, Composite aParent, Object aLayoutData,
			IEditableListListener aListener, int aInstanceId, Class<?> aEditableWidgetClass, String[] aEditableValues) {
		fMainComposite = (null != aToolkit) ? aToolkit.createComposite(aParent) : new Composite(aParent, SWT.NONE);
		fMainComposite.setLayoutData(aLayoutData);
		fMainComposite.setLayout(new GridLayout(4, false));
		fListener = aListener;
		fInstanceId = aInstanceId;
		fValues = aEditableValues;
		createEditableListFromTable(aToolkit, aEditableWidgetClass);
	}

	// ------------------------------------------------------------------------
	// Methods
	// ------------------------------------------------------------------------

	/**
	 * Method dispose.
	 */
	public void dispose() {

		fMainTable.dispose();
		fMainComposite.dispose();
	}

	/**
	 * Method createEditableListFromTable. Builds the editable list in the provided table
	 * 
	 * @param aToolkit
	 *            - FormToolkit
	 * @param aEditableWidgetClass
	 *            - Class<?>
	 */
	public void createEditableListFromTable(FormToolkit aToolkit, final Class<?> aEditableWidgetClass) {

		final Composite tableComposite = (null != aToolkit) ? aToolkit.createComposite(fMainComposite) : new Composite(
				fMainComposite, SWT.NONE);
		fMainTable = (null != aToolkit)
				? aToolkit.createTable(tableComposite, SWT.FULL_SELECTION | SWT.BORDER)
				: new Table(tableComposite, SWT.FULL_SELECTION | SWT.BORDER);

		final GridData tableCompositeData = new GridData(GridData.FILL, GridData.FILL, true, true);
		if (aEditableWidgetClass.equals(Date.class) || aEditableWidgetClass.equals(Label.class)) {
			tableCompositeData.horizontalSpan = 1;
		} else {
			tableCompositeData.horizontalSpan = 2;
		}
		final TableColumnLayout tableColumnLayout = new TableColumnLayout();
		tableComposite.setLayout(tableColumnLayout);

		final TableColumn tableColumn = new TableColumn(fMainTable, SWT.NONE, 0);
		final TableColumn tableColumn2;
		fMainTable.setLinesVisible(true);

		if (aEditableWidgetClass.equals(Date.class) || aEditableWidgetClass.equals(Label.class)) {
			fMainTable.setHeaderVisible(true);
			tableColumn2 = new TableColumn(fMainTable, SWT.NONE, 1);
			if (aEditableWidgetClass.equals(Date.class)) {
				tableColumn.setText(R4EUIConstants.SPENT_TIME_COLUMN_HEADER);
				tableColumn2.setText(R4EUIConstants.ENTRY_TIME_COLUMN_HEADER);
			} else if (aEditableWidgetClass.equals(Label.class)) {
				tableColumn.setText(R4EUIConstants.ID_LABEL);
				tableColumn2.setText(R4EUIConstants.EMAIL_LABEL);
			}
			tableColumn.pack();
			tableColumn2.pack();
			tableColumnLayout.setColumnData(tableColumn, new ColumnWeightData(50, tableColumn.getWidth() * 2, true));
			tableColumnLayout.setColumnData(tableColumn2, new ColumnWeightData(50, tableColumn.getWidth(), true));

		} else {
			tableColumn2 = null; //only 1 column
			tableColumnLayout.setColumnData(tableColumn, new ColumnWeightData(10, 100, true));
		}
		tableComposite.setLayoutData(tableCompositeData);

		fMainComposite.addControlListener(new ControlListener() {
			public void controlResized(ControlEvent e) {

				//TODO:  This does not work 100% as resizing the colums lags when the parent area gets shrinked quickly.
				//        This causes the rightmost part of the table composite to be clipped away.
				//        This will need to be improved, see bug 356857.
				final Rectangle area = fMainTable.getClientArea();
				final Point size = tableComposite.computeSize(SWT.DEFAULT, SWT.DEFAULT);
				final ScrollBar vBar = fMainTable.getVerticalBar();
				final int vBarWidth = vBar.getSize().x;
				int width = area.width - vBarWidth * 3;
				if (width < 0) {
					return;
				}

				if (size.y > area.height + fMainTable.getHeaderHeight()) {
					// Subtract the scrollbar width from the total column width
					// if a vertical scrollbar will be required
					width -= vBarWidth;
				}

				// Set column width first and then resize the table to
				// match the client area width
				if (null != tableColumn2) {
					tableColumn.setWidth(width / 2);
					tableColumn2.setWidth(width - tableColumn.getWidth());
				} else {
					tableColumn.setWidth(width);
				}
			}

			public void controlMoved(ControlEvent e) {
				// ignor
			}
		});

		fMainTable.addListener(SWT.FocusOut, new Listener() {
			public void handleEvent(Event event) {
				if (fEnabled) {
					//Send items updated notification
					if (null != fListener) {
						//If items are empty, do not consider them
						final TableItem[] items = fMainTable.getItems();
						for (int i = 0; i < items.length; i++) {
							if (items[i].getText().trim().length() < 1) {
								fMainTable.remove(i);
							}
						}
						fListener.itemsUpdated(fMainTable.getItems(), fInstanceId);
					}
				}
			}
		});

		fMainTable.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event event) {
				if (null != fListener) {
					fListener.itemSelected(fMainTable.getSelection()[0], fInstanceId); //Only 1 element selected at any given time
				}
			}
		});

		final Composite buttonsComposite = (null != aToolkit)
				? aToolkit.createComposite(fMainComposite)
				: new Composite(fMainComposite, SWT.NONE);
		buttonsComposite.setLayout(new GridLayout());
		buttonsComposite.setLayoutData(new GridData(GridData.CENTER, SWT.TOP, false, false));

		fAddButton = (null != aToolkit) ? aToolkit.createButton(buttonsComposite, R4EUIConstants.BUTTON_ADD_LABEL,
				SWT.NONE) : new Button(buttonsComposite, SWT.NONE);
		fAddButton.setText(R4EUIConstants.BUTTON_ADD_LABEL);
		if (aEditableWidgetClass.equals(CCombo.class)) {
			if (null == fValues || 0 == fValues.length) {
				fAddButton.setEnabled(false);
			}
		}
		fRemoveButton = (null != aToolkit) ? aToolkit.createButton(buttonsComposite,
				R4EUIConstants.BUTTON_REMOVE_LABEL, SWT.NONE) : new Button(buttonsComposite, SWT.NONE);
		fRemoveButton.setText(R4EUIConstants.BUTTON_REMOVE_LABEL);
		if (0 == fMainTable.getItemCount()) {
			fRemoveButton.setEnabled(false);
		} else {
			fRemoveButton.setEnabled(true);
		}

		fAddButton.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
		fAddButton.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				if (aEditableWidgetClass.equals(Label.class)) {
					//Get participants to assign
					final List<R4EParticipant> participants = UIUtils.getAssignParticipants();
					TableItem newItem = null;
					for (R4EParticipant participant : participants) {
						newItem = null;
						String[] tableStrs = new String[2];
						tableStrs[0] = participant.getId();
						tableStrs[1] = participant.getEmail();
						//Check if values already exist
						for (TableItem item : fMainTable.getItems()) {
							if (item.getText(0).equals(tableStrs[0])) {
								newItem = item;
							}
						}
						if (null == newItem) {
							newItem = new TableItem(fMainTable, SWT.NONE);
						}
						fMainTable.showItem(newItem);
						newItem.setText(tableStrs);
					}
					if (null != newItem) {
						fMainTable.showItem(newItem);
					}
					if (null != fListener) {
						fListener.itemsUpdated(fMainTable.getItems(), fInstanceId);
					}
					return;
				}

				final TableItem newItem = new TableItem(fMainTable, SWT.NONE);
				fMainTable.showItem(newItem);
				if (aEditableWidgetClass.equals(Text.class)) {
					fEditableControl = new Text(fMainTable, SWT.SINGLE | SWT.BORDER);
					((Text) fEditableControl).addModifyListener(new ModifyListener() {
						public void modifyText(ModifyEvent me) {
							newItem.setText(((Text) fEditableControl).getText());
						}
					});
					((Text) fEditableControl).addKeyListener(new KeyListener() {

						public void keyReleased(KeyEvent ke) {
							if (ke.keyCode == SWT.CR) {
								return;
							}
						}

						public void keyPressed(KeyEvent ke) {
							// Nothing to do
						}
					});
				} else if (aEditableWidgetClass.equals(CCombo.class)) {
					fEditableControl = new CCombo(fMainTable, SWT.BORDER | SWT.READ_ONLY);
					//Only add the values not already in the table in the CCombo box
					final List<String> currentValues = new ArrayList<String>();
					for (String currentValue : fValues) {
						currentValues.add(currentValue);
					}
					final TableItem[] currentItems = fMainTable.getItems();
					for (TableItem currentItem : currentItems) {
						if (currentValues.contains(currentItem.getText())) {
							currentValues.remove(currentItem.getText());
						}
					}
					((CCombo) fEditableControl).setItems(currentValues.toArray(new String[currentValues.size()]));
					((CCombo) fEditableControl).addModifyListener(new ModifyListener() {
						public void modifyText(ModifyEvent me) {
							newItem.setText(((CCombo) fEditableControl).getText());
						}
					});
				} else if (aEditableWidgetClass.equals(Date.class)) {
					fEditableControl = new Text(fMainTable, SWT.NONE);
					final DateFormat dateFormat = new SimpleDateFormat(R4EUIConstants.DEFAULT_DATE_FORMAT);
					final String[] data = { ((Text) fEditableControl).getText(),
							dateFormat.format(Calendar.getInstance().getTime()) };
					newItem.setText(data);
					((Text) fEditableControl).addModifyListener(new ModifyListener() {
						public void modifyText(ModifyEvent me) {
							//Only accept numbers
							String newText = ((Text) fEditableControl).getText();
							try {
								Integer.valueOf(newText);
							} catch (NumberFormatException nfe) {
								if (newText.length() > 0) {
									newText = newText.substring(0, newText.length() - 1);
									((Text) fEditableControl).setText(newText);
									((Text) fEditableControl).setSelection(newText.length());
								}
							}
							newItem.setText(0, newText);
						}
					});
				} else {
					return;
				}
				fEditableControl.addFocusListener(new FocusListener() {
					public void focusLost(FocusEvent fe) {
						((Control) fe.getSource()).dispose();

						//Send items updated notification
						if (null != fListener) {
							//If items are empty, do not consider them
							final TableItem[] items = fMainTable.getItems();
							final int numColumns = fMainTable.getColumnCount();
							boolean isSameItem = false;
							for (int i = 0; i < items.length; i++) {
								if (items[i].getText().trim().length() < 1) {
									fMainTable.remove(i);
									return;
								}
							}

							//If items are already present, do not consider the duplicates
							if (items.length > 1) {
								for (int i = 0; i < items.length; i++) {
									for (int j = i + 1; j < items.length; j++) {
										isSameItem = true;
										for (int k = 0; k < numColumns; k++) {
											if (!items[i].getText(k).equals(items[j].getText(k))) {
												isSameItem = false;
												break; //at least one column is different go to next item
											}
										}
										if (isSameItem) {
											fMainTable.remove(j);
											return;
										}
									}
								}
							}
							fListener.itemsUpdated(fMainTable.getItems(), fInstanceId);
						}
					}

					public void focusGained(FocusEvent fe) {
						//Nothing to do
					}
				});

				fEditableControl.setFocus();
				final TableEditor editor = new TableEditor(fMainTable);
				editor.grabHorizontal = true;
				editor.grabVertical = true;
				editor.setEditor(fEditableControl, newItem, 0);
				fRemoveButton.setEnabled(true);
			}

			public void widgetDefaultSelected(SelectionEvent e) { // $codepro.audit.disable emptyMethod
			}
		});
		fRemoveButton.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, false));
		fRemoveButton.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent e) {
				final int numItems = fMainTable.getItemCount();
				if (numItems > 0) {
					//Find the table index for the first control
					final Control[] controls = fMainTable.getChildren();
					final int firstControlIndex = numItems - controls.length;

					//Currently selected item
					int tableItemIndex = fMainTable.getSelectionIndex();
					if (R4EUIConstants.INVALID_VALUE == tableItemIndex) {
						//Remove the selected element (and control if there is one) or the last one if none is selected
						tableItemIndex = numItems - 1;
					}
					if (tableItemIndex >= firstControlIndex) {
						controls[tableItemIndex - firstControlIndex].dispose();
					}
					fMainTable.getItem(tableItemIndex).dispose();
				}
				if (0 == fMainTable.getItemCount()) {
					fRemoveButton.setEnabled(false);
				} else {
					fRemoveButton.setEnabled(true);
				}
				if (null != fListener) {
					fListener.itemsUpdated(fMainTable.getItems(), fInstanceId);
				}
				fMainTable.redraw();
			}

			public void widgetDefaultSelected(SelectionEvent e) { // $codepro.audit.disable emptyMethod
			}
		});
	}

	/**
	 * Method removeAll.
	 */
	public void removeAll() {
		fMainTable.removeAll();
	}

	/**
	 * Method addItem.
	 * 
	 * @return Item
	 */
	public Item addItem() {
		return new TableItem(fMainTable, SWT.NONE);
	}

	/**
	 * Method getItem.
	 * 
	 * @param aIndex
	 *            - int
	 * @return Item
	 */
	public Item getItem(int aIndex) {
		return fMainTable.getItem(aIndex);
	}

	/**
	 * Method getSelectedItem.
	 * 
	 * @return Item
	 */
	public Item getSelectedItem() {
		if (0 == fMainTable.getSelection().length) {
			return null;
		}
		return fMainTable.getSelection()[0]; //Only one element selectable at any given time
	}

	/**
	 * Method getItems.
	 * 
	 * @return Item[]
	 */
	public Item[] getItems() {
		return fMainTable.getItems();
	}

	/**
	 * Method getItemCount.
	 * 
	 * @return int
	 */
	public int getItemCount() {
		return fMainTable.getItemCount();
	}

	/**
	 * Method setEnabled.
	 * 
	 * @param aEnabled
	 *            - boolean
	 */
	public void setEnabled(boolean aEnabled) {
		fEnabled = aEnabled;
		for (TableItem item : fMainTable.getItems()) {
			if (aEnabled) {
				item.setForeground(UIUtils.ENABLED_FONT_COLOR);
			} else {
				item.setForeground(UIUtils.DISABLED_FONT_COLOR);
			}
		}
		if (!aEnabled) {
			fAddButton.setEnabled(aEnabled);
			fRemoveButton.setEnabled(aEnabled);
		} else {
			updateButtons();
		}
	}

	/**
	 * Method setVisible.
	 * 
	 * @param aVisible
	 *            - boolean
	 */
	public void setVisible(boolean aVisible) {
		fMainComposite.setVisible(aVisible);
		fMainTable.setVisible(aVisible);
		fAddButton.setVisible(aVisible);
		fRemoveButton.setVisible(aVisible);
	}

	/**
	 * Method getComposite.
	 * 
	 * @return Composite
	 */
	public Composite getComposite() {
		return fMainComposite;
	}

	/**
	 * Method setEditableValues.
	 * 
	 * @param aValues
	 *            - String[]
	 */
	public void setEditableValues(String[] aValues) {
		fValues = aValues;
		if (null == fValues || 0 == fValues.length) {
			fAddButton.setEnabled(false);
		} else {
			fAddButton.setEnabled(true);
		}
		if (0 == fMainTable.getItemCount()) {
			fRemoveButton.setEnabled(false);
		} else {
			fRemoveButton.setEnabled(true);
		}
	}

	/**
	 * Method setTableHeader.
	 * 
	 * @param aIndex
	 *            int
	 * @param aText
	 *            String
	 */
	public void setTableHeader(int aIndex, String aText) {
		try {
			final TableColumn column = fMainTable.getColumn(aIndex);
			column.setText(aText);
			updateTable();
		} catch (IllegalArgumentException e) {
			R4EUIPlugin.Ftracer.traceWarning("Exception: " + e.toString() + " (" + e.getMessage() + ")");
			R4EUIPlugin.getDefault().logWarning("Exception: " + e.toString(), e);
		}
	}

	/**
	 * Method setToolTipText.
	 * 
	 * @param aTooltip
	 *            String
	 */
	public void setToolTipText(String aTooltip) {
		fMainComposite.setToolTipText(aTooltip);
	}

	/**
	 * Method updateButtons.
	 */
	public void updateButtons() {
		if (0 == fMainTable.getItemCount()) {
			fRemoveButton.setEnabled(false);
		} else {
			fRemoveButton.setEnabled(true);
		}
		fAddButton.setEnabled(true);
	}

	/**
	 * Method updateButtons.
	 */
	public void updateTable() {
		for (TableColumn column : fMainTable.getColumns()) {
			column.pack();
		}
	}

	//Test methods
	/**
	 * Method remove.
	 * 
	 * @param removeStr
	 */
	public void remove(String removeStr) {
		for (TableItem item : fMainTable.getItems()) {
			if (item.getText().equals(removeStr)) {
				fMainTable.setSelection(item);
			}
		}
		fRemoveButton.notifyListeners(SWT.Selection, null);
	}

	/**
	 * Method add.
	 * 
	 * @param addStr
	 */
	public void add(String addStr) {
		fAddButton.notifyListeners(SWT.Selection, null);
		if (null != fEditableControl) {
			if (fEditableControl instanceof Text) {
				((Text) fEditableControl).setText(addStr);
			} else if (fEditableControl instanceof CCombo) {
				final String[] items = ((CCombo) fEditableControl).getItems();
				for (int index = 0; index < items.length; index++) {
					if (items[index].equals(addStr)) {
						((CCombo) fEditableControl).select(index);
					}
				}
			}
		}
	}
}
