/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package com.android.calendar.event;

import android.content.ContentProvider;
import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentValues;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.net.Uri;
import android.provider.CalendarContract.Attendees;
import android.provider.CalendarContract.Events;
import android.provider.CalendarContract.Reminders;
import android.test.AndroidTestCase;
import android.test.mock.MockResources;
import android.test.suitebuilder.annotation.SmallTest;
import android.test.suitebuilder.annotation.Smoke;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.text.util.Rfc822Token;

import com.android.calendar.AbstractCalendarActivity;
import com.android.calendar.AsyncQueryService;
import com.android.calendar.CalendarEventModel;
import com.android.calendar.CalendarEventModel.ReminderEntry;
import com.android.calendar.R;
import com.android.calendar.Utils;
import com.android.common.Rfc822Validator;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.LinkedHashSet;
import java.util.TimeZone;

public class EditEventHelperTest extends AndroidTestCase {
    private static final int TEST_EVENT_ID = 1;
    private static final int TEST_EVENT_INDEX_ID = 0;
    private static final long TEST_END = 1272931200000L;
    private static long TEST_END2 = 1272956400000L;
    private static final long TEST_START = 1272844800000L;
    private static long TEST_START2 = 1272870000000L;
    private static final String LOCAL_TZ = TimeZone.getDefault().getID();

    private static final int SAVE_EVENT_NEW_EVENT = 1;
    private static final int SAVE_EVENT_MOD_RECUR = 2;
    private static final int SAVE_EVENT_RECUR_TO_NORECUR = 3;
    private static final int SAVE_EVENT_NORECUR_TO_RECUR= 4;
    private static final int SAVE_EVENT_MOD_NORECUR = 5;
    private static final int SAVE_EVENT_MOD_INSTANCE = 6;
    private static final int SAVE_EVENT_ALLFOLLOW_TO_NORECUR = 7;
    private static final int SAVE_EVENT_FIRST_TO_NORECUR = 8;
    private static final int SAVE_EVENT_FIRST_TO_RECUR = 9;
    private static final int SAVE_EVENT_ALLFOLLOW_TO_RECUR = 10;

    /* These should match up with EditEventHelper.EVENT_PROJECTION.
     * Note that spaces and commas have been removed to allow for easier sanitation.
     */
    private static String[] TEST_CURSOR_DATA = new String[] {
            Integer.toString(TEST_EVENT_ID), // 0 _id
            "The_Question", // 1 title
            "Evaluating_Life_the_Universe_and_Everything", // 2 description
            "Earth_Mk2", // 3 location
            "1", // 4 All Day
            "0", // 5 Has alarm
            "2", // 6 Calendar id
            "1272844800000", // 7 dtstart, Monday, May 3rd midnight UTC
            "1272931200000", // 8 dtend, Tuesday, May 4th midnight UTC
            "P3652421990D", // 9 duration, (10 million years)
            "UTC", // 10 event timezone
            "FREQ=DAILY;WKST=SU", // 11 rrule
            "unique_per_calendar_stuff", // 12 sync id
            "0", // 13 transparency/availability
            "3", // 14 visibility/access level
            "steve@gmail.com", // 15 owner account
            "1", // 16 has attendee data
            null, //17 originalSyncId
            "organizer@gmail.com", // 18 organizer
            "0", // 19 guest can modify
            "-1", // 20 original id
            "1", // 21 event status
            "-339611", // 22 calendar color
            "-2350809", // 23 event color
            "11" // 24 event color key
    };

    private static final String AUTHORITY_URI = "content://EditEventHelperAuthority/";
    private static final String AUTHORITY = "EditEventHelperAuthority";

    private static final String TEST_ADDRESSES =
            "no good, ad1@email.com, \"First Last\" <first@email.com> (comment), " +
            "one.two.three@email.grue";
    private static final String TEST_ADDRESSES2 =
            "no good, ad1@email.com, \"First Last\" <first@email.com> (comment), " +
            "different@email.bit";
    private static final String TEST_ADDRESSES3 =
            "ad1@email.com, \"First Last\" <first@email.com> (comment), " +
            "different@email.bit";
    private static final String TEST_ADDRESSES4 =
            "ad1@email.com, \"First Last\" <first@email.com> (comment), " +
            "one.two.three@email.grue";


    private static final String TAG = "EEHTest";

    private Rfc822Validator mEmailValidator;
    private CalendarEventModel mModel1;
    private CalendarEventModel mModel2;

    private ContentValues mValues;
    private ContentValues mExpectedValues;

    private EditEventHelper mHelper;
    private AbstractCalendarActivity mActivity;
    private int mCurrentSaveTest = 0;

    @Override
    public void setUp() {
        Time time = new Time(Time.TIMEZONE_UTC);
        time.set(TEST_START);
        time.timezone = LOCAL_TZ;
        TEST_START2 = time.normalize(true);

        time.timezone = Time.TIMEZONE_UTC;
        time.set(TEST_END);
        time.timezone = LOCAL_TZ;
        TEST_END2 = time.normalize(true);

        mEmailValidator = new Rfc822Validator(null);
    }

    private class MockAbsCalendarActivity extends AbstractCalendarActivity {
        @Override
        public AsyncQueryService getAsyncQueryService() {
            if (mService == null) {
                mService = new AsyncQueryService(this) {
                    @Override
                    public void startBatch(int token, Object cookie, String authority,
                            ArrayList<ContentProviderOperation> cpo, long delayMillis) {
                        mockApplyBatch(authority, cpo);
                    }
                };
            }
            return mService;
        }

        @Override
        public Resources getResources() {
            Resources res = new MockResources() {
                @Override
                // The actual selects singular vs plural as well and in the given language
                public String getQuantityString(int id, int quantity) {
                    if (id == R.plurals.Nmins) {
                        return quantity + " mins";
                    }
                    if (id == R.plurals.Nminutes) {
                        return quantity + " minutes";
                    }
                    if (id == R.plurals.Nhours) {
                        return quantity + " hours";
                    }
                    if (id == R.plurals.Ndays) {
                        return quantity + " days";
                    }
                    return id + " " + quantity;
                }
            };
            return res;
        }
    }

    private AbstractCalendarActivity buildTestContext() {
        MockAbsCalendarActivity context = new MockAbsCalendarActivity();
        return context;
    }

    private ContentProviderResult[] mockApplyBatch(String authority,
            ArrayList<ContentProviderOperation> operations) {
        switch (mCurrentSaveTest) {
            case SAVE_EVENT_NEW_EVENT:
                // new recurring event
                verifySaveEventNewEvent(operations);
                break;
            case SAVE_EVENT_MOD_RECUR:
                // update to recurring event
                verifySaveEventModifyRecurring(operations);
                break;
            case SAVE_EVENT_RECUR_TO_NORECUR:
                // replace recurring event with non-recurring event
                verifySaveEventRecurringToNonRecurring(operations);
                break;
            case SAVE_EVENT_NORECUR_TO_RECUR:
                // update non-recurring event with recurring event
                verifySaveEventNonRecurringToRecurring(operations);
                break;
            case SAVE_EVENT_MOD_NORECUR:
                // update to non-recurring
                verifySaveEventUpdateNonRecurring(operations);
                break;
            case SAVE_EVENT_MOD_INSTANCE:
                // update to single instance of recurring event
                verifySaveEventModifySingleInstance(operations);
                break;
            case SAVE_EVENT_ALLFOLLOW_TO_NORECUR:
                // update all following with non-recurring event
                verifySaveEventModifyAllFollowingWithNonRecurring(operations);
                break;
            case SAVE_EVENT_FIRST_TO_NORECUR:
                // update all following with non-recurring event on first event in series
                verifySaveEventModifyAllFollowingFirstWithNonRecurring(operations);
                break;
            case SAVE_EVENT_FIRST_TO_RECUR:
                // update all following with recurring event on first event in series
                verifySaveEventModifyAllFollowingFirstWithRecurring(operations);
                break;
            case SAVE_EVENT_ALLFOLLOW_TO_RECUR:
                // update all following with recurring event on second event in series
                verifySaveEventModifyAllFollowingWithRecurring(operations);
                break;
        }
        return new ContentProviderResult[] {new ContentProviderResult(5)};
    }

