/*******************************************************************************
 * Copyright (c) 2005, 2009 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Brad Reynolds - bug 116920
 *     Brad Reynolds - bug 160000
 *     Matthew Hall - bug 260337
 *******************************************************************************/
package org.eclipse.jface.tests.databinding.scenarios;

import static org.junit.Assert.assertEquals;

import java.util.ArrayList;
import java.util.Arrays;

import org.eclipse.core.databinding.beans.typed.BeanProperties;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.jface.databinding.viewers.ViewerSupport;
import org.eclipse.jface.examples.databinding.model.Account;
import org.eclipse.jface.examples.databinding.model.Catalog;
import org.eclipse.jface.examples.databinding.model.Category;
import org.eclipse.jface.examples.databinding.model.SampleData;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.swt.widgets.TableItem;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * To run the tests in this class, right-click and select "Run As JUnit Plug-in
 * Test". This will also start an Eclipse instance. To clean up the launch
 * configuration, open up its "Main" tab and select "[No Application] - Headless
 * Mode" as the application to run.
 */

public class TableScenarios extends ScenariosTestCase {

	private TableViewer tableViewer;

	private Catalog catalog;

	Category category;

	private TableColumn firstNameColumn;

	private TableColumn lastNameColumn;

	private TableColumn stateColumn;

	Image[] images;

	private TableColumn fancyColumn;

	@Before
	@Override
	public void setUp() throws Exception {
		super.setUp();
		getComposite().setLayout(new FillLayout());
		tableViewer = new TableViewer(getComposite());
		tableViewer.getTable().setLinesVisible(true);
		tableViewer.getTable().setHeaderVisible(true);
		firstNameColumn = new TableColumn(tableViewer.getTable(), SWT.NONE);
		firstNameColumn.setWidth(50);
		lastNameColumn = new TableColumn(tableViewer.getTable(), SWT.NONE);
		lastNameColumn.setWidth(50);
		stateColumn = new TableColumn(tableViewer.getTable(), SWT.NONE);
		stateColumn.setWidth(50);
		fancyColumn = new TableColumn(tableViewer.getTable(), SWT.NONE);
		fancyColumn.setWidth(250);

		catalog = SampleData.CATALOG_2005; // Lodging source
		category = SampleData.WINTER_CATEGORY;

		images = new Image[] {
				getShell().getDisplay().getSystemImage(SWT.ICON_ERROR),
				getShell().getDisplay().getSystemImage(SWT.ICON_WARNING),
				getShell().getDisplay().getSystemImage(SWT.ICON_INFORMATION), };
	}

	@After
	@Override
	public void tearDown() throws Exception {
		// do any teardown work here
		super.tearDown();
		tableViewer.getTable().dispose();
		tableViewer = null;
		firstNameColumn = null;
		lastNameColumn = null;
		stateColumn = null;
	}

	@Test
	public void testScenario01() {
		// Show that a TableViewer with three columns renders the accounts
		Account[] accounts = catalog.getAccounts();

		IObservableList list = new WritableList(new ArrayList(), Account.class);
		list.addAll(Arrays.asList(accounts));

		ViewerSupport.bind(tableViewer, list, BeanProperties.values(
				Account.class,
				new String[] { "firstName", "lastName", "state" }));

		Table table = tableViewer.getTable();

		// Verify the data in the table columns matches the accounts
		for (int i = 0; i < accounts.length; i++) {
			Account account = catalog.getAccounts()[i];
			TableItem item = table.getItem(i);

			assertEquals(account.getFirstName(), item.getText(0));
			assertEquals(account.getLastName(), item.getText(1));
			assertEquals(account.getState(), item.getText(2));
		}
	}

	@Test
	public void testScenario02() throws SecurityException,
			IllegalArgumentException {
		// Show that a TableViewer with three columns can be used to update
		// columns
		// Account[] accounts = catalog.getAccounts();
		//
		// TableModelDescription tableModelDescription = new
		// TableModelDescription(new Property(catalog, "accounts"), new
		// String[]{"firstName","lastName","state"});
		// // tableViewerDescription.addEditableColumn("firstName");
		// // tableViewerDescription.addEditableColumn("lastName", null, null,
		// new PhoneConverter());
		// // tableViewerDescription.addEditableColumn("state", null, null, new
		// StateConverter());
		// getDbc().bind(tableViewer,
		// tableModelDescription, null);
		//
		// Account account = accounts[0];
		// // Select the first item in the table
		// tableViewer.editElement(account, 0);
		// // Set the text property of the cell editor which is now active over
		// the "firstName" column
		// CellEditor[] cellEditors = tableViewer.getCellEditors();
		// TextCellEditor firstNameEditor = (TextCellEditor) cellEditors[0];
		// // Change the firstName and test it goes to the model
		// enterText((Text) firstNameEditor.getControl(), "Bill");
		// // Check whether the model has changed
		// assertEquals("Bill",account.getFirstName());
	}

