/*******************************************************************************
 * Copyright (c) 2008, 2009 Oracle. 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:
 *     Oracle - initial API and implementation
 ******************************************************************************/
package org.eclipse.jpt.ui.internal.swt;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EventListener;
import java.util.EventObject;
import java.util.Iterator;
import java.util.List;

import org.eclipse.jface.viewers.ITableLabelProvider;
import org.eclipse.jpt.ui.internal.listeners.SWTCollectionChangeListenerWrapper;
import org.eclipse.jpt.ui.internal.listeners.SWTListChangeListenerWrapper;
import org.eclipse.jpt.utility.internal.CollectionTools;
import org.eclipse.jpt.utility.internal.ListenerList;
import org.eclipse.jpt.utility.internal.StringTools;
import org.eclipse.jpt.utility.internal.model.value.PropertyCollectionValueModelAdapter;
import org.eclipse.jpt.utility.model.event.CollectionAddEvent;
import org.eclipse.jpt.utility.model.event.CollectionChangeEvent;
import org.eclipse.jpt.utility.model.event.CollectionRemoveEvent;
import org.eclipse.jpt.utility.model.event.ListChangeEvent;
import org.eclipse.jpt.utility.model.listener.CollectionChangeListener;
import org.eclipse.jpt.utility.model.listener.ListChangeListener;
import org.eclipse.jpt.utility.model.value.CollectionValueModel;
import org.eclipse.jpt.utility.model.value.ListValueModel;
import org.eclipse.jpt.utility.model.value.PropertyValueModel;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;

/**
 * This adapter provides a more object-oriented interface to the items and
 * selected items in a table.
 * 'listHolder' contains the data of a single column in the column.
 * 'selectedItemsHolder' contains the data of a single column in 'listHolder'
 * that are selected in the table.
 */
@SuppressWarnings("nls")
public class TableModelAdapter<E> {

	// ********** model **********
	/**
	 * A value model on the underlying model list.
	 */
	protected final ListValueModel<E> listHolder;

	/**
	 * A listener that allows us to synchronize the table's contents with
	 * the model list.
	 */
	protected final ListChangeListener listChangeListener;

	/**
	 * A value model on the underlying model selections.
	 */
	protected final CollectionValueModel<E> selectedItemsHolder;

	/**
	 * A listener that allows us to synchronize the table's selection with
	 * the model selections.
	 */
	protected final CollectionChangeListener selectedItemsChangeListener;

	/**
	 * The table we keep synchronized with the model list.
	 */
	protected final Table table;

	/**
	 * A listener that allows us to synchronize our selection list holder
	 * with the table's selection.
	 */
	protected final SelectionListener tableSelectionListener;

	/**
	 * Clients that are interested in selection change events.
	 */
	@SuppressWarnings("unchecked")
	protected final ListenerList<SelectionChangeListener> selectionChangeListenerList;

	/**
	 * Clients that are interested in double click events.
	 */
	@SuppressWarnings("unchecked")
	protected final ListenerList<DoubleClickListener> doubleClickListenerList;

	/**
	 * A listener that allows us to stop listening to stuff when the table
	 * is disposed.
	 */
	protected final DisposeListener tableDisposeListener;

	/**
	 * This label provider is responsible to convert a property at a column index
	 * to a string value.
	 */
	protected final ITableLabelProvider labelProvider;

	/**
	 * The column adapter is responsible to return the count of columns and to
	 * create the value holders for all the properties.
	 */
	private ColumnAdapter<E> columnAdapter;

	/**
	 * Keeps track of the <code>TableItemModelAdapter</code>s that were created
	 * for each item of the list holder.
	 */
	private List<TableItemModelAdapter> tableItemModelAdapters;


	// ********** static methods **********

	/**
	 * Adapt the specified model list and selection to the specified table.
	 * Use the specified string converter to convert the model items to strings
	 * to be displayed in the table.
	 */
	public static <T> TableModelAdapter<T> adapt(
			ListValueModel<T> listHolder,
			PropertyValueModel<T> selectedItemHolder,
			Table table,
			ColumnAdapter<T> columnAdapter,
			ITableLabelProvider labelProvider)
	{
		return new TableModelAdapter<T>(
			listHolder,
			new PropertyCollectionValueModelAdapter<T>(selectedItemHolder),
			table,
			columnAdapter,
			labelProvider
		);
	}