    private void addOwnerAttendeeToOps(ArrayList<ContentProviderOperation> expectedOps, int id) {
        addOwnerAttendee();
        ContentProviderOperation.Builder b;
        b = ContentProviderOperation.newInsert(Attendees.CONTENT_URI).withValues(mExpectedValues);
        b.withValueBackReference(Reminders.EVENT_ID, id);
        expectedOps.add(b.build());
    }

    private void addOwnerAttendeeToOps(ArrayList<ContentProviderOperation> expectedOps) {
        addOwnerAttendee();
        mExpectedValues.put(Attendees.EVENT_ID, TEST_EVENT_ID);
        ContentProviderOperation.Builder b;
        b = ContentProviderOperation.newInsert(Attendees.CONTENT_URI).withValues(mExpectedValues);
        expectedOps.add(b.build());
    }


    // Some tests set the time values to one day later, this does that move in the values
    private void moveExpectedTimeValuesForwardOneDay() {
        long dayInMs = EditEventHelper.DAY_IN_SECONDS*1000;
        mExpectedValues.put(Events.DTSTART, TEST_START + dayInMs);
        mExpectedValues.put(Events.DTEND, TEST_END + dayInMs);
    }

    // Duplicates the delete and add for changing a single email address
    private void addAttendeeChangesOps(ArrayList<ContentProviderOperation> expectedOps) {
        ContentProviderOperation.Builder b =
            ContentProviderOperation.newDelete(Attendees.CONTENT_URI);
        b.withSelection(EditEventHelper.ATTENDEES_DELETE_PREFIX + "?)",
                new String[] {"one.two.three@email.grue"});
        expectedOps.add(b.build());

        mExpectedValues.clear();
        mExpectedValues.put(Attendees.ATTENDEE_NAME, "different@email.bit");
        mExpectedValues.put(Attendees.ATTENDEE_EMAIL, "different@email.bit");
        mExpectedValues.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
        mExpectedValues.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_REQUIRED);
        mExpectedValues.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_NONE);
        mExpectedValues.put(Attendees.EVENT_ID, TEST_EVENT_ID);
        b = ContentProviderOperation
                .newInsert(Attendees.CONTENT_URI)
                .withValues(mExpectedValues);
        expectedOps.add(b.build());
    }

    // This is a commonly added set of values
    private void addOwnerAttendee() {
        mExpectedValues.clear();
        mExpectedValues.put(Attendees.ATTENDEE_EMAIL, mModel1.mOwnerAccount);
        mExpectedValues.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ORGANIZER);
        mExpectedValues.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_REQUIRED);
        mExpectedValues.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_ACCEPTED);
    }

    /** Some tests add all the attendees to the db, the names and emails should match
     * with {@link #TEST_ADDRESSES2} minus the 'no good'
     */
    private void addTestAttendees(ArrayList<ContentProviderOperation> ops,
            boolean newEvent, int id) {
        ContentProviderOperation.Builder b;
        mExpectedValues.clear();
        mExpectedValues.put(Attendees.ATTENDEE_NAME, "ad1@email.com");
        mExpectedValues.put(Attendees.ATTENDEE_EMAIL, "ad1@email.com");
        mExpectedValues.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
        mExpectedValues.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_REQUIRED);
        mExpectedValues.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_NONE);

        if (newEvent) {
            b = ContentProviderOperation
                    .newInsert(Attendees.CONTENT_URI)
                    .withValues(mExpectedValues);
            b.withValueBackReference(Attendees.EVENT_ID, id);
        } else {
            mExpectedValues.put(Attendees.EVENT_ID, id);
            b = ContentProviderOperation
                    .newInsert(Attendees.CONTENT_URI)
                    .withValues(mExpectedValues);
        }
        ops.add(b.build());

        mExpectedValues.clear();
        mExpectedValues.put(Attendees.ATTENDEE_NAME, "First Last");
        mExpectedValues.put(Attendees.ATTENDEE_EMAIL, "first@email.com");
        mExpectedValues.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
        mExpectedValues.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_REQUIRED);
        mExpectedValues.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_NONE);

        if (newEvent) {
            b = ContentProviderOperation
                    .newInsert(Attendees.CONTENT_URI)
                    .withValues(mExpectedValues);
            b.withValueBackReference(Attendees.EVENT_ID, id);
        } else {
            mExpectedValues.put(Attendees.EVENT_ID, id);
            b = ContentProviderOperation
                    .newInsert(Attendees.CONTENT_URI)
                    .withValues(mExpectedValues);
        }
        ops.add(b.build());

        mExpectedValues.clear();
        mExpectedValues.put(Attendees.ATTENDEE_NAME, "different@email.bit");
        mExpectedValues.put(Attendees.ATTENDEE_EMAIL, "different@email.bit");
        mExpectedValues.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
        mExpectedValues.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_REQUIRED);
        mExpectedValues.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_NONE);

        if (newEvent) {
            b = ContentProviderOperation
                    .newInsert(Attendees.CONTENT_URI)
                    .withValues(mExpectedValues);
            b.withValueBackReference(Attendees.EVENT_ID, id);
        } else {
            mExpectedValues.put(Attendees.EVENT_ID, id);
            b = ContentProviderOperation
                    .newInsert(Attendees.CONTENT_URI)
                    .withValues(mExpectedValues);
        }
        ops.add(b.build());
    }

    @Smoke
    @SmallTest
    public void testSaveEventFailures() {
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);

        mModel1 = buildTestModel();
        mModel2 = buildTestModel();

        // saveEvent should return false early if:
        // -it was set to not ok
        // -the model was null
        // -the event doesn't represent the same event as the original event
        // -there's a uri but an original event is not provided
        mHelper.mEventOk = false;
        assertFalse(mHelper.saveEvent(null, null, 0));
        mHelper.mEventOk = true;
        assertFalse(mHelper.saveEvent(null, null, 0));
        mModel2.mId = 13;
        assertFalse(mHelper.saveEvent(mModel1, mModel2, 0));
        mModel2.mId = mModel1.mId;
        mModel1.mUri = (AUTHORITY_URI + TEST_EVENT_ID);
        mModel2.mUri = (AUTHORITY_URI + TEST_EVENT_ID);
        assertFalse(mHelper.saveEvent(mModel1, null, 0));
    }

    @Smoke
    @SmallTest
    public void testSaveEventNewEvent() {
        // Creates a model of a new event for saving
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);

        mModel1 = buildTestModel();
        mModel1.addAttendees(TEST_ADDRESSES2, mEmailValidator);
        mCurrentSaveTest = SAVE_EVENT_NEW_EVENT;

        assertTrue(mHelper.saveEvent(mModel1, null, 0));
    }

    private boolean verifySaveEventNewEvent(ArrayList<ContentProviderOperation> ops) {
        ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
        int br_id = 0;
        mExpectedValues = buildTestValues();
        mExpectedValues.put(Events.HAS_ALARM, 0);
        mExpectedValues.put(Events.HAS_ATTENDEE_DATA, 1);
        ContentProviderOperation.Builder b = ContentProviderOperation
                .newInsert(Events.CONTENT_URI)
                .withValues(mExpectedValues);
        expectedOps.add(b.build());

        // This call has a separate unit test so we'll use it to simplify making the expected vals
        mHelper.saveRemindersWithBackRef(expectedOps, br_id, mModel1.mReminders,
                new ArrayList<ReminderEntry>(), true);

        addOwnerAttendeeToOps(expectedOps, br_id);

        addTestAttendees(expectedOps, true, br_id);

        assertEquals(expectedOps, ops);
        return true;
    }

    @Smoke
    @SmallTest
    public void testSaveEventModifyRecurring() {
        // Creates an original and an updated recurring event model
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);

        mModel1 = buildTestModel();
        mModel2 = buildTestModel();
        mModel1.addAttendees(TEST_ADDRESSES2, mEmailValidator);

        // Updating a recurring event with a new attendee list
        mModel1.mUri = (AUTHORITY_URI + TEST_EVENT_ID);
        // And a new start time to ensure the time fields aren't removed
        mModel1.mOriginalStart = TEST_START;

        // The original model is assumed correct so drop the no good bit
        mModel2.addAttendees(TEST_ADDRESSES4, null);
        mCurrentSaveTest = SAVE_EVENT_MOD_RECUR;

        assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_ALL));
    }

    private boolean verifySaveEventModifyRecurring(ArrayList<ContentProviderOperation> ops) {
        ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
        int br_id = 0;
        mExpectedValues = buildTestValues();
        mExpectedValues.put(Events.HAS_ALARM, 0);
        // This is tested elsewhere, used for convenience here
        mHelper.checkTimeDependentFields(mModel2, mModel1, mExpectedValues,
                EditEventHelper.MODIFY_ALL);

        expectedOps.add(ContentProviderOperation.newUpdate(Uri.parse(mModel1.mUri)).withValues(
                mExpectedValues).build());

        // This call has a separate unit test so we'll use it to simplify making the expected vals
        mHelper.saveReminders(expectedOps, TEST_EVENT_ID, mModel1.mReminders,
                mModel2.mReminders, false);

        addOwnerAttendeeToOps(expectedOps);
        addAttendeeChangesOps(expectedOps);

        assertEquals(expectedOps, ops);
        return true;
    }

    @Smoke
    @SmallTest
    public void testSaveEventRecurringToNonRecurring() {
        // Creates an original and an updated recurring event model
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);

        mModel1 = buildTestModel();
        mModel2 = buildTestModel();
        mModel1.addAttendees(TEST_ADDRESSES2, mEmailValidator);

        // Updating a recurring event with a new attendee list
        mModel1.mUri = (AUTHORITY_URI + TEST_EVENT_ID);
        // And a new start time to ensure the time fields aren't removed
        mModel1.mOriginalStart = TEST_START;

        // The original model is assumed correct so drop the no good bit
        mModel2.addAttendees(TEST_ADDRESSES4, null);

        // Replace an existing recurring event with a non-recurring event
        mModel1.mRrule = null;
        mModel1.mEnd = TEST_END;
        mCurrentSaveTest = SAVE_EVENT_RECUR_TO_NORECUR;

        assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_ALL));
    }

    private boolean verifySaveEventRecurringToNonRecurring(ArrayList<ContentProviderOperation> ops)
            {
        ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
        int id = 0;
        mExpectedValues = buildNonRecurringTestValues();
        mExpectedValues.put(Events.HAS_ALARM, 0);
        // This is tested elsewhere, used for convenience here
        mHelper.checkTimeDependentFields(mModel1, mModel1, mExpectedValues,
                EditEventHelper.MODIFY_ALL);

        expectedOps.add(ContentProviderOperation.newDelete(Uri.parse(mModel1.mUri)).build());
        id = expectedOps.size();
        expectedOps.add(ContentProviderOperation
                        .newInsert(Events.CONTENT_URI)
                        .withValues(mExpectedValues)
                        .build());

        mHelper.saveRemindersWithBackRef(expectedOps, id, mModel1.mReminders,
                mModel2.mReminders, true);

        addOwnerAttendeeToOps(expectedOps, id);

        addTestAttendees(expectedOps, true, id);

        assertEquals(expectedOps, ops);
        return true;
    }

    @Smoke
    @SmallTest
    public void testSaveEventNonRecurringToRecurring() {
        // Creates an original non-recurring and an updated recurring event model
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);

        mModel1 = buildTestModel();
        mModel2 = buildTestModel();
        mModel1.addAttendees(TEST_ADDRESSES2, mEmailValidator);

        // Updating a recurring event with a new attendee list
        mModel1.mUri = (AUTHORITY_URI + TEST_EVENT_ID);
        // And a new start time to ensure the time fields aren't removed
        mModel1.mOriginalStart = TEST_START;

        // The original model is assumed correct so drop the no good bit
        mModel2.addAttendees(TEST_ADDRESSES4, null);

        mModel2.mRrule = null;
        mModel2.mEnd = TEST_END;
        mCurrentSaveTest = SAVE_EVENT_NORECUR_TO_RECUR;

        assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_ALL));
    }

    private boolean verifySaveEventNonRecurringToRecurring(ArrayList<ContentProviderOperation> ops)
            {
        // Changing a non-recurring event to a recurring event should generate the same operations
        // as just modifying a recurring event.
        return verifySaveEventModifyRecurring(ops);
    }

    @Smoke
    @SmallTest
    public void testSaveEventUpdateNonRecurring() {
        // Creates an original non-recurring and an updated recurring event model
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);

        mModel1 = buildTestModel();
        mModel2 = buildTestModel();
        mModel1.addAttendees(TEST_ADDRESSES2, mEmailValidator);

        // Updating a recurring event with a new attendee list
        mModel1.mUri = (AUTHORITY_URI + TEST_EVENT_ID);
        // And a new start time to ensure the time fields aren't removed
        mModel1.mOriginalStart = TEST_START;

        // The original model is assumed correct so drop the no good bit
        mModel2.addAttendees(TEST_ADDRESSES4, null);

        mModel2.mRrule = null;
        mModel2.mEnd = TEST_END2;
        mModel1.mRrule = null;
        mModel1.mEnd = TEST_END2;
        mCurrentSaveTest = SAVE_EVENT_MOD_NORECUR;

        assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_ALL));
    }

    private boolean verifySaveEventUpdateNonRecurring(ArrayList<ContentProviderOperation> ops) {
        ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
        int id = TEST_EVENT_ID;
        mExpectedValues = buildNonRecurringTestValues();
        mExpectedValues.put(Events.HAS_ALARM, 0);
        // This is tested elsewhere, used for convenience here
        mHelper.checkTimeDependentFields(mModel1, mModel1, mExpectedValues,
                EditEventHelper.MODIFY_ALL);
        expectedOps.add(ContentProviderOperation.newUpdate(Uri.parse(mModel1.mUri)).withValues(
                mExpectedValues).build());
        // This call has a separate unit test so we'll use it to simplify making the expected vals
        mHelper.saveReminders(expectedOps, TEST_EVENT_ID, mModel1.mReminders,
                mModel2.mReminders, false);
        addOwnerAttendeeToOps(expectedOps);
        addAttendeeChangesOps(expectedOps);

        assertEquals(expectedOps, ops);
        return true;
    }

    @Smoke
    @SmallTest
    public void testSaveEventModifySingleInstance() {
        // Creates an original non-recurring and an updated recurring event model
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);

        mModel1 = buildTestModel();
        mModel2 = buildTestModel();
        mModel1.addAttendees(TEST_ADDRESSES2, mEmailValidator);

        mModel1.mUri = (AUTHORITY_URI + TEST_EVENT_ID);
        // And a new start time to ensure the time fields aren't removed
        mModel1.mOriginalStart = TEST_START;

        // The original model is assumed correct so drop the no good bit
        mModel2.addAttendees(TEST_ADDRESSES4, null);

        // Modify the second instance of the event
        long dayInMs = EditEventHelper.DAY_IN_SECONDS*1000;
        mModel1.mRrule = null;
        mModel1.mEnd = TEST_END + dayInMs;
        mModel1.mStart += dayInMs;
        mModel1.mOriginalStart = mModel1.mStart;

        mCurrentSaveTest = SAVE_EVENT_MOD_INSTANCE;
        // Only modify this instance
        assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_SELECTED));
    }

    private boolean verifySaveEventModifySingleInstance(ArrayList<ContentProviderOperation> ops) {
        ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
        int id = 0;
        mExpectedValues = buildNonRecurringTestValues();
        mExpectedValues.put(Events.HAS_ALARM, 0);
        // This is tested elsewhere, used for convenience here
        mHelper.checkTimeDependentFields(mModel1, mModel1, mExpectedValues,
                EditEventHelper.MODIFY_ALL);

        moveExpectedTimeValuesForwardOneDay();
        mExpectedValues.put(Events.ORIGINAL_SYNC_ID, mModel2.mSyncId);
        mExpectedValues.put(Events.ORIGINAL_INSTANCE_TIME, mModel1.mOriginalStart);
        mExpectedValues.put(Events.ORIGINAL_ALL_DAY, 1);

        ContentProviderOperation.Builder b = ContentProviderOperation
                .newInsert(Events.CONTENT_URI)
                .withValues(mExpectedValues);
        expectedOps.add(b.build());

        mHelper.saveRemindersWithBackRef(expectedOps, id, mModel1.mReminders,
                mModel2.mReminders, true);

        addOwnerAttendeeToOps(expectedOps, id);

        addTestAttendees(expectedOps, true, id);

        assertEquals(expectedOps, ops);
        return true;
    }

    @Smoke
    @SmallTest
    public void testSaveEventModifyAllFollowingWithNonRecurring() {
        // Creates an original and an updated recurring event model. The update starts on the 2nd
        // instance of the original.
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);

        mModel1 = buildTestModel();
        mModel2 = buildTestModel();
        mModel1.addAttendees(TEST_ADDRESSES2, mEmailValidator);

        mModel1.mUri = (AUTHORITY_URI + TEST_EVENT_ID);
        mModel2.mUri = (AUTHORITY_URI + TEST_EVENT_ID);

        // The original model is assumed correct so drop the no good bit
        mModel2.addAttendees(TEST_ADDRESSES4, null);

        // Modify the second instance of the event
        long dayInMs = EditEventHelper.DAY_IN_SECONDS*1000;
        mModel1.mRrule = null;
        mModel1.mEnd = TEST_END + dayInMs;
        mModel1.mStart += dayInMs;
        mModel1.mOriginalStart = mModel1.mStart;

        mCurrentSaveTest = SAVE_EVENT_ALLFOLLOW_TO_NORECUR;
        // Only modify this instance
        assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_ALL_FOLLOWING));
    }

    private boolean verifySaveEventModifyAllFollowingWithNonRecurring(
            ArrayList<ContentProviderOperation> ops) {
        ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
        int id = 0;
        mExpectedValues = buildNonRecurringTestValues();
        mExpectedValues.put(Events.HAS_ALARM, 0);
        moveExpectedTimeValuesForwardOneDay();
        // This has a separate test
        mHelper.updatePastEvents(expectedOps, mModel2, mModel1.mOriginalStart);
        id = expectedOps.size();
        expectedOps.add(ContentProviderOperation
                .newInsert(Events.CONTENT_URI)
                .withValues(mExpectedValues)
                .build());

        mHelper.saveRemindersWithBackRef(expectedOps, id, mModel1.mReminders,
                mModel2.mReminders, true);

        addOwnerAttendeeToOps(expectedOps, id);

        addTestAttendees(expectedOps, true, id);

        assertEquals(expectedOps, ops);
        return true;
    }

    @Smoke
    @SmallTest
    public void testSaveEventModifyAllFollowingFirstWithNonRecurring() {
        // Creates an original recurring and an updated non-recurring event model for the first
        // instance. This should replace the original event with a non-recurring event.
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);

        mModel1 = buildTestModel();
        mModel2 = buildTestModel();
        mModel1.addAttendees(TEST_ADDRESSES2, mEmailValidator);

        mModel1.mUri = (AUTHORITY_URI + TEST_EVENT_ID);
        mModel2.mUri = mModel1.mUri;
        // And a new start time to ensure the time fields aren't removed
        mModel1.mOriginalStart = TEST_START;

        // The original model is assumed correct so drop the no good bit
        mModel2.addAttendees(TEST_ADDRESSES3, null);

        // Move the event one day but keep original start set to the first instance
        long dayInMs = EditEventHelper.DAY_IN_SECONDS*1000;
        mModel1.mRrule = null;
        mModel1.mEnd = TEST_END + dayInMs;
        mModel1.mStart += dayInMs;

        mCurrentSaveTest = SAVE_EVENT_FIRST_TO_NORECUR;
        // Only modify this instance
        assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_ALL_FOLLOWING));
    }

    private boolean verifySaveEventModifyAllFollowingFirstWithNonRecurring(
            ArrayList<ContentProviderOperation> ops) {

        ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
        int id = 0;
        mExpectedValues = buildNonRecurringTestValues();
        mExpectedValues.put(Events.HAS_ALARM, 0);
        moveExpectedTimeValuesForwardOneDay();

        expectedOps.add(ContentProviderOperation.newDelete(Uri.parse(mModel1.mUri)).build());
        id = expectedOps.size();
        expectedOps.add(ContentProviderOperation
                        .newInsert(Events.CONTENT_URI)
                        .withValues(mExpectedValues)
                        .build());

        mHelper.saveRemindersWithBackRef(expectedOps, id, mModel1.mReminders,
                mModel2.mReminders, true);

        addOwnerAttendeeToOps(expectedOps, id);

        addTestAttendees(expectedOps, true, id);

        assertEquals(expectedOps, ops);
        return true;
    }

    @Smoke
    @SmallTest
    public void testSaveEventModifyAllFollowingFirstWithRecurring() {
        // Creates an original recurring and an updated recurring event model for the first instance
        // This should replace the original event with a new recurrence
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);

        mModel1 = buildTestModel();
        mModel2 = buildTestModel();
        mModel1.addAttendees(TEST_ADDRESSES2, mEmailValidator);

        mModel1.mUri = (AUTHORITY_URI + TEST_EVENT_ID);
        mModel2.mUri = mModel1.mUri;
        // And a new start time to ensure the time fields aren't removed
        mModel1.mOriginalStart = TEST_START;

        // The original model is assumed correct so drop the no good bit
        mModel2.addAttendees(TEST_ADDRESSES4, null);

        // Move the event one day but keep original start set to the first instance
        long dayInMs = EditEventHelper.DAY_IN_SECONDS*1000;
        mModel1.mStart += dayInMs;

        mCurrentSaveTest = SAVE_EVENT_FIRST_TO_RECUR;
        // Only modify this instance
        assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_ALL_FOLLOWING));
    }

    private boolean verifySaveEventModifyAllFollowingFirstWithRecurring(
            ArrayList<ContentProviderOperation> ops) {
        ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
        int br_id = 0;
        mExpectedValues = buildTestValues();
        mExpectedValues.put(Events.HAS_ALARM, 0);
        moveExpectedTimeValuesForwardOneDay();
        mExpectedValues.put(Events.DTEND, (Long)null);
        // This is tested elsewhere, used for convenience here
        mHelper.checkTimeDependentFields(mModel2, mModel1, mExpectedValues,
                EditEventHelper.MODIFY_ALL_FOLLOWING);

        expectedOps.add(ContentProviderOperation.newUpdate(Uri.parse(mModel1.mUri)).withValues(
                mExpectedValues).build());

        // This call has a separate unit test so we'll use it to simplify making the expected vals
        mHelper.saveReminders(expectedOps, TEST_EVENT_ID, mModel1.mReminders,
                mModel2.mReminders, true);

        addOwnerAttendeeToOps(expectedOps);
        addAttendeeChangesOps(expectedOps);

        assertEquals(expectedOps, ops);
        return true;
    }

    @Smoke
    @SmallTest
    public void testSaveEventModifyAllFollowingWithRecurring() {
        // Creates an original recurring and an updated recurring event model
        // for the second instance. This should end the original recurrence and add a new
        // recurrence.
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);

        mModel1 = buildTestModel();
        mModel2 = buildTestModel();
        mModel1.addAttendees(TEST_ADDRESSES2, mEmailValidator);

        mModel1.mUri = (AUTHORITY_URI + TEST_EVENT_ID);
        mModel2.mUri = (AUTHORITY_URI + TEST_EVENT_ID);

        // The original model is assumed correct so drop the no good bit
        mModel2.addAttendees(TEST_ADDRESSES4, null);

        // Move the event one day and the original start so it references the second instance
        long dayInMs = EditEventHelper.DAY_IN_SECONDS*1000;
        mModel1.mStart += dayInMs;
        mModel1.mOriginalStart = mModel1.mStart;

        mCurrentSaveTest = SAVE_EVENT_ALLFOLLOW_TO_RECUR;
        // Only modify this instance
        assertTrue(mHelper.saveEvent(mModel1, mModel2, EditEventHelper.MODIFY_ALL_FOLLOWING));
    }

    private boolean verifySaveEventModifyAllFollowingWithRecurring(
            ArrayList<ContentProviderOperation> ops) {
        ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
        int br_id = 0;
        mExpectedValues = buildTestValues();
        mExpectedValues.put(Events.HAS_ALARM, 0);
        moveExpectedTimeValuesForwardOneDay();
        mExpectedValues.put(Events.DTEND, (Long)null);
        // This is tested elsewhere, used for convenience here
        mHelper.updatePastEvents(expectedOps, mModel2, mModel1.mOriginalStart);

        br_id = expectedOps.size();
        expectedOps.add(ContentProviderOperation
                .newInsert(Events.CONTENT_URI)
                .withValues(mExpectedValues)
                .build());

        // This call has a separate unit test so we'll use it to simplify making the expected vals
        mHelper.saveRemindersWithBackRef(expectedOps, br_id, mModel1.mReminders,
                mModel2.mReminders, true);

        addOwnerAttendeeToOps(expectedOps, br_id);

        addTestAttendees(expectedOps, true, br_id);

        assertEquals(expectedOps, ops);
        return true;
    }

    @Smoke
    @SmallTest
    public void testGetAddressesFromList() {
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);

        LinkedHashSet<Rfc822Token> expected = new LinkedHashSet<Rfc822Token>();
        expected.add(new Rfc822Token(null, "ad1@email.com", ""));
        expected.add(new Rfc822Token("First Last", "first@email.com", "comment"));
        expected.add(new Rfc822Token(null, "one.two.three@email.grue", ""));

        LinkedHashSet<Rfc822Token> actual = mHelper.getAddressesFromList(TEST_ADDRESSES,
                new Rfc822Validator(null));
        assertEquals(expected, actual);
    }

    @Smoke
    @SmallTest
    public void testConstructDefaultStartTime() {
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);

        long now = 0;
        long expected = now + 30 * DateUtils.MINUTE_IN_MILLIS;
        assertEquals(expected, mHelper.constructDefaultStartTime(now));

        // 2:00 -> 2:30
        now = 1262340000000L; // Fri Jan 01 2010 02:00:00 GMT-0800 (PST)
        expected = now + 30 * DateUtils.MINUTE_IN_MILLIS;
        assertEquals(expected, mHelper.constructDefaultStartTime(now));

        // 2:01 -> 2:30
        now += DateUtils.MINUTE_IN_MILLIS;
        assertEquals(expected, mHelper.constructDefaultStartTime(now));

        // 2:02 -> 2:30
        now += DateUtils.MINUTE_IN_MILLIS;
        assertEquals(expected, mHelper.constructDefaultStartTime(now));

        // 2:32 -> 3:00
        now += 30 * DateUtils.MINUTE_IN_MILLIS;
        expected += 30 * DateUtils.MINUTE_IN_MILLIS;
        assertEquals(expected, mHelper.constructDefaultStartTime(now));

        // 2:33 -> 3:00
        now += DateUtils.MINUTE_IN_MILLIS;
        assertEquals(expected, mHelper.constructDefaultStartTime(now));

    }

    @Smoke
    @SmallTest
    public void testConstructDefaultEndTime() {
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);

        long start = 1262340000000L;
        long expected = start + DateUtils.HOUR_IN_MILLIS;
        assertEquals(expected, mHelper.constructDefaultEndTime(start));
    }

    @Smoke
    @SmallTest
    public void testCheckTimeDependentFieldsNoChanges() {
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);

        mModel1 = buildTestModel();
        mModel2 = buildTestModel();
        mModel2.mRrule = null;

        mValues = buildTestValues();
        mExpectedValues = buildTestValues();

        // if any time/recurrence vals are different but there's no new rrule it
        // shouldn't change
        mHelper.checkTimeDependentFields(mModel1, mModel2, mValues, EditEventHelper.MODIFY_ALL);
        assertEquals(mExpectedValues, mValues);

        // also, if vals are different and it's not modifying all it shouldn't
        // change.
        mModel2.mRrule = "something else";
        mHelper.checkTimeDependentFields(mModel1, mModel2, mValues,
                EditEventHelper.MODIFY_SELECTED);
        assertEquals(mExpectedValues, mValues);

        // if vals changed and modify all is selected dtstart should be updated
        // by the difference
        // between originalStart and start
        mModel2.mOriginalStart = mModel2.mStart + 60000; // set the old time to
                                                         // one minute later
        mModel2.mStart += 120000; // move the event another 1 minute.

        // shouldn't change for an allday event
        // expectedVals.put(Events.DTSTART, mModel1.mStart + 60000); // should
        // now be 1 minute later
        // dtstart2 shouldn't change since it gets rezeroed in the local
        // timezone for allDay events

        mHelper.checkTimeDependentFields(mModel1, mModel2, mValues,
                EditEventHelper.MODIFY_SELECTED);
        assertEquals(mExpectedValues, mValues);
    }

    @Smoke
    @SmallTest
    public void testCheckTimeDependentFieldsChanges() {
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);

        mModel1 = buildTestModel();
        mModel2 = buildTestModel();
        mModel2.mRrule = null;

        mValues = buildTestValues();
        mExpectedValues = buildTestValues();

        // if all the time values are the same it should remove them from vals
        mModel2.mRrule = mModel1.mRrule;
        mModel2.mStart = mModel1.mStart;
        mModel2.mOriginalStart = mModel2.mStart;

        mExpectedValues.remove(Events.DTSTART);
        mExpectedValues.remove(Events.DTEND);
        mExpectedValues.remove(Events.DURATION);
        mExpectedValues.remove(Events.ALL_DAY);
        mExpectedValues.remove(Events.RRULE);
        mExpectedValues.remove(Events.EVENT_TIMEZONE);

        mHelper.checkTimeDependentFields(mModel1, mModel2, mValues,
                EditEventHelper.MODIFY_SELECTED);
        assertEquals(mExpectedValues, mValues);

    }

    @Smoke
    @SmallTest
    public void testUpdatePastEvents() {
        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
        ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
        long initialBeginTime = 1472864400000L; // Sep 3, 2016, 12AM UTC time
        mValues = new ContentValues();

        mModel1 = buildTestModel();
        mModel1.mUri = (AUTHORITY_URI + TEST_EVENT_ID);
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);

        mValues.put(Events.RRULE, "FREQ=DAILY;UNTIL=20160903;WKST=SU"); // yyyymmddThhmmssZ
        mValues.put(Events.DTSTART, TEST_START);

        ContentProviderOperation.Builder b = ContentProviderOperation.newUpdate(
                Uri.parse(mModel1.mUri)).withValues(mValues);
        expectedOps.add(b.build());

        mHelper.updatePastEvents(ops, mModel1, initialBeginTime);
        assertEquals(expectedOps, ops);

        mModel1.mAllDay = false;

        mValues.put(Events.RRULE, "FREQ=DAILY;UNTIL=20160903T005959Z;WKST=SU"); // yyyymmddThhmmssZ

        expectedOps.clear();
        b = ContentProviderOperation.newUpdate(Uri.parse(mModel1.mUri)).withValues(mValues);
        expectedOps.add(b.build());

        ops.clear();
        mHelper.updatePastEvents(ops, mModel1, initialBeginTime);
        assertEquals(expectedOps, ops);
    }

    @Smoke
    @SmallTest
    public void testConstructReminderLabel() {
        mActivity = buildTestContext();

        String label = EventViewUtils.constructReminderLabel(mActivity, 35, true);
        assertEquals("35 mins", label);

        label = EventViewUtils.constructReminderLabel(mActivity, 72, false);
        assertEquals("72 minutes", label);

        label = EventViewUtils.constructReminderLabel(mActivity, 60, true);
        assertEquals("1 hours", label);

        label = EventViewUtils.constructReminderLabel(mActivity, 60 * 48, true);
        assertEquals("2 days", label);
    }

    @Smoke
    @SmallTest
    public void testIsSameEvent() {
        mModel1 = new CalendarEventModel();
        mModel2 = new CalendarEventModel();

        mModel1.mId = 1;
        mModel1.mCalendarId = 1;
        mModel2.mId = 1;
        mModel2.mCalendarId = 1;

        // considered the same if the event and calendar ids both match
        assertTrue(EditEventHelper.isSameEvent(mModel1, mModel2));

        mModel2.mId = 2;
        assertFalse(EditEventHelper.isSameEvent(mModel1, mModel2));

        mModel2.mId = 1;
        mModel2.mCalendarId = 2;
        assertFalse(EditEventHelper.isSameEvent(mModel1, mModel2));
    }

    @Smoke
    @SmallTest
    public void testSaveReminders() {
        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
        ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
        long eventId = TEST_EVENT_ID;
        ArrayList<ReminderEntry> reminders = new ArrayList<ReminderEntry>();
        ArrayList<ReminderEntry> originalReminders = new ArrayList<ReminderEntry>();
        boolean forceSave = true;
        boolean result;
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);
        assertNotNull(mHelper);

        // First test forcing a delete with no reminders.
        String where = Reminders.EVENT_ID + "=?";
        String[] args = new String[] {Long.toString(eventId)};
        ContentProviderOperation.Builder b =
                ContentProviderOperation.newDelete(Reminders.CONTENT_URI);
        b.withSelection(where, args);
        expectedOps.add(b.build());

        result = mHelper.saveReminders(ops, eventId, reminders, originalReminders, forceSave);
        assertTrue(result);
        assertEquals(expectedOps, ops);

        // Now test calling save with identical reminders and no forcing
        reminders.add(ReminderEntry.valueOf(5));
        reminders.add(ReminderEntry.valueOf(10));
        reminders.add(ReminderEntry.valueOf(15));

        originalReminders.add(ReminderEntry.valueOf(5));
        originalReminders.add(ReminderEntry.valueOf(10));
        originalReminders.add(ReminderEntry.valueOf(15));

        forceSave = false;

        ops.clear();

        // Should fail to create any ops since nothing changed
        result = mHelper.saveReminders(ops, eventId, reminders, originalReminders, forceSave);
        assertFalse(result);
        assertEquals(0, ops.size());

        //Now test adding a single reminder
        originalReminders.remove(2);

        addExpectedMinutes(expectedOps);

        result = mHelper.saveReminders(ops, eventId, reminders, originalReminders, forceSave);
        assertTrue(result);
        assertEquals(expectedOps, ops);
    }

    @Smoke
    @SmallTest
    public void testSaveRemindersWithBackRef() {
        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
        ArrayList<ContentProviderOperation> expectedOps = new ArrayList<ContentProviderOperation>();
        long eventId = TEST_EVENT_ID;
        ArrayList<ReminderEntry> reminders = new ArrayList<ReminderEntry>();
        ArrayList<ReminderEntry> originalReminders = new ArrayList<ReminderEntry>();
        boolean forceSave = true;
        boolean result;
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);
        assertNotNull(mHelper);

        // First test forcing a delete with no reminders.
        ContentProviderOperation.Builder b =
                ContentProviderOperation.newDelete(Reminders.CONTENT_URI);
        b.withSelection(Reminders.EVENT_ID + "=?", new String[1]);
        b.withSelectionBackReference(0, TEST_EVENT_INDEX_ID);
        expectedOps.add(b.build());

        result =
                mHelper.saveRemindersWithBackRef(ops, TEST_EVENT_INDEX_ID, reminders,
                        originalReminders, forceSave);
        assertTrue(result);
        assertEquals(expectedOps, ops);

        // Now test calling save with identical reminders and no forcing
        reminders.add(ReminderEntry.valueOf(5));
        reminders.add(ReminderEntry.valueOf(10));
        reminders.add(ReminderEntry.valueOf(15));

        originalReminders.add(ReminderEntry.valueOf(5));
        originalReminders.add(ReminderEntry.valueOf(10));
        originalReminders.add(ReminderEntry.valueOf(15));

        forceSave = false;

        ops.clear();

        result = mHelper.saveRemindersWithBackRef(ops, ops.size(), reminders, originalReminders,
                        forceSave);
        assertFalse(result);
        assertEquals(0, ops.size());

        //Now test adding a single reminder
        originalReminders.remove(2);

        addExpectedMinutesWithBackRef(expectedOps);

        result = mHelper.saveRemindersWithBackRef(ops, ops.size(), reminders, originalReminders,
                        forceSave);
        assertTrue(result);
        assertEquals(expectedOps, ops);
    }

    @Smoke
    @SmallTest
    public void testIsFirstEventInSeries() {
        mModel1 = new CalendarEventModel();
        mModel2 = new CalendarEventModel();

        // It's considered the first event if the original start of the new model matches the
        // start of the old model
        mModel1.mOriginalStart = 100;
        mModel1.mStart = 200;
        mModel2.mOriginalStart = 100;
        mModel2.mStart = 100;

        assertTrue(EditEventHelper.isFirstEventInSeries(mModel1, mModel2));

        mModel1.mOriginalStart = 80;
        assertFalse(EditEventHelper.isFirstEventInSeries(mModel1, mModel2));
    }

    @Smoke
    @SmallTest
    public void testAddRecurrenceRule() {
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);
        mValues = new ContentValues();
        mExpectedValues = new ContentValues();
        mModel1 = new CalendarEventModel();

        mExpectedValues.put(Events.RRULE, "Weekly, Monday");
        mExpectedValues.put(Events.DURATION, "P60S");
        mExpectedValues.put(Events.DTEND, (Long) null);

        mModel1.mRrule = "Weekly, Monday";
        mModel1.mStart = 1;
        mModel1.mEnd = 60001;
        mModel1.mAllDay = false;

        mHelper.addRecurrenceRule(mValues, mModel1);
        assertEquals(mExpectedValues, mValues);

        mExpectedValues.put(Events.DURATION, "P1D");

        mModel1.mAllDay = true;
        mValues.clear();

        mHelper.addRecurrenceRule(mValues, mModel1);
        assertEquals(mExpectedValues, mValues);

    }

    @Smoke
    @SmallTest
    public void testUpdateRecurrenceRule() {
        int selection = EditEventHelper.DOES_NOT_REPEAT;
        int weekStart = Calendar.SUNDAY;
        mModel1 = new CalendarEventModel();
        mModel1.mTimezone = Time.TIMEZONE_UTC;
        mModel1.mStart = 1272665741000L; // Fri, April 30th ~ 3:17PM

        mModel1.mRrule = "This should go away";

        EditEventHelper.updateRecurrenceRule(selection, mModel1, weekStart);
        assertNull(mModel1.mRrule);

        mModel1.mRrule = "This shouldn't change";
        selection = EditEventHelper.REPEATS_CUSTOM;

        EditEventHelper.updateRecurrenceRule(selection, mModel1, weekStart);
        assertEquals("This shouldn't change", mModel1.mRrule);

        selection = EditEventHelper.REPEATS_DAILY;

        EditEventHelper.updateRecurrenceRule(selection, mModel1, weekStart);
        assertEquals("FREQ=DAILY;WKST=SU", mModel1.mRrule);

        selection = EditEventHelper.REPEATS_EVERY_WEEKDAY;

        EditEventHelper.updateRecurrenceRule(selection, mModel1, weekStart);
        assertEquals("FREQ=WEEKLY;WKST=SU;BYDAY=MO,TU,WE,TH,FR", mModel1.mRrule);

        selection = EditEventHelper.REPEATS_WEEKLY_ON_DAY;

        EditEventHelper.updateRecurrenceRule(selection, mModel1, weekStart);
        assertEquals("FREQ=WEEKLY;WKST=SU;BYDAY=FR", mModel1.mRrule);

        selection = EditEventHelper.REPEATS_MONTHLY_ON_DAY;

        EditEventHelper.updateRecurrenceRule(selection, mModel1, weekStart);
        assertEquals("FREQ=MONTHLY;WKST=SU;BYMONTHDAY=30", mModel1.mRrule);

        selection = EditEventHelper.REPEATS_MONTHLY_ON_DAY_COUNT;

        EditEventHelper.updateRecurrenceRule(selection, mModel1, weekStart);
        assertEquals("FREQ=MONTHLY;WKST=SU;BYDAY=-1FR", mModel1.mRrule);

        selection = EditEventHelper.REPEATS_YEARLY;

        EditEventHelper.updateRecurrenceRule(selection, mModel1, weekStart);
        assertEquals("FREQ=YEARLY;WKST=SU", mModel1.mRrule);
    }

    @Smoke
    @SmallTest
    public void testSetModelFromCursor() {
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);
        MatrixCursor c = new MatrixCursor(EditEventHelper.EVENT_PROJECTION);
        c.addRow(TEST_CURSOR_DATA);

        mModel1 = new CalendarEventModel();
        mModel2 = buildTestModel();

        EditEventHelper.setModelFromCursor(mModel1, c);
        assertEquals(mModel1, mModel2);

        TEST_CURSOR_DATA[EditEventHelper.EVENT_INDEX_ALL_DAY] = "0";
        c.close();
        c = new MatrixCursor(EditEventHelper.EVENT_PROJECTION);
        c.addRow(TEST_CURSOR_DATA);

        mModel2.mAllDay = false;
        mModel2.mStart = TEST_START; // UTC time

        EditEventHelper.setModelFromCursor(mModel1, c);
        assertEquals(mModel1, mModel2);

        TEST_CURSOR_DATA[EditEventHelper.EVENT_INDEX_RRULE] = null;
        c.close();
        c = new MatrixCursor(EditEventHelper.EVENT_PROJECTION);
        c.addRow(TEST_CURSOR_DATA);

        mModel2.mRrule = null;
        mModel2.mEnd = TEST_END;
        mModel2.mDuration = null;

        EditEventHelper.setModelFromCursor(mModel1, c);
        assertEquals(mModel1, mModel2);

        TEST_CURSOR_DATA[EditEventHelper.EVENT_INDEX_ALL_DAY] = "1";
        c.close();
        c = new MatrixCursor(EditEventHelper.EVENT_PROJECTION);
        c.addRow(TEST_CURSOR_DATA);

        mModel2.mAllDay = true;
        mModel2.mStart = TEST_START; // Monday, May 3rd, midnight
        mModel2.mEnd = TEST_END; // Tuesday, May 4th, midnight

        EditEventHelper.setModelFromCursor(mModel1, c);
        assertEquals(mModel1, mModel2);
    }

    @Smoke
    @SmallTest
    public void testGetContentValuesFromModel() {
        mActivity = buildTestContext();
        mHelper = new EditEventHelper(mActivity, null);
        mExpectedValues = buildTestValues();
        mModel1 = buildTestModel();

        ContentValues values = mHelper.getContentValuesFromModel(mModel1);
        assertEquals(mExpectedValues, values);

        mModel1.mRrule = null;
        mModel1.mEnd = TEST_END;

        mExpectedValues.put(Events.RRULE, (String) null);
        mExpectedValues.put(Events.DURATION, (String) null);
        mExpectedValues.put(Events.DTEND, TEST_END); // UTC time

        values = mHelper.getContentValuesFromModel(mModel1);
        assertEquals(mExpectedValues, values);

        mModel1.mAllDay = false;

        mExpectedValues.put(Events.ALL_DAY, 0);
        mExpectedValues.put(Events.DTSTART, TEST_START);
        mExpectedValues.put(Events.DTEND, TEST_END);
        // not an allday event so timezone isn't modified
        mExpectedValues.put(Events.EVENT_TIMEZONE, "UTC");

        values = mHelper.getContentValuesFromModel(mModel1);
        assertEquals(mExpectedValues, values);
    }

    @Smoke
    @SmallTest
    public void testExtractDomain() {
        String domain = EditEventHelper.extractDomain("test.email@gmail.com");
        assertEquals("gmail.com", domain);

        domain = EditEventHelper.extractDomain("bademail.no#$%at symbol");
        assertNull(domain);
    }

    private void addExpectedMinutes(ArrayList<ContentProviderOperation> expectedOps) {
        ContentProviderOperation.Builder b;
        mValues = new ContentValues();

        mValues.clear();
        mValues.put(Reminders.MINUTES, 5);
        mValues.put(Reminders.METHOD, Reminders.METHOD_DEFAULT);
        mValues.put(Reminders.EVENT_ID, TEST_EVENT_ID);
        b = ContentProviderOperation.newInsert(Reminders.CONTENT_URI).withValues(mValues);
        expectedOps.add(b.build());

        mValues.clear();
        mValues.put(Reminders.MINUTES, 10);
        mValues.put(Reminders.METHOD, Reminders.METHOD_DEFAULT);
        mValues.put(Reminders.EVENT_ID, TEST_EVENT_ID);
        b = ContentProviderOperation.newInsert(Reminders.CONTENT_URI).withValues(mValues);
        expectedOps.add(b.build());

        mValues.clear();
        mValues.put(Reminders.MINUTES, 15);
        mValues.put(Reminders.METHOD, Reminders.METHOD_DEFAULT);
        mValues.put(Reminders.EVENT_ID, TEST_EVENT_ID);
        b = ContentProviderOperation.newInsert(Reminders.CONTENT_URI).withValues(mValues);
        expectedOps.add(b.build());
    }

    private void addExpectedMinutesWithBackRef(ArrayList<ContentProviderOperation> expectedOps) {
        ContentProviderOperation.Builder b;
        mValues = new ContentValues();

        mValues.clear();
        mValues.put(Reminders.MINUTES, 5);
        mValues.put(Reminders.METHOD, Reminders.METHOD_DEFAULT);
        b = ContentProviderOperation.newInsert(Reminders.CONTENT_URI).withValues(mValues);
        b.withValueBackReference(Reminders.EVENT_ID, TEST_EVENT_INDEX_ID);
        expectedOps.add(b.build());

        mValues.clear();
        mValues.put(Reminders.MINUTES, 10);
        mValues.put(Reminders.METHOD, Reminders.METHOD_DEFAULT);
        b = ContentProviderOperation.newInsert(Reminders.CONTENT_URI).withValues(mValues);
        b.withValueBackReference(Reminders.EVENT_ID, TEST_EVENT_INDEX_ID);
        expectedOps.add(b.build());

        mValues.clear();
        mValues.put(Reminders.MINUTES, 15);
        mValues.put(Reminders.METHOD, Reminders.METHOD_DEFAULT);
        b = ContentProviderOperation.newInsert(Reminders.CONTENT_URI).withValues(mValues);
        b.withValueBackReference(Reminders.EVENT_ID, TEST_EVENT_INDEX_ID);
        expectedOps.add(b.build());
    }

    private static void assertEquals(ArrayList<ContentProviderOperation> expected,
            ArrayList<ContentProviderOperation> actual) {
        if (expected == null) {
            assertNull(actual);
        }
        int size = expected.size();

        assertEquals(size, actual.size());

        for (int i = 0; i < size; i++) {
            assertTrue("At index " + i + ", expected:\n" + String.valueOf(expected.get(i)) +
                    "\nActual:\n" + String.valueOf(actual.get(i)),
                    cpoEquals(expected.get(i), actual.get(i)));
        }

    }

    private static boolean cpoEquals(ContentProviderOperation cpo1, ContentProviderOperation cpo2) {
        if (cpo1 == null && cpo2 != null) {
            return false;
        }
        if (cpo1 == cpo2) {
            return true;
        }
        if (cpo2 == null) {
            return false;
        }

        // It turns out we can't trust the toString() of the ContentProviderOperations to be
        // consistent, so we have to do the comparison manually.
        //
        // Start by splitting by commas, so that we can compare each key-value pair individually.
        String[] operations1 = cpo1.toString().split(",");
        String[] operations2 = cpo2.toString().split(",");
        // The two numbers of operations must be equal.
        if (operations1.length != operations2.length) {
            return false;
        }
        // Iterate through the key-value pairs and separate out the key and value.
        // The value may be either a single string, or a series of further key-value pairs
        // that are separated by " ", with a "=" between the key and value.
        for (int i = 0; i < operations1.length; i++) {
            String operation1 = operations1[i];
            String operation2 = operations2[i];
            // Limit the array to length 2 in case a ":" appears in the value.
            String[] keyValue1 = operation1.split(":", 2);
            String[] keyValue2 = operation2.split(":", 2);
            // If the key doesn't match, return false.
            if (!keyValue1[0].equals(keyValue2[0])) {
                return false;
            }
            // First just check if the value matches up. If so, we're good to go.
            if (keyValue1[1].equals(keyValue2[1])) {
                continue;
            }
            // If not, we need to try splitting the value by " " and sorting those keyvalue pairs.
            // Note that these are trimmed first to ensure we're not thrown off by extra whitespace.
            String[] valueKeyValuePairs1 = keyValue1[1].trim().split(" ");
            String[] valueKeyValuePairs2 = keyValue2[1].trim().split(" ");
            // Sort the value's keyvalue pairs alphabetically, and now compare them to each other.
            Arrays.sort(valueKeyValuePairs1);
            Arrays.sort(valueKeyValuePairs2);
            for (int j = 0; j < valueKeyValuePairs1.length; j++) {
                if (!valueKeyValuePairs1[j].equals(valueKeyValuePairs2[j])) {
                    return false;
                }
            }
        }

        // If we make it all the way through without finding anything different, return true.
        return true;
    }

    // Generates a default model for testing. Should match up with
    // generateTestValues
    private CalendarEventModel buildTestModel() {
        CalendarEventModel model = new CalendarEventModel();
        model.mId = TEST_EVENT_ID;
        model.mTitle = "The_Question";
        model.mDescription = "Evaluating_Life_the_Universe_and_Everything";
        model.mLocation = "Earth_Mk2";
        model.mAllDay = true;
        model.mHasAlarm = false;
        model.mCalendarId = 2;
        model.mStart = TEST_START; // Monday, May 3rd, local Time
        model.mDuration = "P3652421990D";
        // The model uses the local timezone for allday
        model.mTimezone = "UTC";
        model.mRrule = "FREQ=DAILY;WKST=SU";
        model.mSyncId = "unique_per_calendar_stuff";
        model.mAvailability = 0;
        model.mAccessLevel = 2; // This is one less than the values written if >0
        model.mOwnerAccount = "steve@gmail.com";
        model.mHasAttendeeData = true;
        model.mOrganizer = "organizer@gmail.com";
        model.mIsOrganizer = false;
        model.mGuestsCanModify = false;
        model.mEventStatus = Events.STATUS_CONFIRMED;
        int displayColor = Utils.getDisplayColorFromColor(-2350809);
        model.setEventColor(displayColor);
        model.mCalendarAccountName = "steve.owner@gmail.com";
        model.mCalendarAccountType = "gmail.com";
        EventColorCache cache = new EventColorCache();
        cache.insertColor("steve.owner@gmail.com", "gmail.com", displayColor, 12);
        model.mEventColorCache = cache;
        model.mModelUpdatedWithEventCursor = true;
        return model;
    }

    // Generates a default set of values for testing. Should match up with
    // generateTestModel
    private ContentValues buildTestValues() {
        ContentValues values = new ContentValues();

        values.put(Events.CALENDAR_ID, 2L);
        values.put(Events.EVENT_TIMEZONE, "UTC"); // Allday events are converted
                                                  // to UTC for the db
        values.put(Events.TITLE, "The_Question");
        values.put(Events.ALL_DAY, 1);
        values.put(Events.DTSTART, TEST_START); // Monday, May 3rd, midnight UTC time
        values.put(Events.HAS_ATTENDEE_DATA, 1);

        values.put(Events.RRULE, "FREQ=DAILY;WKST=SU");
        values.put(Events.DURATION, "P3652421990D");
        values.put(Events.DTEND, (Long) null);
        values.put(Events.DESCRIPTION, "Evaluating_Life_the_Universe_and_Everything");
        values.put(Events.EVENT_LOCATION, "Earth_Mk2");
        values.put(Events.AVAILABILITY, 0);
        values.put(Events.STATUS, Events.STATUS_CONFIRMED);
        values.put(Events.ACCESS_LEVEL, 3); // This is one more than the model if
                                          // >0
        values.put(Events.EVENT_COLOR_KEY, 12);

        return values;
    }

    private ContentValues buildNonRecurringTestValues() {
        ContentValues values = buildTestValues();
        values.put(Events.DURATION, (String)null);
        values.put(Events.DTEND, TEST_END);
        values.put(Events.RRULE, (String)null);
        return values;
    }

    // This gets called by EditEventHelper to read or write the data
    class TestProvider extends ContentProvider {
        int index = 0;

        public TestProvider() {
        }

        @Override
        public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs,
                String orderBy) {
            return null;
        }

        @Override
        public int delete(Uri uri, String selection, String[] selectionArgs) {
            return 0;
        }

        @Override
        public String getType(Uri uri) {
            return null;
        }

        @Override
        public boolean onCreate() {
            return false;
        }

        @Override
        public Uri insert(Uri uri, ContentValues values) {
            // TODO Auto-generated method stub
            return null;
        }

        @Override
        public int update(Uri uri, ContentValues values, String selection, String[] selectionArgs) {
            // TODO Auto-generated method stub
            return 0;
        }
    }

}