	@Test
	public void testScenario04() {
		// // Show that when an item is added to a collection the table gets an
		// extra item
		// Account[] accounts = catalog.getAccounts();
		//
		// TableViewerDescription tableViewerDescription = new
		// TableViewerDescription(
		// tableViewer);
		// tableViewerDescription.addColumn("firstName");
		// tableViewerDescription.addColumn("lastName");
		// tableViewerDescription.addColumn("state");
		// tableViewerDescription.addColumn(null,new IConverter(){
		//
		// public Class getModelType() {
		// return Account.class;
		// }
		//
		// public Class getTargetType() {
		// return ViewerLabel.class;
		// }
		//
		// public Object convertTargetToModel(Object targetObject) {
		// return null;
		// }
		//
		// public Object convertModelToTarget(Object modelObject) {
		// Account account = (Account) modelObject;
		// return new ViewerLabel(account.toString(), images[new
		// Random().nextInt(images.length)]);
		// }});
		// getDbc().bind(tableViewerDescription,
		// new Property(catalog, "accounts"), null);
		//
		// //interact();
		//
		// // Verify the number of accounts matches the number of items in the
		// table
		// assertEquals(tableViewer.getTable().getItemCount(),accounts.length);
		// // Add a new account and verify that the number of items in the table
		// increases
		// Account newAccount = new Account();
		// newAccount.setFirstName("Finbar");
		// newAccount.setLastName("McGoo");
		// newAccount.setLastName("NC");
		// catalog.addAccount(newAccount);
		// // The number of items should have gone up by one
		// assertEquals(tableViewer.getTable().getItemCount(),accounts.length +
		// 1);
		// // The number of items should still match the number of accounts
		// (i.e. test the model)
		// assertEquals(tableViewer.getTable().getItemCount(),catalog.getAccounts().length);
		// // Remove the account that was just added
		// catalog.removeAccount(newAccount);
		// // The number of items should match the original
		// assertEquals(tableViewer.getTable().getItemCount(),accounts.length);
		// // The number of items should still match the number of accounts
		// (i.e. test the model is reset)
		// assertEquals(tableViewer.getTable().getItemCount(),catalog.getAccounts().length);
		//
		// // Test adding and removing to the model on a non UI thread
		// int numberOfAccounts = catalog.getAccounts().length;
		// final Account barney = new Account();
		// barney.setFirstName("Barney");
		// barney.setLastName("Smith");
		// barney.setLastName("CA");
		// invokeNonUI(new Runnable(){
		// public void run(){
		// catalog.addAccount(barney);
		// }
		// });
		// spinEventLoop(0);
		// // The number of items should have gone up by one
		// assertEquals(tableViewer.getTable().getItemCount(),numberOfAccounts +
		// 1);
		//
		// invokeNonUI(new Runnable(){
		// public void run(){
		// catalog.removeAccount(barney);
		// }
		// });
		// spinEventLoop(0);
		// // The number of items should have reverted to the original number
		// before barney was added and removed
		// assertEquals(tableViewer.getTable().getItemCount(),numberOfAccounts);
		//
	}

	@Test
	public void testScenario03() {
		// // Show that converters work for table columns
		// Account[] accounts = catalog.getAccounts();
		//
		// TableViewerDescription tableViewerDescription = new
		// TableViewerDescription(
		// tableViewer);
		// tableViewerDescription.addEditableColumn("lastName");
		// tableViewerDescription.addEditableColumn("phone", null, null ,
		// new PhoneConverter());
		// tableViewerDescription.addEditableColumn("state", null, null ,
		// new StateConverter());
		// getDbc().bind(tableViewerDescription,
		// new Property(catalog, "accounts"), null);
		//
		// // Verify that the data in the the table columns matches the expected
		// // What we are looking for is that the phone numbers are converterted
		// to
		// // nnn-nnn-nnnn and that
		// // the state letters are converted to state names
		// // Verify the data in the table columns matches the accounts
		// PhoneConverter phoneConverter = new PhoneConverter();
		// StateConverter stateConverter = new StateConverter();
		// for (int i = 0; i < accounts.length; i++) {
		// Account account = catalog.getAccounts()[i];
		// // Check the phone number
		// String col_phone = ((ITableLabelProvider) tableViewer
		// .getLabelProvider()).getColumnText(account, 1);
		// assertEquals(getValue((String)phoneConverter
		// .convertModelToTarget(account.getPhone())), col_phone);
		// String col_state = ((ITableLabelProvider) tableViewer
		// .getLabelProvider()).getColumnText(account, 2);
		// assertEquals(getValue((String)stateConverter
		// .convertModelToTarget(account.getState())), col_state);
		// }
	}

