package org.bostonandroid.datepreferencetest;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.GregorianCalendar;

import android.preference.DatePreference;
import android.preference.PreferenceManager;
import android.test.ActivityInstrumentationTestCase2;
import android.view.KeyEvent;

public class DatePreferenceActivityTest extends
    ActivityInstrumentationTestCase2<DatePreferenceActivity> {
  
  public DatePreferenceActivityTest() {
    super("org.bostonandroid.datepreferencetest", DatePreferenceActivity.class);
  }

  @Override
  protected void setUp() throws Exception {
    super.setUp();
    setActivityInitialTouchMode(false);
  }
  
  public void testDefaultDateUnset() {
    DatePreferenceActivity activity = getActivity();
    PreferenceManager preferenceManager = activity.getPreferenceManager();
    DatePreference datePreference = (DatePreference)preferenceManager.findPreference("dod");
    Calendar givenDate = datePreference.getDate();
    assertCalendarDateEquals(defaultDate(), givenDate);
  }
  
  public void testDefaultDateFromXml() {
    DatePreferenceActivity activity = getActivity();
    PreferenceManager preferenceManager = activity.getPreferenceManager();
    DatePreference datePreference = (DatePreference)preferenceManager.findPreference("dob");
    Calendar defaultDate = datePreference.getDate();
    Calendar expected = new GregorianCalendar(1991,0,1);
    assertCalendarDateEquals(expected, defaultDate);
  }
  
  public void testDefaultDateForBadDate() {
    DatePreferenceActivity activity = getActivity();
    PreferenceManager preferenceManager = activity.getPreferenceManager();
    DatePreference datePreference = (DatePreference)preferenceManager.findPreference("doa");
    Calendar defaultDate = datePreference.getDate();
    assertCalendarDateEquals(defaultDate(), defaultDate);
  }
  
  public void testDateChanged() {
    DatePreferenceActivity activity = getActivity();
    assertNotNull(activity);
    
    activateDodPreference();
    
    // increment the day
    sendKeys(KeyEvent.KEYCODE_DPAD_DOWN,
        KeyEvent.KEYCODE_DPAD_UP,
        KeyEvent.KEYCODE_DPAD_RIGHT,
        KeyEvent.KEYCODE_DPAD_UP,
        KeyEvent.KEYCODE_DPAD_UP,
        KeyEvent.KEYCODE_DPAD_CENTER);

    pressOK();
    
    Calendar newDate = getDatePreference(activity).getDate();
    Calendar expected = defaultDate();
    expected.add(Calendar.DAY_OF_MONTH, 1);
    
    assertCalendarDateEquals(expected, newDate);
  }
  
  public void testDateCanceled() {
    DatePreferenceActivity activity = getActivity();
    assertNotNull(activity);
    
    activateDodPreference();

    // increment the day
    sendKeys(KeyEvent.KEYCODE_DPAD_DOWN,
        KeyEvent.KEYCODE_DPAD_UP,
        KeyEvent.KEYCODE_DPAD_RIGHT,
        KeyEvent.KEYCODE_DPAD_UP,
        KeyEvent.KEYCODE_DPAD_UP,
        KeyEvent.KEYCODE_DPAD_CENTER);
    
    pressCancel();
    
    Calendar newDate = getDatePreference(activity).getDate();
    Calendar expected = defaultDate();
    
    assertCalendarDateEquals(expected, newDate);
  }
  
  public void testDateEdited() {
    DatePreferenceActivity activity = getActivity();
    assertNotNull(activity);
    
    activateDodPreference();

    // change the day
    sendKeys(KeyEvent.KEYCODE_DPAD_DOWN,
        KeyEvent.KEYCODE_DPAD_UP,
        KeyEvent.KEYCODE_DPAD_RIGHT,
        KeyEvent.KEYCODE_DPAD_UP,
        KeyEvent.KEYCODE_DEL,
        KeyEvent.KEYCODE_DEL,
        KeyEvent.KEYCODE_0,
        KeyEvent.KEYCODE_2);

    pressOK();
    
    Calendar newDate = getDatePreference(activity).getDate();
    Calendar expected = defaultDate();
    expected.add(Calendar.DAY_OF_MONTH, 1);
    
    assertCalendarDateEquals(expected, newDate);
  }
  
  // TODO: test: inputting letters?; edge case: increment date, cancel, show pref, OK, date is now set to canceled date
  
  private Calendar defaultDate() {
    return new GregorianCalendar(1970, 0, 1);
  }
  
  protected void assertCalendarDateEquals(Calendar expected, Calendar actual) {
    String msg = "Expected: " + formatter().format(expected.getTime()) + " but got: " + formatter().format(actual.getTime());
    assertEquals(msg, expected.get(Calendar.YEAR), actual.get(Calendar.YEAR));
    assertEquals(msg, expected.get(Calendar.MONTH), actual.get(Calendar.MONTH));
    assertEquals(msg, expected.get(Calendar.DAY_OF_MONTH), actual.get(Calendar.DAY_OF_MONTH));
  }
  
  private SimpleDateFormat formatter() {
    return new SimpleDateFormat("yyyy.MM.dd");
  }
  
  private void pressOK() {
    sendKeys(KeyEvent.KEYCODE_DPAD_DOWN,
        KeyEvent.KEYCODE_DPAD_DOWN,
        KeyEvent.KEYCODE_DPAD_DOWN,
        KeyEvent.KEYCODE_DPAD_LEFT,
        KeyEvent.KEYCODE_DPAD_CENTER);
  }
  
  private void pressCancel() {
      sendKeys(KeyEvent.KEYCODE_DPAD_DOWN,
          KeyEvent.KEYCODE_DPAD_DOWN,
          KeyEvent.KEYCODE_DPAD_DOWN,
          KeyEvent.KEYCODE_DPAD_RIGHT,
          KeyEvent.KEYCODE_DPAD_CENTER);
  }
  
  private void activateDodPreference() {
    sendKeys(KeyEvent.KEYCODE_DPAD_UP,
        KeyEvent.KEYCODE_DPAD_DOWN,
        KeyEvent.KEYCODE_DPAD_CENTER);
  }
  
  private DatePreference getDatePreference(DatePreferenceActivity activity) {
    PreferenceManager preferenceManager = activity.getPreferenceManager();
    assertNotNull(preferenceManager);
    DatePreference datePreference = (DatePreference)preferenceManager.findPreference("dod");
    assertNotNull(datePreference);
    return datePreference;
  }
}
@@ -139,16 +139,56 @@
 endar;%0A%0A
+import android.content.DialogInterface;%0A
 import a
@@ -3547,36 +3547,116 @@
 EYCODE_2);%0A%0A
+%0A
     
-pressOK(
+DatePreference datePreference = getDatePreference(activity);%0A    clickOK(datePreference
 );%0A    %0A    
@@ -3666,36 +3666,33 @@
 endar newDate = 
-getD
+d
 atePreference(ac
@@ -3684,34 +3684,24 @@
 tePreference
-(activity)
 .getDate();%0A
@@ -4832,32 +4832,179 @@
 CENTER);%0A  %7D%0A  %0A
+  // actually different than pressing OK%0A  private void clickOK(DatePreference dialog) %7B%0A    dialog.onClick(null, DialogInterface.BUTTON1);%0A  %7D%0A  %0A
   private void p

Simulate a button click