	// ********** constructors **********

	/**
	 * Constructor - the list holder, selections holder, table, and
	 * string converter are required.
	 */
	protected TableModelAdapter(
			ListValueModel<E> listHolder,
			CollectionValueModel<E> selectedItemsHolder,
			Table table,
			ColumnAdapter<E> columnAdapter,
			ITableLabelProvider labelProvider)
	{
		super();
		if ((listHolder == null) || (selectedItemsHolder == null) || (table == null) || (labelProvider == null)) {
			throw new NullPointerException();
		}
		this.listHolder = listHolder;
		this.selectedItemsHolder = selectedItemsHolder;
		this.table = table;
		this.columnAdapter = columnAdapter;
		this.labelProvider = labelProvider;
		this.tableItemModelAdapters = new ArrayList<TableItemModelAdapter>(columnAdapter.columnCount());

		this.listChangeListener = this.buildListChangeListener();
		this.listHolder.addListChangeListener(ListValueModel.LIST_VALUES, this.listChangeListener);

		this.selectedItemsChangeListener = this.buildSelectedItemsChangeListener();
		this.selectedItemsHolder.addCollectionChangeListener(CollectionValueModel.VALUES, this.selectedItemsChangeListener);

		this.tableSelectionListener = this.buildTableSelectionListener();
		this.table.addSelectionListener(this.tableSelectionListener);

		this.selectionChangeListenerList = this.buildSelectionChangeListenerList();
		this.doubleClickListenerList = this.buildDoubleClickListenerList();

		this.tableDisposeListener = this.buildTableDisposeListener();
		this.table.addDisposeListener(this.tableDisposeListener);

		this.synchronizeTable();
	}


	// ********** initialization **********

	protected ListChangeListener buildListChangeListener() {
		return new SWTListChangeListenerWrapper(this.buildListChangeListener_());
	}

	protected ListChangeListener buildListChangeListener_() {
		return new ListChangeListener() {
			public void itemsAdded(ListChangeEvent event) {
				TableModelAdapter.this.listItemsAdded(event);
			}
			public void itemsRemoved(ListChangeEvent event) {
				TableModelAdapter.this.listItemsRemoved(event);
			}
			public void itemsMoved(ListChangeEvent event) {
				TableModelAdapter.this.listItemsMoved(event);
			}
			public void itemsReplaced(ListChangeEvent event) {
				TableModelAdapter.this.listItemsReplaced(event);
			}
			public void listCleared(ListChangeEvent event) {
				TableModelAdapter.this.listCleared(event);
			}
			public void listChanged(ListChangeEvent event) {
				TableModelAdapter.this.listChanged(event);
			}
			@Override
			public String toString() {
				return "list listener";
			}
		};
	}

	protected CollectionChangeListener buildSelectedItemsChangeListener() {
		return new SWTCollectionChangeListenerWrapper(this.buildSelectedItemsChangeListener_());
	}

	protected CollectionChangeListener buildSelectedItemsChangeListener_() {
		return new CollectionChangeListener() {
			public void itemsAdded(CollectionAddEvent event) {
				TableModelAdapter.this.selectedItemsAdded(event);
			}
			public void itemsRemoved(CollectionRemoveEvent event) {
				TableModelAdapter.this.selectedItemsRemoved(event);
			}
			public void collectionCleared(CollectionChangeEvent event) {
				TableModelAdapter.this.selectedItemsCleared(event);
			}
			public void collectionChanged(CollectionChangeEvent event) {
				TableModelAdapter.this.selectedItemsChanged(event);
			}
			@Override
			public String toString() {
				return "selected items listener";
			}
		};
	}

	protected SelectionListener buildTableSelectionListener() {
		return new SelectionListener() {
			public void widgetSelected(SelectionEvent event) {
				TableModelAdapter.this.tableSelectionChanged(event);
			}
			public void widgetDefaultSelected(SelectionEvent event) {
				TableModelAdapter.this.tableDoubleClicked(event);
			}
			@Override
			public String toString() {
				return "table selection listener";
			}
		};
	}

	@SuppressWarnings("unchecked")
	protected ListenerList<DoubleClickListener> buildDoubleClickListenerList() {
		return new ListenerList<DoubleClickListener>(DoubleClickListener.class);
	}

