/*******************************************************************************
 * Copyright (c) 2005, 2018 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 - bugs 116920, 160000
 *     Matthew Hall - bugs 260329, 260337
 *******************************************************************************/
package org.eclipse.jface.tests.databinding.scenarios;

import static org.junit.Assert.assertEquals;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;

import org.eclipse.core.databinding.beans.BeanProperties;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.observable.Realm;
import org.eclipse.core.databinding.observable.list.IObservableList;
import org.eclipse.core.databinding.observable.list.WritableList;
import org.eclipse.core.databinding.observable.value.IObservableValue;
import org.eclipse.jface.databinding.swt.SWTObservables;
import org.eclipse.jface.databinding.viewers.ViewerSupport;
import org.eclipse.jface.databinding.viewers.ViewersObservables;
import org.eclipse.jface.examples.databinding.model.Account;
import org.eclipse.jface.examples.databinding.model.Adventure;
import org.eclipse.jface.examples.databinding.model.Catalog;
import org.eclipse.jface.examples.databinding.model.Lodging;
import org.eclipse.jface.examples.databinding.model.SampleData;
import org.eclipse.jface.viewers.ComboViewer;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CCombo;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Combo;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class ComboScenarios extends ScenariosTestCase {

	protected ComboViewer cviewer = null;

	protected Combo combo = null;

	protected Catalog catalog = null;

	ILabelProvider lodgingLabelProvider = new LabelProvider() {
		@Override
		public String getText(Object element) {
			return ((Lodging) element).getName();
		}
	};

	ILabelProvider accountLabelProvider = new LabelProvider() {
		@Override
		public String getText(Object element) {
			return ((Account) element).getCountry();
		}
	};

	@Override
	@Before
	public void setUp() throws Exception {
		super.setUp();
		getComposite().setLayout(new FillLayout());

		combo = new Combo(getComposite(), SWT.READ_ONLY | SWT.DROP_DOWN);
		cviewer = new ComboViewer(combo);

		catalog = SampleData.CATALOG_2005; // Lodging source
	}

	@Override
	@After
	public void tearDown() throws Exception {
		combo.dispose();
		combo = null;
		cviewer = null;
		super.tearDown();
	}

	protected Object getViewerSelection() {
		return cviewer.getStructuredSelection().getFirstElement();
	}

	/**
	 * @return the ComboViewer's domain object list
	 */
	protected List getViewerContent(ComboViewer cviewer) {
		Object[] elements = ((IStructuredContentProvider) cviewer
				.getContentProvider()).getElements(null);
		if (elements != null)
			return Arrays.asList(elements);
		return null;
	}

	/**
	 *
	 * @return the combo's items (String[]), which is the same thing as the
	 *         Viewer's labels
	 *
	 */
	protected List getComboContent() {
		String[] elements = combo.getItems();
		if (elements != null)
			return Arrays.asList(elements);
		return null;
	}

	protected List getColumn(Object[] list, String feature) {
		List result = new ArrayList();
		if (list == null || list.length == 0)
			return result;
		String getterName = "get"
				+ feature.substring(0, 1).toUpperCase(Locale.ENGLISH)
				+ feature.substring(1);
		try {
			Method getter = list[0].getClass().getMethod(getterName);
			try {
				for (int i = 0; i < list.length; i++) {
					result.add(getter.invoke(list[i]));
				}
			} catch (IllegalArgumentException e) {
			} catch (IllegalAccessException e) {
			} catch (InvocationTargetException e) {
			}
		} catch (SecurityException e) {
		} catch (NoSuchMethodException e) {
		}
		return result;
	}

	/**
	 * This test case deal with the 3rd scenario, using vanilla bindings: Ensure
	 * a valid content and selection are bounded correctly Bind a collection of
	 * Lodgings to a ComboViewer Bind the ComboViewer's selection to the
	 * defaultLodging of an Adventure
	 *
	 * This test does not deal with null values, empty content, changed content,
	 * property change of content elements, etc.
	 *
	 */
	@Test
	public void test_ROCombo_Scenario03_vanilla() {
		IObservableList lodgings = BeansObservables.observeList(Realm
				.getDefault(), catalog, "lodgings");
		ViewerSupport.bind(cviewer, lodgings, BeanProperties.value(
				Lodging.class, "name"));

		Adventure skiAdventure = SampleData.WINTER_HOLIDAY; // selection will

		// Ensure that cv's content now has the catalog's lodgings
		assertArrayEquals(catalog.getLodgings(), getViewerContent(cviewer)
				.toArray());

		// Ensure that the cv's labels are the same as the lodging descriptions
		assertEquals(getColumn(catalog.getLodgings(), "name"),
				getComboContent());

		getDbc().bindValue(ViewersObservables.observeSingleSelection(cviewer),
				BeansObservables.observeValue(skiAdventure, "defaultLodging"));

		// Check to see that the initial selection is the currentDefault Lodging
		assertEquals(getViewerSelection(), skiAdventure.getDefaultLodging());

		// Change the selection of the ComboViewer to all possible lodgings, and
		// verify that skiAdventure's default lodging was changed accordingly
		for (int i = 0; i < catalog.getLodgings().length; i++) {
			Object selection = catalog.getLodgings()[i];
			cviewer.setSelection(new StructuredSelection(selection));
			assertEquals(selection, skiAdventure.getDefaultLodging());
			assertEquals(getViewerSelection(), skiAdventure.getDefaultLodging());
		}

	}

	/**
	 * This test case deal with the 3rd scenario, and focuses on the collection
	 * binding to the combo. It will bind a collection, add/remove/change
	 * elements in the collection, and change element's properties to ensure
	 * that the combo's labels were updated appropriatly.
	 *
	 * it also induce null values in properties, and elments.
	 *
	 * This test does not deal with the combo's selection.
	 */
	@Test
	public void test_ROCombo_Scenario03_collectionBindings() {
		// column binding
		// Bind the ComboViewer's content to the available lodging
		IObservableList lodgings = BeansObservables.observeList(Realm
				.getDefault(), catalog, "lodgings");
		ViewerSupport.bind(cviewer, lodgings, BeanProperties.value(
				Lodging.class, "name"));

		// Ensure that cv's content now has the catalog's lodgings
		assertArrayEquals(catalog.getLodgings(), getViewerContent(cviewer)
				.toArray());

		// Ensure that the cv's labels are the same as the lodging descriptions
		assertEquals(getColumn(catalog.getLodgings(), "name"),
				getComboContent());

		// Add a lodging in the middle (not supported by the model right now)
		// Lodging lodging = SampleData.FACTORY.createLodging();
		// lodging.setName("Middle Lodging");
		// catalog.addLodging(lodging);
		// assertEquals(getViewerContent(cviewer).get(2), lodging);

		// Add a lodging at the end
		Lodging lodging = SampleData.FACTORY.createLodging();
		lodging.setName("End Lodging");
		catalog.addLodging(lodging);
		int index = getComboContent().size() - 1;
		assertEquals(getViewerContent(cviewer).get(index), lodging);

		// Delete the first Lodging
		catalog.removeLodging(catalog.getLodgings()[0]);
		// Ensure that the cv's labels are the same as the lodging descriptions
		assertEquals(getColumn(catalog.getLodgings(), "name"),
				getComboContent());

		// Delete middle Lodging
		catalog.removeLodging(catalog.getLodgings()[2]);
		// Ensure that the cv's labels are the same as the lodging descriptions
		assertEquals(getColumn(catalog.getLodgings(), "name"),
				getComboContent());

		// Change the names of all Lodging
		for (int i = 0; i < catalog.getLodgings().length; i++) {
			Lodging l = catalog.getLodgings()[i];
			l.setName("Changed: " + l.getName());
		}
		spinEventLoop(0); // force Async. efforts
		assertEquals(getColumn(catalog.getLodgings(), "name"),
				getComboContent());

		// Set to null value
		Lodging l = catalog.getLodgings()[0];
		assertEquals(combo.getItem(0), l.getName());
		l.setName(null);
		assertEquals("", combo.getItem(0));

		// set to empty list
		while (catalog.getLodgings().length > 0) {
			catalog.removeLodging(catalog.getLodgings()[0]);
			assertEquals(getColumn(catalog.getLodgings(), "name"),
					getComboContent());
		}
	}

	/**
	 * This scenario tests a simple SWT combo with a set item list where the
	 * selection is bouded to a String property
	 */
	// @Test
	// public void test_ROCombo_Scenario01() {
	//
	// // Read-Only Combo will not change its text property on a call to
	// // setText()
	//
	// String[] items = new String[] { "FairyLand", "TuneLand", "NoWereLand",
	// "TinkerLand", "DreamLand" };
	// combo.setItems(items);
	// Account account = catalog.getAccounts()[0];
	//
	// // simple Combo's selection bound to the Account's country property
	// getDbc().bind(new Property(combo, SWTProperties.SELECTION),
	// new Property(account, "country"), null);
	//
	// // Drive the combo selection
	// int index = 3;
	// combo.setText(items[index]); // this should drive the selection
	// assertEquals(account.getCountry(), items[index]);
	//
	// // Set the country, and ensure selection is set property
	// index = 1;
	// account.setCountry(items[index]);
	// assertEquals(index, combo.getSelectionIndex());
	// assertEquals(combo.getText(), items[index]);
	//
	// index = combo.getSelectionIndex();
	// String txt = combo.getText();
	// // Set the country to something that is not in the Combo's list
	// account.setCountry("FooBar");
	// // Combo's selection will not Change
	// assertEquals(combo.getSelectionIndex(), index);
	// assertEquals(combo.getText(), txt);
	//
	// }
	/**
	 * This scenario tests a simple SWT combo that is bound to a list of Country
	 * objects. The Country object's name property is listed in the Combo.
	 *
	 * The Combo's selection is bounded to the Country property of an Account.
	 */
	// @Test
	// public void test_ROCombo_Scenario02_SWTCombo() {
	//
	// // Create a list of Strings for the countries
	// IObservableList list = new WritableList();
	// for (int i = 0; i < catalog.getAccounts().length; i++)
	// list.add(catalog.getAccounts()[i].getCountry());
	//
	// // Bind the combo's content to that of the String based list
	// getDbc().bind(combo, list, null);
	// assertEquals(Arrays.asList(combo.getItems()), list);
	//
	// Account account = catalog.getAccounts()[0];
	//
	// // simple Combo's selection bound to the Account's country property
	// getDbc().bind(new Property(combo, SWTProperties.SELECTION),
	// new Property(account, "country"), null);
	//
	// // Drive the combo selection
	// String selection = (String) list.get(2);
	// combo.setText(selection); // this should drive the selection
	// assertEquals(account.getCountry(), selection);
	//
	// }
	/**
	 * This scenario tests a simple SWT combo that is bound to a list of Country
	 * objects. The Country object's name property is listed in the Combo.
	 *
	 * The Combo's selection is bounded to the Country property of an Account.
	 */
	// @Test
	// public void test_ROCombo_Scenario02_ComboViewer() {
	//
	// // Account label provider will fill the combo with the country
	// cviewer.setLabelProvider(accountLabelProvider);
	// // Bind the ComboViewer's content to the available accounts
	// getDbc().bind(
	// cviewer,
	// new ListModelDescription(new Property(catalog, "accounts"),
	// "country"), null);
	//
	// // Ensure that cv's content now has the catalog's accounts
	// assertArrayEquals(catalog.getAccounts(), getViewerContent(cviewer)
	// .toArray());
	// // Ensure that the cv's labels are the same as the account countries
	// assertEquals(getColumn(catalog.getAccounts(), "country"),
	// getComboContent());
	//
	// Account account = SampleData.FACTORY.createAccount();
	//
	// // Use the Viewers visual Combo (Strings) to set the account's country
	// getDbc().bind(new Property(combo, SWTProperties.SELECTION),
	// new Property(account, "country"), null);
	//
	// // Change the selection of the ComboViewer to all possible accounts, and
	// // verify that the account's Country is being changed correctly.
	// for (int i = 0; i < catalog.getAccounts().length; i++) {
	// Account selection = catalog.getAccounts()[i];
	// cviewer.setSelection(new StructuredSelection(selection));
	// assertEquals(selection.getCountry(), account.getCountry());
	// }
	//
	// }
	/**
	 * This test ensure that multiple combos can be bound to the same deomain
	 * model
	 */
	@Test
	public void test_ROCombo_multipleBindings() {
		Adventure skiAdventure = SampleData.WINTER_HOLIDAY; // for selection

		// Bind the ComboViewer's content to the available lodging
		IObservableList lodgings = BeansObservables.observeList(Realm
				.getDefault(), catalog, "lodgings");
		ViewerSupport.bind(cviewer, lodgings, BeanProperties.value(
				Lodging.class, "name"));

		// Ensure that cv's content now has the catalog's lodgings
		assertArrayEquals(catalog.getLodgings(), getViewerContent(cviewer)
				.toArray());

		// Ensure that the cv's labels are the same as the lodging descriptions
		assertEquals(getColumn(catalog.getLodgings(), "name"),
				getComboContent());

		ComboViewer otherViewer = new ComboViewer(getComposite(), SWT.NONE);
		ViewerSupport.bind(otherViewer, lodgings, BeanProperties.value(
				Lodging.class, "name"));

		// Ensure that cv's content now has the catalog's lodgings
		assertArrayEquals(catalog.getLodgings(), getViewerContent(otherViewer)
				.toArray());

		// Bind both selections to the same thing
		IObservableValue selection = ViewersObservables
				.observeSingleSelection(cviewer);
		getDbc().bindValue(selection,
				BeansObservables.observeValue(skiAdventure, "defaultLodging"));

		IObservableValue otherSelection = ViewersObservables
				.observeSingleSelection(otherViewer);
		getDbc().bindValue(otherSelection,
				BeansObservables.observeValue(skiAdventure, "defaultLodging"));

		Lodging lodging = catalog.getLodgings()[0];

		// Ensure that setting the selection is driven forward to the other
		// combo
		cviewer.setSelection(new StructuredSelection(lodging));
		assertEquals(cviewer.getStructuredSelection().getFirstElement(),
				otherViewer.getStructuredSelection().getFirstElement());

		// Change the list of one combo, and ensure it updates the other combo
		catalog.removeLodging(lodging);
		assertEquals(getViewerContent(cviewer), getViewerContent(otherViewer));

	}

	/**
	 * This scenario tests a simple SWT CCombo that is bound to a list of
	 * Country objects. The Country object's name property is listed in the
	 * Combo.
	 *
	 * The Combo's selection is bounded to the Country property of an Account.
	 */
	@Test
	public void test_ROCombo_SWTCCombo() {

		// Create a list of Strings for the countries
		IObservableList list = new WritableList();
		for (int i = 0; i < catalog.getAccounts().length; i++)
			list.add(catalog.getAccounts()[i].getCountry());

		CCombo ccombo = new CCombo(getComposite(), SWT.READ_ONLY
				| SWT.DROP_DOWN);

		// Bind the combo's content to that of the String based list
		getDbc().bindList(SWTObservables.observeItems(ccombo), list);
		assertEquals(Arrays.asList(ccombo.getItems()), list);

		Account account = catalog.getAccounts()[0];

		// simple Combo's selection bound to the Account's country property
		IObservableValue comboSelection = SWTObservables
				.observeSelection(ccombo);
		getDbc().bindValue(comboSelection,
				BeansObservables.observeValue(account, "country"));

		// Drive the combo selection
		String selection = (String) list.get(2);
		ccombo.setText(selection); // this should drive the selection
		assertEquals(account.getCountry(), selection);

	}

	/**
	 * This scenario tests a simple SWT CCombo that is bound to a list of
	 * Country objects. The Country object's name property is listed in the
	 * Combo.
	 *
	 * The Combo's selection is bounded to the Country property of an Account.
	 */
	@Test
	public void test_WCombo_SWTCCombo() {

		// Create a list of Strings for the countries
		IObservableList list = new WritableList();
		for (int i = 0; i < catalog.getAccounts().length; i++)
			list.add(catalog.getAccounts()[i].getCountry());

		CCombo ccombo = new CCombo(getComposite(), SWT.READ_ONLY
				| SWT.DROP_DOWN);

		// Bind the combo's content to that of the String based list
		getDbc().bindList(SWTObservables.observeItems(ccombo), list);
		assertEquals(Arrays.asList(ccombo.getItems()), list);

		Account account = catalog.getAccounts()[0];

		// simple Combo's selection bound to the Account's country property
		IObservableValue comboSelection = SWTObservables
				.observeSelection(ccombo);
		getDbc().bindValue(comboSelection,
				BeansObservables.observeValue(account, "country"));

		// Drive the combo selection
		String selection = (String) list.get(2);
		ccombo.setText(selection); // this should drive the selection
		assertEquals(account.getCountry(), selection);

		selection = (String) list.get(1);
		account.setCountry(selection);
		assertEquals(selection, ccombo.getItem(ccombo.getSelectionIndex()));
		assertEquals(selection, ccombo.getText());

		selection = "country not in list";
		account.setCountry(selection);
		assertEquals(-1, ccombo.getSelectionIndex());
		assertEquals(selection, ccombo.getText());
	}

	/**
	 * This scenario tests a simple SWT CCombo that is bound to a list of
	 * Country objects. The Country object's name property is listed in the
	 * Combo.
	 *
	 * The Combo's selection is bounded to the Country property of an Account.
	 */
	@Test
	public void test_ROCombo_SWTList() {

		// Create a list of Strings for the countries
		IObservableList list = new WritableList();
		for (int i = 0; i < catalog.getAccounts().length; i++)
			list.add(catalog.getAccounts()[i].getCountry());

		org.eclipse.swt.widgets.List swtlist = new org.eclipse.swt.widgets.List(
				getComposite(), SWT.READ_ONLY | SWT.SINGLE);

		// Bind the combo's content to that of the String based list
		getDbc().bindList(SWTObservables.observeItems(swtlist), list);
		assertEquals(Arrays.asList(swtlist.getItems()), list);

		Account account = catalog.getAccounts()[0];

		// simple Combo's selection bound to the Account's country property
		IObservableValue listSelection = SWTObservables
				.observeSelection(swtlist);
		getDbc().bindValue(listSelection,
				BeansObservables.observeValue(account, "country"));

		String selection = (String) list.get(2);
		swtlist.select(2); // this should drive the selection
		swtlist.notifyListeners(SWT.Selection, null); // Force notification
		assertEquals(account.getCountry(), selection);

	}

}