	@Test
	public void testScenario05() {
		// // Show that when the model changes then the UI refreshes to reflect
		// this
		//
		// TableViewerDescription tableViewerDescription = new
		// TableViewerDescription(
		// tableViewer);
		// tableViewerDescription.addColumn("lastName");
		// tableViewerDescription.addColumn("phone",
		// new PhoneConverter());
		// tableViewerDescription.addColumn("state",
		// new StateConverter());
		// getDbc().bind(tableViewerDescription,
		// new Property(catalog, "accounts"), null);
		//
		// final Account account = catalog.getAccounts()[0];
		// String lastName = tableViewer.getTable().getItem(0).getText(0);
		// // Check the firstName in the TableItem is the same as the model
		// assertEquals(lastName,account.getLastName());
		// // Now change the model and check again
		// account.setLastName("Gershwin");
		// lastName = tableViewer.getTable().getItem(0).getText(0);
		// assertEquals(lastName,account.getLastName());
		//
		// // Test the model update on a non UI thread
		// invokeNonUI(new Runnable(){
		// public void run(){
		// account.setLastName("Mozart");
		// }
		// });
		// spinEventLoop(0);
		// lastName = tableViewer.getTable().getItem(0).getText(0);
		// assertEquals(lastName,account.getLastName());
		//
	}

	@Test
	public void testScenario06() {
		// // Check that explicit type means that defaulting of converters works
		// TableViewerDescription tableViewerDescription = new
		// TableViewerDescription(
		// tableViewer);
		// tableViewerDescription.addEditableColumn("price");
		// tableViewerDescription.getColumn(0).setPropertyType(Double.TYPE);
		// getDbc().bind(tableViewerDescription,
		// new Property(catalog, "transporations"), null);
		// Transportation transporation = catalog.getTransporations()[0];
		// tableViewer.editElement(transporation, 0);
		// // Set the text property of the cell editor which is now active over
		// the "firstName" column
		// CellEditor[] cellEditors = tableViewer.getCellEditors();
		// TextCellEditor priceEditor = (TextCellEditor) cellEditors[0];
		// // Change the firstName and test it goes to the model
		// enterText((Text) priceEditor.getControl(), "123.45");
		// // Verify the model is updated
		// assertEquals(transporation.getPrice(),123.45,0);

	}

	@Test
	public void testScenario07() {
		// // Verify that even when a column's property type is not set, that it
		// is worked out lazily from the target type
		// TableViewerDescription tableViewerDescription = new
		// TableViewerDescription(
		// tableViewer);
		// tableViewerDescription.addEditableColumn("price");
		// // The column's type is not set to be Double.TYPE. This will be
		// inferred once the first Transportation object is set
		// // into the ObservableCollection
		// getDbc().bind(tableViewerDescription,
		// new Property(catalog, "transporations"), null);
		// Transportation transporation = catalog.getTransporations()[0];
		// tableViewer.editElement(transporation, 0);
		// // Set the text property of the cell editor which is now active over
		// the "firstName" column
		// CellEditor[] cellEditors = tableViewer.getCellEditors();
		// TextCellEditor priceEditor = (TextCellEditor) cellEditors[0];
		// // Change the firstName and test it goes to the model
		// enterText((Text) priceEditor.getControl(), "123.45");
		// // Verify the model is updated
		// assertEquals(transporation.getPrice(),123.45,0);
		//
	}