	@SuppressWarnings("unchecked")
	protected ListenerList<SelectionChangeListener> buildSelectionChangeListenerList() {
		return new ListenerList<SelectionChangeListener>(SelectionChangeListener.class);
	}

	protected DisposeListener buildTableDisposeListener() {
		return new DisposeListener() {
			public void widgetDisposed(DisposeEvent event) {
				TableModelAdapter.this.tableDisposed(event);
			}
			@Override
			public String toString() {
				return "table dispose listener";
			}
		};
	}

	protected void synchronizeTable() {
		this.synchronizeTableColumns();
		this.synchronizeTableItems();
		this.synchronizeTableSelection();
	}


	// ********** list **********

	/**
	 * Creates the table colums.
	 */
	protected void synchronizeTableColumns() {
		if (this.table.isDisposed()) {
			return;
		}

		int columnCount = this.columnAdapter.columnCount();

		for (int index = 0; index < columnCount; index++) {
			TableColumn tableColumn = new TableColumn(this.table, SWT.NULL, index);
			tableColumn.setMoveable(false);
			tableColumn.setResizable(true);
			tableColumn.setWidth(100);

			String columnName = this.columnAdapter.columnName(index);

			if (columnName == null) {
				columnName = "";
			}

			tableColumn.setText(columnName);
		}
	}

	/**
	 * Brute force synchronization of table with the model list.
	 */
	protected void synchronizeTableItems() {
		if (this.table.isDisposed()) {
			return;
		}

		for (int index = table.getItemCount(); --index >= 0; ) {
			this.table.remove(index);
			this.tableItemModelAdapters.remove(index);
		}

		int itemCount = this.listHolder.size();

		for (int index = 0; index < itemCount; index++) {

			TableItem tableItem = new TableItem(this.table, SWT.NULL, index);
			tableItem.setData(this.listHolder.get(index));

			TableItemModelAdapter adapter = buildItemModel(tableItem);
			tableItemModelAdapters.add(adapter);
		}
	}

	/**
	 * The model has changed - synchronize the table.
	 */
	protected void listItemsAdded(ListChangeEvent event) {

		if (this.table.isDisposed()) {
			return;
		}

		int index = event.getIndex();

		for (E item : this.getItems(event)) {

			TableItem tableItem = new TableItem(this.table, SWT.NULL, index);
			tableItem.setData(item);

			TableItemModelAdapter adapter = this.buildItemModel(tableItem);
			tableItemModelAdapters.add(index++, adapter);
		}
	}

	/**
	 * The model has changed - synchronize the table.
	 */
	protected void listItemsRemoved(ListChangeEvent event) {

		if (this.table.isDisposed()) {
			return;
		}

		this.table.remove(event.getIndex(), event.getIndex() + event.getItemsSize() - 1);

		for (int index = event.getIndex() + event.getItemsSize(); --index >= event.getIndex(); ) {
			tableItemModelAdapters.remove(index);
		}
	}

	/**
	 * The model has changed - synchronize the table.
	 */
	protected void listItemsMoved(ListChangeEvent event) {

		if (this.table.isDisposed()) {
			return;
		}

		int length        = event.getMoveLength();
		int sourceIndex   = event.getSourceIndex();
		int targetIndex   = event.getTargetIndex();
		int lowStartIndex = Math.min(targetIndex, sourceIndex);
		int hiStartIndex  = Math.max(targetIndex, sourceIndex);

		Object[] items = new Object[hiStartIndex - lowStartIndex + length];
		int itemsIndex = items.length;

		// Remove the TableItems wrapping the moved items
		for (int index = hiStartIndex + length; --index >= lowStartIndex; ) {

			TableItemModelAdapter tableItemModel = this.tableItemModelAdapters.get(index);
			items[--itemsIndex] = tableItemModel.tableItem.getData();

			// Remove the TableItem, which will also dispose TableItemModelAdapter
			this.table.remove(index);
		}

		// Move the items so they can retrieved in the right order when
		// re-creating the TableItems
		CollectionTools.move(
			items,
			targetIndex - lowStartIndex,
			sourceIndex - lowStartIndex,
			length
		);

		itemsIndex = 0;

		// Add TableItems for the moved items
		for (int index = lowStartIndex; index <= hiStartIndex + length - 1; index++) {

			// Create the new TableItem
			TableItem tableItem = new TableItem(this.table, SWT.NULL, index);
			tableItem.setData(items[itemsIndex++]);

			// Adapt it with a model adapter
			TableItemModelAdapter adapter = this.buildItemModel(tableItem);
			tableItemModelAdapters.set(index, adapter);
		}
	}


