/*******************************************************************************
 * Copyright (c) 2005, 2006 IBM Corporation 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
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jface.tests.databinding.scenarios;

import org.eclipse.jface.examples.databinding.model.Account;
import org.eclipse.jface.examples.databinding.model.Adventure;
import org.eclipse.jface.examples.databinding.model.SampleData;
import org.eclipse.jface.examples.databinding.model.Transportation;
import org.eclipse.jface.internal.databinding.provisional.DataBindingContext;
import org.eclipse.jface.internal.databinding.provisional.description.Property;
import org.eclipse.jface.tests.databinding.BindingTestSuite;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

/**
 * 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 TextControlScenario extends ScenariosTestCase {

	private Text text;

	private Adventure adventure;

	private Transportation transportation;

	private Account account;

	protected void setUp() throws Exception {
		super.setUp();
		// do any setup work here
		adventure = SampleData.WINTER_HOLIDAY;
		transportation = SampleData.EXECUTIVE_JET;
		account = SampleData.PRESIDENT;
		text = new Text(getComposite(), SWT.BORDER);
	}

	protected void tearDown() throws Exception {
		text.dispose();
		text = null;
		super.tearDown();
	}

	public void testScenario01() {
		// Bind the adventure "name" property to a text field
		// Change the UI and verify the model changes
		// Change the model and verify the UI changes
		getDbc().bind(text, new Property(adventure, "name"), null);
		assertEquals(adventure.getName(), text.getText());
		text.setText("England");
		text.notifyListeners(SWT.FocusOut, null);
		assertEquals("England", adventure.getName());
		adventure.setName("France");
		assertEquals("France", text.getText());
		adventure.setName("Germany");
		spinEventLoop(0);
		assertEquals("Germany", text.getText());
	}

	public void testScenario02() {

		// Bind the transportation "price" property to a text field
		// This is a Double.TYPE so we check that conversion and validation
		// occurs
		// Change the UI and verify the model changes
		// Change the model and verify the UI changes
		getDbc().bind(text, new Property(transportation, "price"), null);
		assertEquals(Double.toString(transportation.getPrice()), text.getText());
		text.setText("9876.54");
		text.notifyListeners(SWT.FocusOut, null);
		assertEquals(9876.54, transportation.getPrice(), 0);
		transportation.setPrice(1234.56);
		assertEquals("1234.56", text.getText());
	}

	public void testScenario03() {
		// Show that the Escape key can be pressed in the middle of editing and
		// the value will revert
		// the updatePolicy for this test is TIME_LATE so it occurs when focus
		// is lost from the Text control
		getSWTObservableFactory().setUpdateTime(DataBindingContext.TIME_LATE);
		getDbc().bind(text, new Property(adventure, "name"), null);
		String currentText = text.getText();
		text.setText("Switzerland");
		// We do not notify FocusOut
		// Verify that the model hasn't changed
		assertEquals(currentText, adventure.getName());
		Event event = new Event();
		event.character = SWT.ESC;
		event.keyCode = 27;
		text.notifyListeners(SWT.KeyDown, event);
		// Verify that the text has reverted
		assertEquals(currentText, text.getText());
		// And that the model didn't change
		assertEquals(adventure.getName(), currentText);
		// Now change the GUI and commit this change
		currentText = "Austria";
		text.setText(currentText);
		text.notifyListeners(SWT.FocusOut, null);
		assertEquals(text.getText(), adventure.getName());
		// Now change the text again and press escape a second time
		text.setText("Turkey");
		// Send escape
		text.notifyListeners(SWT.KeyDown, event);
		// Verify it has reverted to "Austria" and not any other value, i.e. the
		// last value it displayed
		assertEquals(currentText, text.getText());

	}

	public void testScenario04() {
		// Show that the Escape key can be pressed in the middle of editing and
		// the value will revert
		// the updatePolicy for this test is TIME_EARLY so it occurs when each
		// keystroke occurs
		getSWTObservableFactory().setUpdateTime(DataBindingContext.TIME_EARLY);
		getDbc().bind(text, new Property(adventure, "name"), null);
		String originalName = adventure.getName();
		// Change the text field character by character and ensure that the
		// model changes
		String newName = "Switzerland";
		for (int i = 0; i < newName.length(); i++) {
			text.setText(newName.substring(0, i + 1));
			// Verify the model has changed
			assertEquals(newName.substring(0, i + 1), adventure.getName());
		}
		// Now send an escape key and verify that the model reverts
		Event event = new Event();
		event.character = SWT.ESC;
		event.keyCode = 27;
		text.notifyListeners(SWT.KeyDown, event);
		assertEquals(adventure.getName(), originalName);
		// Now send "Austria" key by key
		newName = "Austria";
		for (int i = 0; i < newName.length(); i++) {
			text.setText(newName.substring(0, i + 1));
			// Verify the model has changed
			assertEquals(newName.substring(0, i + 1), adventure.getName());
		}
		// Send a focus lost event to commit the change
		text.notifyListeners(SWT.FocusOut, null);
		// Send an escape key
		text.notifyListeners(SWT.KeyDown, event);
		// Verify that the model has changed and has not reverted
		assertEquals(newName, adventure.getName());
	}

	/**
	 * public void testScenario05(){ // Show that nesting of properties works.
	 * Adventure has defaultLodging and Lodging has name getDbc().bind(text,new
	 * Property(adventure,"defaultLodging.name"),null); // Verify the GUI is
	 * showing the model value
	 * assertEquals(text.getText(),adventure.getDefaultLodging().getName());
	 *  }
	 */
	public void testScenario06() {
		// // Show that partial validation works for TIME_EARLY
		// // We are using TIME_EARLY to verify that invalid states are not sent
		// to the model
		// getSWTObservableFactory().setUpdateTime(DataBindingContext.TIME_EARLY);
		// getDbc().bind(text, new Property(account, "phone"), new BindSpec(new
		// PhoneConverter(),new PhoneValidator()));
		// // Verify we have no error message for partial validation or full
		// validation yet
		// assertTrue(((String)getDbc().getPartialValidationMessage().getValue()).length()
		// == 0);
		// assertTrue(((String)getDbc().getValidationMessage().getValue()).length()
		// == 0);
		// // Update some of the phone number
		// String originalPhoneNumber = account.getPhone();
		// text.setText("999");
		// // Verify that the phone number is partially invalid and there is no
		// validation message
		// assertTrue(((String)getDbc().getPartialValidationMessage().getValue()).length()
		// > 0);
		// assertTrue(((String)getDbc().getValidationMessage().getValue()).length()
		// == 0);
		// // And that the model has not changed
		// assertEquals(account.getPhone(),originalPhoneNumber);
		// // Verify that fixing the phone removes the error and the model is
		// updated too
		// text.setText("999-888-7777");
		// assertTrue(((String)getDbc().getPartialValidationMessage().getValue()).length()
		// == 0);
		// assertEquals(account.getPhone(),"9998887777");
	}

	public void testScenario07() {
		// // Show that partial validation works for TIME_LATE
		// getSWTObservableFactory().setUpdateTime(DataBindingContext.TIME_LATE);
		// getDbc().bind(text, new Property(account, "phone"), new BindSpec(new
		// PhoneConverter(),new PhoneValidator()));
		// // Update some of the phone number
		// String originalPhoneNumber = account.getPhone();
		// text.setText("222");
		// // Verify that we have no completion validation message and a partial
		// one
		// assertTrue(((String)getDbc().getPartialValidationMessage().getValue()).length()
		// > 0);
		// assertTrue(((String)getDbc().getValidationMessage().getValue()).length()
		// == 0);
		// // Fix the error
		// text.setText("222-333-4444");
		// // Verify that the errors are both fixed
		// assertTrue(((String)getDbc().getPartialValidationMessage().getValue()).length()
		// == 0);
		// assertTrue(((String)getDbc().getValidationMessage().getValue()).length()
		// == 0);
		// // The model should not be changed
		// assertEquals(originalPhoneNumber,account.getPhone());
		// // Lose focus and verify that the complete validation message is
		// fixed
		// text.notifyListeners(SWT.FocusOut,null);
		// assertTrue(((String)getDbc().getValidationMessage().getValue()).length()
		// == 0);
		// // The model should be changed
		// assertEquals("2223334444",account.getPhone());
	}

	public void testScenario08() {

		if(BindingTestSuite.failingTestsDisabled(this)) {
			return;
		}
		
		// Show that the CustomBeanBindSupportFactory will automatically pick up
		// the
		// validator on the MaxNumberOfPeople property

		getSWTObservableFactory().setUpdateTime(DataBindingContext.TIME_EARLY);
		DataBindingContext parentDbc = getDbc();
		DataBindingContext childDbc = new DataBindingContext(parentDbc);
		childDbc.addBindSupportFactory(new CustomBeanBindSupportFactory(
				parentDbc));
		childDbc
				.addObservableFactory(new CustomBeanObservableFactory(parentDbc));
		childDbc.bind(text, new Property(adventure, "maxNumberOfPeople"), null);
		// make sure we can set a value inside the validator's range
		text.setText("4");
		assertEquals(4, adventure.getMaxNumberOfPeople());
		// Now try to set a value outside the validator's range
		text.setText("999");
		assertEquals(4, adventure.getMaxNumberOfPeople());
		childDbc.dispose();
	}

	public void testScenario09() {

		// Verify direct binding between a Text and Label following bugzilla
		// 118696
		getSWTObservableFactory().setUpdateTime(DataBindingContext.TIME_LATE);
		Label label = new Label(getComposite(), SWT.NONE);
		getDbc().bind(text, label, null);
		// Change the text
		text.setText("Frog");
		// Verify the label does not change
		assertTrue(label.getText().length() == 0);
		// Lose focus from the text field
		text.notifyListeners(SWT.FocusOut, null);
		assertEquals(label.getText(), "Frog");

	}

	public void testScenario10() {

		// Verify direct binding between a Text and Label following bugzilla
		// 118696 with TIME_EARLY
		getSWTObservableFactory().setUpdateTime(DataBindingContext.TIME_EARLY);
		Label label = new Label(getComposite(), SWT.NONE);
		getDbc().bind(text, label, null);
		// Change the text
		String newTextValue = "Frog";
		for (int i = 0; i < newTextValue.length(); i++) {
			text.setText(newTextValue.substring(0, i + 1));
			// Verify the label has changed key by key
			assertEquals(text.getText(), label.getText());
		}
		// Lose focus
		text.notifyListeners(SWT.FocusOut, null);
		// Verify the text and label are the same following a lose focus
		assertEquals(text.getText(), label.getText());
	}

}
