/*******************************************************************************
 * Copyright (c) 2005, 2007 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
 *     Brad Reynolds - bug 116920
 *     Matthew Hall - bug 260329
 *******************************************************************************/
package org.eclipse.jface.tests.databinding.scenarios;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.jface.databinding.swt.SWTObservables;
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.tests.databinding.BindingTestSuite;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Text;

import com.ibm.icu.text.NumberFormat;

/**
 * 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;

    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().bindValue(SWTObservables.observeText(text, SWT.Modify),
                BeansObservables.observeValue(adventure, "name"));

        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().bindValue(SWTObservables.observeText(text, SWT.Modify),
                BeansObservables.observeValue(transportation, "price"));

        NumberFormat numberFormat = NumberFormat.getInstance();
        
        assertEquals(numberFormat.format(transportation.getPrice()), text.getText());
        text.setText("9876.54");
        text.notifyListeners(SWT.FocusOut, null);
        assertEquals(9876.54, transportation.getPrice(), 0);
        
        transportation.setPrice(1234.56);
        assertEquals(numberFormat.format(transportation.getPrice()), 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
//        getDbc().bindValue(SWTObservables.observeText(text, SWT.FocusOut),
//                BeansObservables.observeValue(adventure, "name"),
//                null, 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
//        getDbc().bindValue(SWTObservables.observeText(text, SWT.Modify),
//                BeansObservables.observeValue(adventure, "name"),
//                null, 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

        DataBindingContext dbc = getDbc();
        
        dbc.bindValue(SWTObservables.observeText(text, SWT.Modify),
				BeansObservables.observeValue(adventure, "maxNumberOfPeople"),
				new CustomBeanUpdateValueStrategy(), 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());
        dbc.dispose();
    }

    public void testScenario09() {
        // Verify direct binding between a Text and Label following bugzilla
        // 118696        
        Label label = new Label(getComposite(), SWT.NONE);
        getDbc().bindValue(SWTObservables.observeText(text, SWT.FocusOut), SWTObservables.observeText(label));

        // 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
        Label label = new Label(getComposite(), SWT.NONE);
        getDbc().bindValue(SWTObservables.observeText(text, SWT.Modify), SWTObservables.observeText(label));

        // 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());
    }

}