	private TableItemModelAdapter buildItemModel(TableItem tableItem) {
		return TableItemModelAdapter.adapt(
			tableItem,
			columnAdapter,
			labelProvider
		);
	}

	/**
	 * The model has changed - synchronize the table.
	 */
	protected void listItemsReplaced(ListChangeEvent event) {
		if (this.table.isDisposed()) {
			return;
		}

		int rowIndex = event.getIndex();

		for (E item : this.getItems(event)) {
			TableItem tableItem = this.table.getItem(rowIndex);
			tableItem.setData(item);

			TableItemModelAdapter adapter = tableItemModelAdapters.get(rowIndex);

			int columnCount = this.columnAdapter.columnCount();
			boolean revalidate = (columnCount == 1);

			for (int columnIndex = columnCount; --columnIndex >= 0; ) {
				adapter.tableItemChanged(columnIndex, tableItem.getData(), revalidate);
			}

			rowIndex++;
		}
	}

	/**
	 * The model has changed - synchronize the table.
	 */
	protected void listCleared(@SuppressWarnings("unused") ListChangeEvent event) {
		if (this.table.isDisposed()) {
			return;
		}
		this.table.removeAll();
	}

	/**
	 * The model has changed - synchronize the table.
	 */
	protected void listChanged(@SuppressWarnings("unused") ListChangeEvent event) {
		this.synchronizeTableItems();
	}

	// minimized scope of suppressed warnings
	@SuppressWarnings("unchecked")
	protected Iterable<E> getItems(ListChangeEvent event) {
		return (Iterable<E>) event.getItems();
	}


	// ********** selected items **********

	protected int indexOf(E item) {
		int len = this.listHolder.size();
		for (int i = 0; i < len; i++) {
			if (this.listHolder.get(i) == item) {
				return i;
			}
		}
		return -1;
	}

	protected void synchronizeTableSelection() {
		if (this.table.isDisposed()) {
			return;
		}
		int[] indices = new int[this.selectedItemsHolder.size()];
		int i = 0;
		for (Iterator<E> stream = this.selectedItemsHolder.iterator(); stream.hasNext(); ) {
			indices[i++] = this.indexOf(stream.next());
		}
		this.table.deselectAll();
		this.table.select(indices);
	}

	protected void selectedItemsAdded(CollectionAddEvent event) {
		if (this.table.isDisposed()) {
			return;
		}
		this.table.select(this.getIndices(event.getAddedItemsSize(), this.getAddedItems(event)));
	}

	protected void selectedItemsRemoved(CollectionRemoveEvent event) {
		if (this.table.isDisposed()) {
			return;
		}
		this.table.deselect(this.getIndices(event.getRemovedItemsSize(), this.getRemovedItems(event)));
	}

	protected int[] getIndices(int itemsSize, Iterable<E> items) {
		int[] indices = new int[itemsSize];
		int i = 0;
		for (E item : items) {
			indices[i++] = this.indexOf(item);
		}
		return indices;
	}

	protected void selectedItemsCleared(@SuppressWarnings("unused") CollectionChangeEvent event) {
		if (this.table.isDisposed()) {
			return;
		}
		this.table.deselectAll();
	}

	protected void selectedItemsChanged(@SuppressWarnings("unused") CollectionChangeEvent event) {
		this.synchronizeTableSelection();
	}

	// minimized scope of suppressed warnings
	@SuppressWarnings("unchecked")
	protected Iterable<E> getAddedItems(CollectionAddEvent event) {
		return (Iterable<E>) event.getAddedItems();
	}

	// minimized scope of suppressed warnings
	@SuppressWarnings("unchecked")
	protected Iterable<E> getRemovedItems(CollectionRemoveEvent event) {
		return (Iterable<E>) event.getRemovedItems();
	}


	// ********** list box events **********