	@Test
	public void testScenario08_00() {
		// // Verify that binding to a Collection property (rather than an
		// array) works when specifying data type
		// TableViewerDescription tableViewerDescription = new
		// TableViewerDescription(
		// tableViewer);
		// tableViewerDescription.addEditableColumn("userId");
		// tableViewerDescription.addEditableColumn("password");
		// getDbc().bind(tableViewerDescription,
		// new Property(catalog, "signons", Signon.class, null), null);
		// Signon firstSignon = (Signon) catalog.getSignons().get(0);
		// // Verify the UI matches the model
		// TableItem firstTableItem = tableViewer.getTable().getItem(0);
		// assertEquals(firstTableItem.getText(1),firstSignon.getPassword());
		// // Change the model and ensure the UI refreshes
		// firstSignon.setPassword("Eclipse123Rocks");
		// assertEquals("Eclipse123Rocks",firstSignon.getPassword());
		// assertEquals(firstTableItem.getText(1),firstSignon.getPassword());
		// // Change the GUI and ensure the model refreshes
		// tableViewer.editElement(firstSignon, 1);
		// CellEditor[] cellEditors = tableViewer.getCellEditors();
		// TextCellEditor passwordEditor = (TextCellEditor) cellEditors[1];
		// enterText((Text) passwordEditor.getControl(), "Cricket11Players");
		// assertEquals("Cricket11Players",firstSignon.getPassword());
		//
	}

	@Test
	public void testScenario08_01() {
		// // Verify that binding to a Collection property (rather than an
		// array) works without specifying data type
		// TableViewerDescription tableViewerDescription = new
		// TableViewerDescription(
		// tableViewer);
		// tableViewerDescription.addEditableColumn("userId");
		// tableViewerDescription.addEditableColumn("password");
		// getDbc().bind(tableViewerDescription,
		// new Property(catalog, "signons"), null);
		// Signon firstSignon = (Signon) catalog.getSignons().get(0);
		// // Verify the UI matches the model
		// TableItem firstTableItem = tableViewer.getTable().getItem(0);
		// assertEquals(firstTableItem.getText(1),firstSignon.getPassword());
		// // Change the model and ensure the UI refreshes
		// firstSignon.setPassword("Eclipse123Rocks");
		// assertEquals("Eclipse123Rocks",firstSignon.getPassword());
		// assertEquals(firstTableItem.getText(1),firstSignon.getPassword());
		// // Change the GUI and ensure the model refreshes
		// tableViewer.editElement(firstSignon, 1);
		// CellEditor[] cellEditors = tableViewer.getCellEditors();
		// TextCellEditor passwordEditor = (TextCellEditor) cellEditors[1];
		// enterText((Text) passwordEditor.getControl(), "Cricket11Players");
		// assertEquals("Cricket11Players",firstSignon.getPassword());
		//
	}

	@Test
	public void testScenario09() {
		// // Verify that nested properties work. Catalog has adventures.
		// Adventure has defaultLodging. Loding has name.
		// TableViewerDescription tableViewerDescription = new
		// TableViewerDescription(tableViewer);
		// tableViewerDescription.addColumn("name");
		// tableViewerDescription.addColumn("defaultLodging.name");
		// getDbc().bind(tableViewerDescription,new Property(category,
		// "adventures"),null);
		//
	}
	/**
	 * @Test
	public void testScenario10(){ // Verify that for TIME_EARLY updating
	 * occurs on a per key basic for a TextCellEditor // Show that converters
	 * work for table columns Account[] accounts = catalog.getAccounts();
	 * Account firstAccount = accounts[0];
	 * SampleData.getSWTObservableFactory().setUpdateTime
	 * (DataBindingContext.TIME_EARLY); TableViewerDescription
	 * tableViewerDescription = new TableViewerDescription(tableViewer);
	 * tableViewerDescription.addEditableColumn("lastName");
	 * tableViewerDescription.addColumn("lastName");
	 * getDbc().bind(tableViewerDescription,new Property(catalog, "accounts"),
	 * null); // Verify that the first account is shown in the first row with
	 * the last name correctly
	 * assertEquals(tableViewer.getTable().getItem(0).getData(),firstAccount);
	 * assertEquals
	 * (tableViewer.getTable().getItem(0).getText(0),firstAccount.getLastName
	 * ());
	 * assertEquals(tableViewer.getTable().getItem(0).getText(1),firstAccount
	 * .getLastName()); // Create a cell editor over the first column
	 * tableViewer.editElement(firstAccount, 0); // Set the text property of the
	 * cell editor which is now active over the "firstName" column CellEditor[]
	 * cellEditors = tableViewer.getCellEditors(); TextCellEditor
	 * lastNameCellEditor = (TextCellEditor) cellEditors[0];
	 * ((Text)lastNameCellEditor.getControl()).setText("E"); // Verify that the
	 * key press goes to the model assertEquals(firstAccount.getLastName(),"E");
	 * }
	 */
}
