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

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

}