	@SuppressWarnings("unchecked")
	protected void tableSelectionChanged(@SuppressWarnings("unused") SelectionEvent event) {
		if (this.selectionChangeListenerList.size() > 0) {
			SelectionChangeEvent<E> scEvent = new SelectionChangeEvent(this, this.selectedItems());
			for (SelectionChangeListener<E> selectionChangeListener : this.selectionChangeListenerList.getListeners()) {
				selectionChangeListener.selectionChanged(scEvent);
			}
		}
	}

	@SuppressWarnings("unchecked")
	protected Collection<E> selectedItems() {
		if (this.table.isDisposed()) {
			return Collections.emptySet();
		}
		ArrayList<E> selectedItems = new ArrayList(this.table.getSelectionCount());
		for (int selectionIndex : this.table.getSelectionIndices()) {
			selectedItems.add(this.listHolder.get(selectionIndex));
		}
		return selectedItems;
	}

	@SuppressWarnings("unchecked")
	protected void tableDoubleClicked(@SuppressWarnings("unused") SelectionEvent event) {
		if (this.table.isDisposed()) {
			return;
		}
		if (this.doubleClickListenerList.size() > 0) {
			// there should be only a single item selected during a double-click(?)
			E selection = this.listHolder.get(this.table.getSelectionIndex());
			DoubleClickEvent<E> dcEvent = new DoubleClickEvent(this, selection);
			for (DoubleClickListener<E> doubleClickListener : this.doubleClickListenerList.getListeners()) {
				doubleClickListener.doubleClick(dcEvent);
			}
		}
	}


	// ********** dispose **********

	protected void tableDisposed(@SuppressWarnings("unused") DisposeEvent event) {
		// the table is not yet "disposed" when we receive this event
		// so we can still remove our listeners
		this.table.removeDisposeListener(this.tableDisposeListener);
		this.table.removeSelectionListener(this.tableSelectionListener);
		this.selectedItemsHolder.removeCollectionChangeListener(CollectionValueModel.VALUES, this.selectedItemsChangeListener);
		this.listHolder.removeListChangeListener(ListValueModel.LIST_VALUES, this.listChangeListener);
	}


	// ********** standard methods **********

	@Override
	public String toString() {
		return StringTools.buildToStringFor(this, this.listHolder);
	}


	// ********** double click support **********

	public void addDoubleClickListener(DoubleClickListener<E> listener) {
		this.doubleClickListenerList.add(listener);
	}

	public void removeDoubleClickListener(DoubleClickListener<E> listener) {
		this.doubleClickListenerList.remove(listener);
	}

	public interface DoubleClickListener<E> extends EventListener {
		void doubleClick(DoubleClickEvent<E> event);
	}

	public static class DoubleClickEvent<E> extends EventObject {
		private final E selection;
		private static final long serialVersionUID = 1L;

		protected DoubleClickEvent(TableModelAdapter<E> source, E selection) {
			super(source);
			if (selection == null) {
				throw new NullPointerException();
			}
			this.selection = selection;
		}

		@Override
		@SuppressWarnings("unchecked")
		public TableModelAdapter<E> getSource() {
			return (TableModelAdapter<E>) super.getSource();
		}

		public E selection() {
			return this.selection;
		}

	}


	// ********** selection support **********

	public void addSelectionChangeListener(SelectionChangeListener<E> listener) {
		this.selectionChangeListenerList.add(listener);
	}

	public void removeSelectionChangeListener(SelectionChangeListener<E> listener) {
		this.selectionChangeListenerList.remove(listener);
	}

	public interface SelectionChangeListener<E> extends EventListener {
		void selectionChanged(SelectionChangeEvent<E> event);
	}

	public static class SelectionChangeEvent<E> extends EventObject {
		private final Collection<E> selection;
		private static final long serialVersionUID = 1L;

		protected SelectionChangeEvent(TableModelAdapter<E> source, Collection<E> selection) {
			super(source);
			if (selection == null) {
				throw new NullPointerException();
			}
			this.selection = selection;
		}

		@Override
		@SuppressWarnings("unchecked")
		public TableModelAdapter<E> getSource() {
			return (TableModelAdapter<E>) super.getSource();
		}

		public Iterator<E> selection() {
			return this.selection.iterator();
		}
	}
}
