/*
 * Copyright (C) 2011 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 android.provider.cts;

import dalvik.annotation.TestTargetClass;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.provider.CalendarContract;
import android.provider.CalendarContract.Attendees;
import android.provider.CalendarContract.Calendars;
import android.provider.CalendarContract.Events;
import android.provider.CalendarContract.Instances;
import android.provider.CalendarContract.Reminders;
import android.test.InstrumentationTestCase;
import android.test.suitebuilder.annotation.*;
import android.text.format.DateUtils;
import android.text.format.Time;
import android.util.Log;

@TestTargetClass(android.provider.CalendarContract.class)
public class CalendarTest extends InstrumentationTestCase {

    private static final String TAG = "CalCTS";
    private static final String CTS_TEST_TYPE = "LOCAL";
    // @formatter:off
    private static final String[] TIME_ZONES = new String[] {
            "UTC",
            "America/Los_Angeles",
            "Asia/Beirut",
            "Pacific/Auckland", };
    // @formatter:on

    private static final String SQL_WHERE_ID = Events._ID + "=?";
    private static final String SQL_WHERE_CALENDAR_ID = Events.CALENDAR_ID + "=?";

    private ContentResolver mContentResolver;

    /** If set, log verbose instance info when running recurrence tests. */
    private static final boolean DEBUG_RECURRENCE = false;

    private static class CalendarHelper {

        // @formatter:off
        public static final String[] CALENDARS_SYNC_PROJECTION = new String[] {
                Calendars._ID,
                Calendars.ACCOUNT_NAME,
                Calendars.ACCOUNT_TYPE,
                Calendars._SYNC_ID,
                Calendars.CAL_SYNC7,
                Calendars.CAL_SYNC8,
                Calendars.DIRTY,
                Calendars.NAME,
                Calendars.CALENDAR_DISPLAY_NAME,
                Calendars.CALENDAR_COLOR,
                Calendars.CALENDAR_ACCESS_LEVEL,
                Calendars.VISIBLE,
                Calendars.SYNC_EVENTS,
                Calendars.CALENDAR_LOCATION,
                Calendars.CALENDAR_TIME_ZONE,
                Calendars.OWNER_ACCOUNT,
                Calendars.CAN_ORGANIZER_RESPOND,
                Calendars.CAN_MODIFY_TIME_ZONE,
                Calendars.MAX_REMINDERS,
                Calendars.DELETED,
                Calendars.CAL_SYNC1,
                Calendars.CAL_SYNC2,
                Calendars.CAL_SYNC3,
                Calendars.CAL_SYNC4,
                Calendars.CAL_SYNC5,
                Calendars.CAL_SYNC6,
                };
        // @formatter:on

        private CalendarHelper() {}     // do not instantiate this class

        static String generateCalendarOwnerEmail(String account) {
            return "OWNER_" + account + "@example.com";
        }

        /**
         * Creates a new set of values for creating a single calendar with every
         * field.
         *
         * @param account The account name to create this calendar with
         * @param seed A number used to generate the values
         * @return A complete set of values for the calendar
         */
        public static ContentValues getNewCalendarValues(
                String account, int seed) {
            String seedString = Long.toString(seed);
            ContentValues values = new ContentValues();
            values.put(Calendars.ACCOUNT_TYPE, CTS_TEST_TYPE);

            values.put(Calendars.ACCOUNT_NAME, account);
            values.put(Calendars._SYNC_ID, "SYNC_ID:" + seedString);
            values.put(Calendars.CAL_SYNC7, "SYNC_V:" + seedString);
            values.put(Calendars.CAL_SYNC8, "SYNC_TIME:" + seedString);
            values.put(Calendars.DIRTY, 0);
            values.put(Calendars.OWNER_ACCOUNT, generateCalendarOwnerEmail(account));

            values.put(Calendars.NAME, seedString);
            values.put(Calendars.CALENDAR_DISPLAY_NAME, "DISPLAY_" + seedString);

            values.put(Calendars.CALENDAR_ACCESS_LEVEL, (seed % 8) * 100);

            values.put(Calendars.CALENDAR_COLOR, 0xff000000 + seed);
            values.put(Calendars.VISIBLE, seed % 2);
            values.put(Calendars.SYNC_EVENTS, 1);   // must be 1 for recurrence expansion
            values.put(Calendars.CALENDAR_LOCATION, "LOCATION:" + seedString);
            values.put(Calendars.CALENDAR_TIME_ZONE, TIME_ZONES[seed % TIME_ZONES.length]);
            values.put(Calendars.CAN_ORGANIZER_RESPOND, seed % 2);
            values.put(Calendars.CAN_MODIFY_TIME_ZONE, seed % 2);
            values.put(Calendars.MAX_REMINDERS, seed);
            values.put(Calendars.CAL_SYNC1, "SYNC1:" + seedString);
            values.put(Calendars.CAL_SYNC2, "SYNC2:" + seedString);
            values.put(Calendars.CAL_SYNC3, "SYNC3:" + seedString);
            values.put(Calendars.CAL_SYNC4, "SYNC4:" + seedString);
            values.put(Calendars.CAL_SYNC5, "SYNC5:" + seedString);
            values.put(Calendars.CAL_SYNC6, "SYNC6:" + seedString);

            return values;
        }

        /**
         * Creates a set of values with just the updates and modifies the
         * original values to the expected values
         */
        public static ContentValues getUpdateCalendarValuesWithOriginal(
                ContentValues original, int seed) {
            ContentValues values = new ContentValues();
            String seedString = Long.toString(seed);

            values.put(Calendars.CALENDAR_DISPLAY_NAME, "DISPLAY_" + seedString);
            values.put(Calendars.CALENDAR_COLOR, 0xff000000 + seed);
            values.put(Calendars.VISIBLE, seed % 2);
            values.put(Calendars.SYNC_EVENTS, seed % 2);

            original.putAll(values);
            original.put(Calendars.DIRTY, 1);

            return values;
        }

        public static int deleteCalendarById(ContentResolver resolver, long id) {
            return resolver.delete(Calendars.CONTENT_URI, Calendars._ID + "=?",
                    new String[] { Long.toString(id) });
        }

        public static int deleteCalendarByAccount(ContentResolver resolver, String account) {
            return resolver.delete(Calendars.CONTENT_URI, Calendars.ACCOUNT_NAME + "=?",
                    new String[] { account });
        }

        public static Cursor getCalendarsByAccount(ContentResolver resolver, String account) {
            String selection = Calendars.ACCOUNT_TYPE + "=?";
            String[] selectionArgs;
            if (account != null) {
                selection += " AND " + Calendars.ACCOUNT_NAME + "=?";
                selectionArgs = new String[2];
                selectionArgs[1] = account;
            } else {
                selectionArgs = new String[1];
            }
            selectionArgs[0] = CTS_TEST_TYPE;

            return resolver.query(Calendars.CONTENT_URI, CALENDARS_SYNC_PROJECTION, selection,
                    selectionArgs, null);
        }
    }

    // @formatter:off
    private static class EventHelper {
        public static final String[] EVENTS_PROJECTION = new String[] {
            Events._ID,
            Events.ACCOUNT_NAME,
            Events.ACCOUNT_TYPE,
            Events.OWNER_ACCOUNT,
            // Events.ORGANIZER_CAN_RESPOND, from Calendars
            // Events.CAN_CHANGE_TZ, from Calendars
            // Events.MAX_REMINDERS, from Calendars
            Events.CALENDAR_ID,
            // Events.CALENDAR_DISPLAY_NAME, from Calendars
            // Events.CALENDAR_COLOR, from Calendars
            // Events.CALENDAR_ACL, from Calendars
            // Events.CALENDAR_VISIBLE, from Calendars
            Events.SYNC_DATA3,
            Events.SYNC_DATA6,
            Events.TITLE,
            Events.EVENT_LOCATION,
            Events.DESCRIPTION,
            Events.STATUS,
            Events.SELF_ATTENDEE_STATUS,
            Events.DTSTART,
            Events.DTEND,
            Events.EVENT_TIMEZONE,
            Events.EVENT_END_TIMEZONE,
            Events.DURATION,
            Events.ALL_DAY,
            Events.ACCESS_LEVEL,
            Events.AVAILABILITY,
            Events.HAS_ALARM,
            Events.HAS_EXTENDED_PROPERTIES,
            Events.RRULE,
            Events.RDATE,
            Events.EXRULE,
            Events.EXDATE,
            Events.ORIGINAL_ID,
            Events.ORIGINAL_SYNC_ID,
            Events.ORIGINAL_INSTANCE_TIME,
            Events.ORIGINAL_ALL_DAY,
            Events.LAST_DATE,
            Events.HAS_ATTENDEE_DATA,
            Events.GUESTS_CAN_MODIFY,
            Events.GUESTS_CAN_INVITE_OTHERS,
            Events.GUESTS_CAN_SEE_GUESTS,
            Events.ORGANIZER,
            Events.DELETED,
            Events._SYNC_ID,
            Events.SYNC_DATA4,
            Events.SYNC_DATA5,
            Events.DIRTY,
            Events.SYNC_DATA8,
            Events.SYNC_DATA2, // Events.SYNC_DATA1
            // Events.SYNC_DATA2
            // Events.SYNC_DATA3
            // Events.SYNC_DATA4
        };
        // @formatter:on

        private EventHelper() {}    // do not instantiate this class

        /**
         * Constructs a set of name/value pairs that can be used to create a Calendar event.
         * Various fields are generated from the seed value.
         */
        public static ContentValues getNewEventValues(
                String account, int seed, long calendarId, boolean asSyncAdapter) {
            String seedString = Long.toString(seed);
            ContentValues values = new ContentValues();
            values.put(Events.ORGANIZER, "ORGANIZER:" + seedString);

            values.put(Events.TITLE, "TITLE:" + seedString);
            values.put(Events.EVENT_LOCATION, "LOCATION_" + seedString);

            values.put(Events.CALENDAR_ID, calendarId);

            values.put(Events.DESCRIPTION, "DESCRIPTION:" + seedString);
            values.put(Events.STATUS, seed % 3);

            values.put(Events.DTSTART, seed);
            values.put(Events.DTEND, seed + DateUtils.HOUR_IN_MILLIS);
            values.put(Events.EVENT_TIMEZONE, TIME_ZONES[seed % TIME_ZONES.length]);
            // values.put(Events.EVENT_TIMEZONE2, TIME_ZONES[(seed +1) %
            // TIME_ZONES.length]);
            if ((seed % 2) == 0) {
                // Either set to zero, or leave unset to get default zero.
                // Must be 0 or dtstart/dtend will get adjusted.
                values.put(Events.ALL_DAY, 0);
            }
            values.put(Events.ACCESS_LEVEL, seed % 4);
            values.put(Events.AVAILABILITY, seed % 2);
            values.put(Events.HAS_ALARM, seed % 2);
            values.put(Events.HAS_EXTENDED_PROPERTIES, seed % 2);
            values.put(Events.HAS_ATTENDEE_DATA, seed % 2);
            values.put(Events.GUESTS_CAN_MODIFY, seed % 2);
            values.put(Events.GUESTS_CAN_INVITE_OTHERS, seed % 2);
            values.put(Events.GUESTS_CAN_SEE_GUESTS, seed % 2);

            if (asSyncAdapter) {
                values.put(Events._SYNC_ID, "SYNC_ID:" + seedString);
                values.put(Events.SYNC_DATA4, "SYNC_V:" + seedString);
                values.put(Events.SYNC_DATA5, "SYNC_TIME:" + seedString);
                values.put(Events.SYNC_DATA3, "HTML:" + seedString);
                values.put(Events.SYNC_DATA6, "COMMENTS:" + seedString);
                values.put(Events.DIRTY, 0);
                values.put(Events.SYNC_DATA8, "0");
            } else {
                // only the sync adapter can set the DIRTY flag
                //values.put(Events.DIRTY, 1);
            }
            // values.put(Events.SYNC1, "SYNC1:" + seedString);
            // values.put(Events.SYNC2, "SYNC2:" + seedString);
            // values.put(Events.SYNC3, "SYNC3:" + seedString);
            // values.put(Events.SYNC4, "SYNC4:" + seedString);
            // values.put(Events.SYNC5, "SYNC5:" + seedString);
//            Events.RRULE,
//            Events.RDATE,
//            Events.EXRULE,
//            Events.EXDATE,
//            // Events.ORIGINAL_ID
//            Events.ORIGINAL_EVENT, // rename ORIGINAL_SYNC_ID
//            Events.ORIGINAL_INSTANCE_TIME,
//            Events.ORIGINAL_ALL_DAY,

            return values;
        }

        /**
         * Constructs a set of name/value pairs that can be used to create a recurring
         * Calendar event.
         *
         * A duration of "P1D" is treated as an all-day event.
         *
         * @param startWhen Starting date/time in RFC 3339 format
         * @param duration Event duration, in RFC 2445 duration format
         * @param rrule Recurrence rule
         * @return name/value pairs to use when creating event
         */
        public static ContentValues getNewRecurringEventValues(String account, int seed,
                long calendarId, boolean asSyncAdapter, String startWhen, String duration,
                String rrule) {

            // Set up some general stuff.
            ContentValues values = getNewEventValues(account, seed, calendarId, asSyncAdapter);

            // Replace the DTSTART field.
            String timeZone = values.getAsString(Events.EVENT_TIMEZONE);
            Time time = new Time(timeZone);
            time.parse3339(startWhen);
            values.put(Events.DTSTART, time.toMillis(false));

            // Add in the recurrence-specific fields, and drop DTEND.
            values.put(Events.RRULE, rrule);
            values.put(Events.DURATION, duration);
            values.remove(Events.DTEND);

            return values;
        }

        /**
         * Constructs the basic name/value pairs required for an exception to a recurring event.
         *
         * @param instanceStartMillis The start time of the instance
         * @return name/value pairs to use when creating event
         */
        public static ContentValues getNewExceptionValues(long instanceStartMillis) {
            ContentValues values = new ContentValues();
            values.put(Events.ORIGINAL_INSTANCE_TIME, instanceStartMillis);

            return values;
        }

        public static ContentValues getUpdateEventValuesWithOriginal(ContentValues original,
                int seed, boolean asSyncAdapter) {
            String seedString = Long.toString(seed);
            ContentValues values = new ContentValues();

            values.put(Events.TITLE, "TITLE:" + seedString);
            values.put(Events.EVENT_LOCATION, "LOCATION_" + seedString);
            values.put(Events.DESCRIPTION, "DESCRIPTION:" + seedString);
            values.put(Events.STATUS, seed % 3);

            values.put(Events.DTSTART, seed);
            values.put(Events.DTEND, seed + DateUtils.HOUR_IN_MILLIS);
            values.put(Events.EVENT_TIMEZONE, TIME_ZONES[seed % TIME_ZONES.length]);
            // values.put(Events.EVENT_TIMEZONE2, TIME_ZONES[(seed +1) %
            // TIME_ZONES.length]);
            values.put(Events.ACCESS_LEVEL, seed % 4);
            values.put(Events.AVAILABILITY, seed % 2);
            values.put(Events.HAS_ALARM, seed % 2);
            values.put(Events.HAS_EXTENDED_PROPERTIES, seed % 2);
            values.put(Events.HAS_ATTENDEE_DATA, seed % 2);
            values.put(Events.GUESTS_CAN_MODIFY, seed % 2);
            values.put(Events.GUESTS_CAN_INVITE_OTHERS, seed % 2);
            values.put(Events.GUESTS_CAN_SEE_GUESTS, seed % 2);
            if (asSyncAdapter) {
                values.put(Events._SYNC_ID, "SYNC_ID:" + seedString);
                values.put(Events.SYNC_DATA4, "SYNC_V:" + seedString);
                values.put(Events.SYNC_DATA5, "SYNC_TIME:" + seedString);
                values.put(Events.DIRTY, 0);
            }
            original.putAll(values);
            return values;
        }

        public static void addDefaultReadOnlyValues(ContentValues values, String account,
                boolean asSyncAdapter) {
            values.put(Events.SELF_ATTENDEE_STATUS, Events.STATUS_TENTATIVE);
            values.put(Events.DELETED, 0);
            values.put(Events.DIRTY, asSyncAdapter ? 0 : 1);
            values.put(Events.OWNER_ACCOUNT, CalendarHelper.generateCalendarOwnerEmail(account));
            values.put(Events.ACCOUNT_TYPE, CTS_TEST_TYPE);
            values.put(Events.ACCOUNT_NAME, account);
        }

        /**
         * Generates a RFC2445-format duration string.
         */
        private static String generateDurationString(long durationMillis, boolean isAllDay) {
            long durationSeconds = durationMillis / 1000;

            // The server may react differently to an all-day event specified as "P1D" than
            // it will to "PT86400S"; see b/1594638.
            if (isAllDay && (durationSeconds % 86400) == 0) {
                return "P" + durationSeconds / 86400 + "D";
            } else {
                return "PT" + durationSeconds + "S";
            }
        }

        /**
         * Deletes the event, and updates the values.
         * @param resolver The resolver to issue the query against.
         * @param uri The deletion URI.
         * @param values Set of values to update (sets DELETED and DIRTY).
         * @return The number of rows modified.
         */
        public static int deleteEvent(ContentResolver resolver, Uri uri, ContentValues values) {
            values.put(Events.DELETED, 1);
            values.put(Events.DIRTY, 1);
            return resolver.delete(uri, null, null);
        }

        public static int deleteEventAsSyncAdapter(ContentResolver resolver, Uri uri,
                String account) {
            Uri syncUri = asSyncAdapter(uri, account, CTS_TEST_TYPE);
            return resolver.delete(syncUri, null, null);
        }

        public static Cursor getEventsByAccount(ContentResolver resolver, String account) {
            String selection = Calendars.ACCOUNT_TYPE + "=?";
            String[] selectionArgs;
            if (account != null) {
                selection += " AND " + Calendars.ACCOUNT_NAME + "=?";
                selectionArgs = new String[2];
                selectionArgs[1] = account;
            } else {
                selectionArgs = new String[1];
            }
            selectionArgs[0] = CTS_TEST_TYPE;
            return resolver.query(Events.CONTENT_URI, EVENTS_PROJECTION, selection, selectionArgs,
                    null);
        }

        public static Cursor getEventByUri(ContentResolver resolver, Uri uri) {
            return resolver.query(uri, EVENTS_PROJECTION, null, null, null);
        }
    }

    static Uri asSyncAdapter(Uri uri, String account, String accountType) {
        return uri.buildUpon()
                .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,
                        "true")
                .appendQueryParameter(Calendars.ACCOUNT_NAME, account)
                .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build();
    }

    @Override
    protected void setUp() throws Exception {
        super.setUp();
        mContentResolver = getInstrumentation().getTargetContext().getContentResolver();
        // IContentProvider provider = mContentResolver.acquireProvider(Calendar.AUTHORITY);
        // mBuilder = new ContactsContract_TestDataBuilder(provider);
    }

    @MediumTest
    public void testCalendarCreationAndDeletion() {
        String account = "cc1_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);
        long id = createAndVerifyCalendar(account, seed++, null);

        removeAndVerifyCalendar(account, id);
    }

    /**
     * Tests whether the default projections work.  We don't need to have any data in
     * the calendar, since it's testing the database schema.
     */
    @MediumTest
    public void testDefaultProjections() {
        String account = "dproj_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);
        long id = createAndVerifyCalendar(account, seed++, null);

        Cursor c;
        Uri uri;
        // Calendars
        c = mContentResolver.query(Calendars.CONTENT_URI, null, null, null, null);
        c.close();
        // Events
        c = mContentResolver.query(Events.CONTENT_URI, null, null, null, null);
        c.close();
        // Instances
        uri = Uri.withAppendedPath(Instances.CONTENT_URI, "0/1");
        c = mContentResolver.query(uri, null, null, null, null);
        c.close();
        // Attendees
        c = mContentResolver.query(Attendees.CONTENT_URI, null, null, null, null);
        c.close();
        // Reminders (only REMINDERS_ID currently uses default projection)
        uri = ContentUris.withAppendedId(Reminders.CONTENT_URI, 0);
        c = mContentResolver.query(uri, null, null, null, null);
        c.close();
        // CalendarAlerts
        c = mContentResolver.query(CalendarContract.CalendarAlerts.CONTENT_URI,
                null, null, null, null);
        c.close();
        // CalendarCache
        c = mContentResolver.query(CalendarContract.CalendarCache.URI,
                null, null, null, null);
        c.close();
        // CalendarEntity
        c = mContentResolver.query(CalendarContract.CalendarEntity.CONTENT_URI,
                null, null, null, null);
        c.close();
        // EventEntities
        c = mContentResolver.query(CalendarContract.EventsEntity.CONTENT_URI,
                null, null, null, null);
        c.close();
        // EventDays
        uri = Uri.withAppendedPath(CalendarContract.EventDays.CONTENT_URI, "1/2");
        c = mContentResolver.query(uri, null, null, null, null);
        c.close();
        // ExtendedProperties
        c = mContentResolver.query(CalendarContract.ExtendedProperties.CONTENT_URI,
                null, null, null, null);
        c.close();

        removeAndVerifyCalendar(account, id);
    }

    @MediumTest
    public void testCalendarUpdateAsApp() {
        String account = "cu1_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create a calendar
        ContentValues values = CalendarHelper.getNewCalendarValues(account, seed);
        long id = createAndVerifyCalendar(account, seed++, values);

        Uri uri = ContentUris.withAppendedId(Calendars.CONTENT_URI, id);

        // Update the calendar using the direct Uri
        ContentValues updateValues = CalendarHelper.getUpdateCalendarValuesWithOriginal(
                values, seed++);
        assertEquals(1, mContentResolver.update(uri, updateValues, null, null));

        verifyCalendar(account, values, id);

        // Update the calendar using selection + args
        String selection = Calendars._ID + "=?";
        String[] selectionArgs = new String[] { Long.toString(id) };

        updateValues = CalendarHelper.getUpdateCalendarValuesWithOriginal(values, seed++);

        assertEquals(1, mContentResolver.update(
                Calendars.CONTENT_URI, updateValues, selection, selectionArgs));

        verifyCalendar(account, values, id);

        removeAndVerifyCalendar(account, id);
    }

    // TODO test calendar updates as sync adapter

    private void verifyEvent(ContentValues values, long eventId) {
        Uri eventUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId);
        // Verify
        Cursor c = mContentResolver
                .query(eventUri, EventHelper.EVENTS_PROJECTION, null, null, null);
        assertEquals(1, c.getCount());
        assertTrue(c.moveToFirst());
        assertEquals(eventId, c.getLong(0));
        for (String key : values.keySet()) {
            int index = c.getColumnIndex(key);
            assertEquals(key, values.getAsString(key), c.getString(index));
        }
        c.close();
    }

    @MediumTest
    public void testEventCreationAndDeletion() {
        String account = "ec1_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar and event
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        ContentValues eventValues = EventHelper
                .getNewEventValues(account, seed++, calendarId, true);
        long eventId = createAndVerifyEvent(account, seed, calendarId, true, eventValues);

        Uri eventUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId);

        removeAndVerifyEvent(eventUri, eventValues, account);

        removeAndVerifyCalendar(account, calendarId);
    }

    @MediumTest
    public void testEventUpdateAsApp() {
        String account = "em1_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create event as sync adapter
        ContentValues eventValues = EventHelper
                .getNewEventValues(account, seed++, calendarId, true);
        long eventId = createAndVerifyEvent(account, seed, calendarId, true, eventValues);

        // Update event as app
        Uri eventUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId);

        ContentValues updateValues = EventHelper.getUpdateEventValuesWithOriginal(eventValues,
                seed++, false);
        assertEquals(1, mContentResolver.update(eventUri, updateValues, null, null));
        updateValues.put(Events.DIRTY, 1);      // provider should have marked as dirty
        verifyEvent(updateValues, eventId);

        removeAndVerifyEvent(eventUri, eventValues, account);

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Tests update of multiple events with a single update call.
     */
    @MediumTest
    public void testBulkUpdate() {
        String account = "bup_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);
        String calendarIdStr = String.valueOf(calendarId);

        // Create events
        ContentValues eventValues;
        eventValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        long eventId1 = createAndVerifyEvent(account, seed, calendarId, true, eventValues);

        eventValues = EventHelper.getNewEventValues(account, seed++, calendarId, true);
        long eventId2 = createAndVerifyEvent(account, seed, calendarId, true, eventValues);

        // Update the "description" field in all events in this calendar.
        String newDescription = "bulk edit";
        ContentValues updateValues = new ContentValues();
        updateValues.put(Events.DESCRIPTION, newDescription);

        // Must be sync adapter to do a bulk update.
        Uri uri = asSyncAdapter(Events.CONTENT_URI, account, CTS_TEST_TYPE);
        int count = mContentResolver.update(uri, updateValues, SQL_WHERE_CALENDAR_ID,
                new String[] { calendarIdStr });

        // Check to see if the changes went through.
        Uri eventUri = Events.CONTENT_URI;
        Cursor c = mContentResolver.query(eventUri, new String[] { Events.DESCRIPTION },
                SQL_WHERE_CALENDAR_ID, new String[] { calendarIdStr }, null);
        assertEquals(2, c.getCount());
        while (c.moveToNext()) {
            assertEquals(newDescription, c.getString(0));
        }
        c.close();
    }

    /**
     * Tests the content provider's enforcement of restrictions on who is allowed to modify
     * specific columns in a Calendar.
     * <p>
     * This attempts to create a new row in the Calendar table, specifying one restricted
     * column at a time.
     */
    @MediumTest
    public void testSyncOnlyInsertEnforcement() {
        // These operations should not succeed, so there should be nothing to clean up after.
        // TODO: this should be a new event augmented with an illegal column, not a single
        //       column.  Otherwise we might be tripping over a "DTSTART must exist" test.
        ContentValues vals = new ContentValues();
        for (int i = 0; i < Calendars.SYNC_WRITABLE_COLUMNS.length; i++) {
            boolean threw = false;
            try {
                vals.clear();
                vals.put(Calendars.SYNC_WRITABLE_COLUMNS[i], "1");
                mContentResolver.insert(Calendars.CONTENT_URI, vals);
            } catch (IllegalArgumentException e) {
                threw = true;
            }
            assertTrue("Only sync adapter should be allowed to insert "
                    + Calendars.SYNC_WRITABLE_COLUMNS[i], threw);
        }
    }

    /**
     * Tests creation of a recurring event.
     * <p>
     * This (and the other recurrence tests) uses dates well in the past to reduce the likelihood
     * of encountering non-test recurring events.  (Ideally we would select events associated
     * with a specific calendar.)  With dates well in the past, it's also important to have a
     * fixed maximum count or end date; otherwise, if the metadata min/max instance values are
     * large enough, the recurrence recalculation processor could get triggered on an insert or
     * update and bump up against the 2000-instance limit.
     *
     * TODO: need some allDay tests
     */
    @MediumTest
    public void testRecurrence() {
        String account = "re_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create recurring event
        ContentValues eventValues = EventHelper.getNewRecurringEventValues(account, seed++,
                calendarId, true, "2003-08-05T09:00:00", "PT1H",
                "FREQ=WEEKLY;INTERVAL=2;COUNT=4;BYDAY=TU,SU;WKST=SU");
        long eventId = createAndVerifyEvent(account, seed, calendarId, true, eventValues);
        //Log.d(TAG, "+++ basic recurrence eventId is " + eventId);

        // Check to see if we have the expected number of instances
        String timeZone = eventValues.getAsString(Events.EVENT_TIMEZONE);
        int instanceCount = getInstanceCount(timeZone, "2003-08-05T00:00:00",
                "2003-08-31T11:59:59");
        if (false) {
            Cursor instances = getInstances(timeZone, "2003-08-05T00:00:00", "2003-08-31T11:59:59",
                    new String[] { Instances.BEGIN });
            dumpInstances(instances, timeZone, "initial");
        }
        assertEquals("recurrence instance count", 4, instanceCount);

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Tests conversion of a regular event to a recurring event.
     */
    @MediumTest
    public void testConversionToRecurring() {
        String account = "reconv_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar and event
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        ContentValues eventValues = EventHelper
                .getNewEventValues(account, seed++, calendarId, true);
        long eventId = createAndVerifyEvent(account, seed, calendarId, true, eventValues);

        long dtstart = eventValues.getAsLong(Events.DTSTART);
        long dtend = eventValues.getAsLong(Events.DTEND);
        long durationSecs = (dtend - dtstart) / 1000;

        ContentValues updateValues = new ContentValues();
        updateValues.put(Events.RRULE, "FREQ=WEEKLY");   // recurs forever
        updateValues.put(Events.DURATION, "P" + durationSecs + "S");
        updateValues.putNull(Events.DTEND);

        // Issue update; do it as app instead of sync adapter to exercise that path.
        updateAndVerifyEvent(account, calendarId, eventId, false, updateValues);

        // Make sure LAST_DATE got nulled out by our infinitely repeating sequence.
        Uri eventUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId);
        Cursor c = mContentResolver.query(eventUri, new String[] { Events.LAST_DATE },
                null, null, null);
        assertEquals(1, c.getCount());
        assertTrue(c.moveToFirst());
        assertNull(c.getString(0));
        c.close();

        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Tests creation of a recurring event with single-instance exceptions.
     */
    @MediumTest
    public void testSingleRecurrenceExceptions() {
        String account = "rex_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create recurring event.
        ContentValues eventValues = EventHelper.getNewRecurringEventValues(account, seed++,
                calendarId, true, "1999-03-28T09:00:00", "PT1H", "FREQ=WEEKLY;WKST=SU;COUNT=100");
        long eventId = createAndVerifyEvent(account, seed++, calendarId, true, eventValues);

        // Add some attendees and reminders.
        addAttendees(account, eventId, seed);
        addReminders(account, eventId, seed);

        // Select a period that gives us 5 instances.
        String timeZone = eventValues.getAsString(Events.EVENT_TIMEZONE);
        String testStart = "1999-03-28T00:00:00";
        String testEnd = "1999-04-25T23:59:59";
        String[] projection = { Instances.BEGIN, Instances.START_MINUTE, Instances.END_MINUTE };

        Cursor instances = getInstances(timeZone, testStart, testEnd, projection);
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "initial");
        }

        assertEquals("initial recurrence instance count", 5, instances.getCount());

        /*
         * Advance the start time of a few instances, and verify.
         */

        // Leave first instance alone.
        instances.moveToPosition(1);

        long startMillis;
        ContentValues excepValues;

        // Advance the start time of the 2nd instance.
        startMillis = instances.getLong(0);
        excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.DTSTART, startMillis + 3600*1000);
        long excepEventId2 = createAndVerifyException(account, eventId, excepValues, true);
        instances.moveToNext();

        // Advance the start time of the 3rd instance.
        startMillis = instances.getLong(0);
        excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.DTSTART, startMillis + 3600*1000*2);
        long excepEventId3 = createAndVerifyException(account, eventId, excepValues, true);
        instances.moveToNext();

        // Cancel the 4th instance.
        startMillis = instances.getLong(0);
        excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.STATUS, Events.STATUS_CANCELED);
        long excepEventId4 = createAndVerifyException(account, eventId, excepValues, true);
        instances.moveToNext();

        // TODO: try to modify a non-existent instance.

        instances.close();

        // TODO: compare Reminders, Attendees, ExtendedProperties on one of the exception events

        // Re-query the instances and figure out if they look right.
        instances = getInstances(timeZone, testStart, testEnd, projection);
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "with DTSTART exceptions");
        }
        assertEquals("exceptional recurrence instance count", 4, instances.getCount());

        long prevMinute = -1;
        while (instances.moveToNext()) {
            // expect the start times for each entry to be different from the previous entry
            long startMinute = instances.getLong(1);
            assertTrue("instance start times are different", startMinute != prevMinute);

            prevMinute = startMinute;
        }
        instances.close();


        // Delete all of our exceptions, and verify.
        int deleteCount = 0;
        deleteCount += deleteException(account, eventId, excepEventId2);
        deleteCount += deleteException(account, eventId, excepEventId3);
        deleteCount += deleteException(account, eventId, excepEventId4);
        assertEquals("events deleted", 3, deleteCount);

        // Re-query the instances and figure out if they look right.
        instances = getInstances(timeZone, testStart, testEnd, projection);
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "post exception deletion");
        }
        assertEquals("post-exception deletion instance count", 5, instances.getCount());

        prevMinute = -1;
        while (instances.moveToNext()) {
            // expect the start times for each entry to be the same
            long startMinute = instances.getLong(1);
            if (prevMinute != -1) {
                assertEquals("instance start times are the same", startMinute, prevMinute);
            }
            prevMinute = startMinute;
        }
        instances.close();

        /*
         * Repeat the test, this time modifying DURATION.
         */

        instances = getInstances(timeZone, testStart, testEnd, projection);
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "initial");
        }

        assertEquals("initial recurrence instance count", 5, instances.getCount());

        // Leave first instance alone.
        instances.moveToPosition(1);

        // Advance the end time of the 2nd instance.
        startMillis = instances.getLong(0);
        excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.DURATION, "P" + 3600*2 + "S");
        excepEventId2 = createAndVerifyException(account, eventId, excepValues, true);
        instances.moveToNext();

        // Advance the end time of the 3rd instance, and change the self-attendee status.
        startMillis = instances.getLong(0);
        excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.DURATION, "P" + 3600*3 + "S");
        excepValues.put(Events.SELF_ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_DECLINED);
        excepEventId3 = createAndVerifyException(account, eventId, excepValues, true);
        instances.moveToNext();

        // Advance the start time of the 4th instance, which will also advance the end time.
        startMillis = instances.getLong(0);
        excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.DTSTART, startMillis + 3600*1000);
        excepEventId4 = createAndVerifyException(account, eventId, excepValues, true);
        instances.moveToNext();

        instances.close();

        // TODO: make sure the selfAttendeeStatus change took

        // Re-query the instances and figure out if they look right.
        instances = getInstances(timeZone, testStart, testEnd, projection);
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "with DURATION exceptions");
        }
        assertEquals("exceptional recurrence instance count", 5, instances.getCount());

        prevMinute = -1;
        while (instances.moveToNext()) {
            // expect the start times for each entry to be different from the previous entry
            long endMinute = instances.getLong(2);
            assertTrue("instance end times are different", endMinute != prevMinute);

            prevMinute = endMinute;
        }
        instances.close();

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Tests creation of a simple recurrence exception when not pretending to be the sync
     * adapter.  One significant consequence is that we don't set the _sync_id field in the
     * events, which affects how the provider correlates recurrences and exceptions.
     */
    @MediumTest
    public void testNonAdapterRecurrenceExceptions() {
        String account = "rena_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Generate recurring event, with "asSyncAdapter" set to false.
        ContentValues eventValues = EventHelper.getNewRecurringEventValues(account, seed++,
                calendarId, false, "1991-02-03T12:00:00", "PT1H", "FREQ=DAILY;WKST=SU;COUNT=10");

        // Select a period that gives us 3 instances.
        String timeZone = eventValues.getAsString(Events.EVENT_TIMEZONE);
        String testStart = "1991-02-03T00:00:00";
        String testEnd = "1991-02-05T23:59:59";
        String[] projection = { Instances.BEGIN, Instances.START_MINUTE };

        // Expand the bounds of the instances table so we expand future events as they are added.
        expandInstanceRange(account, calendarId, testStart, testEnd, timeZone);

        // Create the event in the database.
        long eventId = createAndVerifyEvent(account, seed++, calendarId, false, eventValues);
        assertTrue(eventId >= 0);

        // Add some attendees.
        addAttendees(account, eventId, seed);

        Cursor instances = getInstances(timeZone, testStart, testEnd, projection);
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "initial");
        }
        assertEquals("initial recurrence instance count", 3, instances.getCount());

        /*
         * Alter the attendee status of the second event.  This should cause the instances to
         * be updated, replacing the previous 2nd instance with the exception instance.  If the
         * code is broken we'll see four instances (because the original instance didn't get
         * removed) or one instance (because the code correctly deleted all related events but
         * couldn't correlate the exception with its original recurrence).
         */

        // Leave first instance alone.
        instances.moveToPosition(1);

        long startMillis;
        ContentValues excepValues;

        // Advance the start time of the 2nd instance.
        startMillis = instances.getLong(0);
        excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.SELF_ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_DECLINED);
        long excepEventId2 = createAndVerifyException(account, eventId, excepValues, false);
        instances.moveToNext();

        instances.close();

        // Re-query the instances and figure out if they look right.
        instances = getInstances(timeZone, testStart, testEnd, projection);
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "with exceptions");
        }

        // TODO: this test currently fails due to limitations in the provider
        //assertEquals("exceptional recurrence instance count", 3, instances.getCount());

        instances.close();

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Tests creation of a simple recurrence exception where the exception is created first.
     * Simulates out-of-order delivery from the server.
     * <p>
     * We can't use the /exception URI, because that only works if the events are created
     * in order.
     */
    @MediumTest
    public void testOutOfOrderRecurrenceExceptions() {
        String account = "reooo_account";
        String startWhen = "1987-08-09T12:00:00";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Generate base event.
        ContentValues eventValues = EventHelper.getNewRecurringEventValues(account, seed,
                calendarId, true, startWhen, "PT1H", "FREQ=DAILY;WKST=SU;COUNT=10");

        // Select a period that gives us 3 instances.
        String timeZone = eventValues.getAsString(Events.EVENT_TIMEZONE);
        String testStart = "1987-08-09T00:00:00";
        String testEnd = "1987-08-11T23:59:59";
        String[] projection = { Instances.BEGIN, Instances.START_MINUTE, Instances.EVENT_ID };

        /*
         * We're interested in exploring what the instance expansion code does with the events
         * as they arrive.  It won't do anything at event-creation time unless the instance
         * range already covers the interesting set of dates, so we need to create and remove
         * an instance in the same time frame beforehand.
         */
        expandInstanceRange(account, calendarId, testStart, testEnd, timeZone);

        /*
         * Instances table should be expanded.  Do the test.
         */

        // Generate exception from base.  We shift the start time by half an hour.
        ContentValues excepValues = new ContentValues(eventValues);
        excepValues.remove(Events._SYNC_ID);
        excepValues.put(Events.ORIGINAL_SYNC_ID, eventValues.getAsString(Events._SYNC_ID));

        long dtstartMillis = excepValues.getAsLong(Events.DTSTART);
        dtstartMillis += 24 * 60 * 60 * 1000;       // add one day -- use the second instance
        excepValues.put(Events.ORIGINAL_INSTANCE_TIME, dtstartMillis);
        dtstartMillis += 1800 * 1000;
        excepValues.put(Events.DTSTART, dtstartMillis);
        excepValues.put(Events.DTEND, dtstartMillis + 3600*1000);
        excepValues.remove(Events.DURATION);
        excepValues.remove(Events.RRULE);

        // Create exception event.
        long excepId = createAndVerifyEvent(account, seed, calendarId, true, excepValues);
        assertTrue(excepId >= 0);

        // Create recurring event.
        long eventId = createAndVerifyEvent(account, seed, calendarId, true, eventValues);
        assertTrue(eventId >= 0);

        // Check to see how many instances we get.  If the recurrence and the exception don't
        // get paired up correctly, we'll see one instance too many.
        Cursor instances = getInstances(timeZone, testStart, testEnd, projection);
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "with exception");
        }

        assertEquals("initial recurrence instance count", 3, instances.getCount());

        instances.close();

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Tests exceptions that modify all future instances of a recurring event.
     */
    @MediumTest
    public void testForwardRecurrenceExceptions() {
        String account = "refx_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create recurring event
        ContentValues eventValues = EventHelper.getNewRecurringEventValues(account, seed++,
                calendarId, true, "1999-01-01T06:00:00", "PT1H", "FREQ=WEEKLY;WKST=SU;COUNT=10");
        long eventId = createAndVerifyEvent(account, seed++, calendarId, true, eventValues);

        // Add some attendees and reminders.
        addAttendees(account, eventId, seed++);
        addReminders(account, eventId, seed++);

        // Get some instances.
        String timeZone = eventValues.getAsString(Events.EVENT_TIMEZONE);
        String testStart = "1999-01-01T00:00:00";
        String testEnd = "1999-01-29T23:59:59";
        String[] projection = { Instances.BEGIN, Instances.START_MINUTE };

        Cursor instances = getInstances(timeZone, testStart, testEnd, projection);
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "initial");
        }

        assertEquals("initial recurrence instance count", 5, instances.getCount());

        // Modify starting from 3rd instance.
        instances.moveToPosition(2);

        long startMillis;
        ContentValues excepValues;

        // Replace with a new recurrence rule.  We move the start time an hour later, and cap
        // it at two instances.
        startMillis = instances.getLong(0);
        excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.DTSTART, startMillis + 3600*1000);
        excepValues.put(Events.RRULE, "FREQ=WEEKLY;COUNT=2;WKST=SU");
        long excepEventId = createAndVerifyException(account, eventId, excepValues, true);
        instances.close();


        // Check to see if it took.
        instances = getInstances(timeZone, testStart, testEnd, projection);
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "with new rule");
        }

        assertEquals("count with exception", 4, instances.getCount());

        long prevMinute = -1;
        for (int i = 0; i < 4; i++) {
            long startMinute;
            instances.moveToNext();
            switch (i) {
                case 0:
                    startMinute = instances.getLong(1);
                    break;
                case 1:
                case 3:
                    startMinute = instances.getLong(1);
                    assertEquals("first/last pairs match", prevMinute, startMinute);
                    break;
                case 2:
                    startMinute = instances.getLong(1);
                    assertFalse("first two != last two", prevMinute == startMinute);
                    break;
                default:
                    fail();
                    startMinute = -1;   // make compiler happy
                    break;
            }

            prevMinute = startMinute;
        }
        instances.close();

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Tests exceptions that modify all instances of a recurring event.  This is not really an
     * exception, since it won't create a new event, but supporting it allows us to use the
     * exception URI without having to determine whether the "start from here" instance is the
     * very first instance.
     */
    @MediumTest
    public void testFullRecurrenceUpdate() {
        String account = "ref_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create recurring event
        String rrule = "FREQ=DAILY;WKST=MO;COUNT=100";
        ContentValues eventValues = EventHelper.getNewRecurringEventValues(account, seed++,
                calendarId, true, "1997-08-29T02:14:00", "PT1H", rrule);
        long eventId = createAndVerifyEvent(account, seed++, calendarId, true, eventValues);
        //Log.i(TAG, "+++ eventId is " + eventId);

        // Get some instances.
        String timeZone = eventValues.getAsString(Events.EVENT_TIMEZONE);
        String testStart = "1997-08-01T00:00:00";
        String testEnd = "1997-08-31T23:59:59";
        String[] projection = { Instances.BEGIN, Instances.EVENT_LOCATION };
        String newLocation = "NEW!";

        Cursor instances = getInstances(timeZone, testStart, testEnd, projection);
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "initial");
        }

        assertEquals("initial recurrence instance count", 3, instances.getCount());

        instances.moveToFirst();
        long startMillis = instances.getLong(0);
        ContentValues excepValues = EventHelper.getNewExceptionValues(startMillis);
        excepValues.put(Events.RRULE, rrule);   // identifies this as an "all future events" excep
        excepValues.put(Events.EVENT_LOCATION, newLocation);
        long excepEventId = createAndVerifyException(account, eventId, excepValues, true);
        instances.close();

        // Check results.
        assertEquals("full update does not create new ID", eventId, excepEventId);

        instances = getInstances(timeZone, testStart, testEnd, projection);
        assertEquals("post-update instance count", 3, instances.getCount());
        while (instances.moveToNext()) {
            assertEquals("new location", newLocation, instances.getString(1));
        }

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    @MediumTest
    public void testMultiRuleRecurrence() {
        String account = "multirule_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create recurring event
        String rrule = "FREQ=DAILY;WKST=MO;COUNT=5\nFREQ=WEEKLY;WKST=SU;COUNT=5";
        ContentValues eventValues = EventHelper.getNewRecurringEventValues(account, seed++,
                calendarId, true, "1997-08-29T02:14:00", "PT1H", rrule);
        long eventId = createAndVerifyEvent(account, seed++, calendarId, true, eventValues);

        // TODO: once multi-rule RRULEs are fully supported, verify that they work

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Issue bad requests and expect them to get rejected.
     */
    @MediumTest
    public void testBadRequests() {
        String account = "neg_account";
        int seed = 0;

        // Clean up just in case
        CalendarHelper.deleteCalendarByAccount(mContentResolver, account);

        // Create calendar
        long calendarId = createAndVerifyCalendar(account, seed++, null);

        // Create recurring event
        String rrule = "FREQ=OFTEN;WKST=MO";
        ContentValues eventValues = EventHelper.getNewRecurringEventValues(account, seed++,
                calendarId, true, "1997-08-29T02:14:00", "PT1H", rrule);
        try {
            createAndVerifyEvent(account, seed++, calendarId, true, eventValues);
            fail("Bad recurrence rule should have been rejected");
        } catch (IllegalArgumentException iae) {
            // good
        }

        // delete the calendar
        removeAndVerifyCalendar(account, calendarId);
    }

    /**
     * Acquires the set of instances that appear between the specified start and end points.
     *
     * @param timeZone Time zone to use when parsing startWhen and endWhen
     * @param startWhen Start date/time, in RFC 3339 format
     * @param endWhen End date/time, in RFC 3339 format
     * @param projection Array of desired column names
     * @return Cursor with instances (caller should close when done)
     */
    private Cursor getInstances(String timeZone, String startWhen, String endWhen,
            String[] projection) {
        Time startTime = new Time(timeZone);
        startTime.parse3339(startWhen);
        long startMillis = startTime.toMillis(false);

        Time endTime = new Time(timeZone);
        endTime.parse3339(endWhen);
        long endMillis = endTime.toMillis(false);

        // We want a list of instances that occur between the specified dates.
        Uri uri = Uri.withAppendedPath(CalendarContract.Instances.CONTENT_URI,
                startMillis + "/" + endMillis);

        Cursor instances = mContentResolver.query(uri, projection, null, null,
                projection[0] + " ASC");

        return instances;
    }

    /** debug -- dump instances cursor */
    private static void dumpInstances(Cursor instances, String timeZone, String msg) {
        Log.d(TAG, "Instances (" + msg + ")");

        int posn = instances.getPosition();
        instances.moveToPosition(-1);

        //Log.d(TAG, "+++ instances has " + instances.getCount() + " rows, " +
        //        instances.getColumnCount() + " columns");
        while (instances.moveToNext()) {
            long beginMil = instances.getLong(0);
            Time beginT = new Time(timeZone);
            beginT.set(beginMil);
            String logMsg = "--> begin=" + beginT.format3339(false) + " (" + beginMil + ")";
            for (int i = 2; i < instances.getColumnCount(); i++) {
                logMsg += " [" + instances.getString(i) + "]";
            }
            Log.d(TAG, logMsg);
        }
        instances.moveToPosition(posn);
    }


    /**
     * Counts the number of instances that appear between the specified start and end times.
     */
    private int getInstanceCount(String timeZone, String startWhen, String endWhen) {
        Cursor instances = getInstances(timeZone, startWhen, endWhen,
                new String[] { Instances._ID });
        int count = instances.getCount();
        instances.close();
        return count;
    }

    /**
     * Deletes an event as app and sync adapter which removes it from the db and
     * verifies after each.
     *
     * @param eventUri The uri for the event to delete
     * @param accountName TODO
     */
    private void removeAndVerifyEvent(Uri eventUri, ContentValues eventValues, String accountName) {
        // Delete event
        EventHelper.deleteEvent(mContentResolver, eventUri, eventValues);
        // Verify
        verifyEvent(eventValues, ContentUris.parseId(eventUri));
        // Delete as sync adapter
        assertEquals(1,
                EventHelper.deleteEventAsSyncAdapter(mContentResolver, eventUri, accountName));
        // Verify
        Cursor c = EventHelper.getEventByUri(mContentResolver, eventUri);
        assertEquals(0, c.getCount());
        c.close();
    }

    /**
     * Creates an event on the given calendar and verifies it.
     *
     * @param account
     * @param seed
     * @param calendarId
     * @param asSyncAdapter
     * @param values optional pre created set of values; will have several new entries added
     * @return the _id for the new event
     */
    private long createAndVerifyEvent(String account, int seed, long calendarId,
            boolean asSyncAdapter, ContentValues values) {
        // Create an event
        if (values == null) {
            values = EventHelper.getNewEventValues(account, seed, calendarId, asSyncAdapter);
        }
        Uri insertUri = Events.CONTENT_URI;
        if (asSyncAdapter) {
            insertUri = asSyncAdapter(insertUri, account, CTS_TEST_TYPE);
        }
        Uri uri = mContentResolver.insert(insertUri, values);

        // Verify
        EventHelper.addDefaultReadOnlyValues(values, account, asSyncAdapter);
        long eventId = ContentUris.parseId(uri);
        assertTrue(eventId >= 0);

        verifyEvent(values, eventId);
        return eventId;
    }

    /**
     * Updates an event, and verifies that the updates took.
     */
    private void updateAndVerifyEvent(String account, long calendarId, long eventId,
            boolean asSyncAdapter, ContentValues updateValues) {
        Uri uri = Uri.withAppendedPath(Events.CONTENT_URI, String.valueOf(eventId));
        if (asSyncAdapter) {
            uri = asSyncAdapter(uri, account, CTS_TEST_TYPE);
        }
        int count = mContentResolver.update(uri, updateValues, null, null);

        // Verify
        assertEquals(1, count);
        verifyEvent(updateValues, eventId);
    }

    /**
     * Creates an exception to a recurring event, and verifies it.
     * @param account The account to use.
     * @param originalEventId The ID of the original event.
     * @param values Values for the exception; must include originalInstanceTime.
     * @return The _id for the new event.
     */
    private long createAndVerifyException(String account, long originalEventId,
            ContentValues values, boolean asSyncAdapter) {
        // Create the exception
        Uri uri = Uri.withAppendedPath(Events.CONTENT_EXCEPTION_URI,
                String.valueOf(originalEventId));
        if (asSyncAdapter) {
            uri = asSyncAdapter(uri, account, CTS_TEST_TYPE);
        }
        Uri resultUri = mContentResolver.insert(uri, values);
        assertNotNull(resultUri);
        long eventId = ContentUris.parseId(resultUri);
        assertTrue(eventId >= 0);
        return eventId;
    }

    /**
     * Deletes an exception to a recurring event.
     * @param account The account to use.
     * @param eventId The ID of the original recurring event.
     * @param excepId The ID of the exception event.
     * @return The number of rows deleted.
     */
    private int deleteException(String account, long eventId, long excepId) {
        Uri uri = Uri.withAppendedPath(Events.CONTENT_EXCEPTION_URI,
                eventId + "/" + excepId);
        uri = asSyncAdapter(uri, account, CTS_TEST_TYPE);
        return mContentResolver.delete(uri, null, null);
    }

    /**
     * Add some attendees to an event.
     */
    private void addAttendees(String account, long eventId, int seed) {

        assertTrue(eventId >= 0);
        Uri syncUri = asSyncAdapter(Attendees.CONTENT_URI, account, CTS_TEST_TYPE);

        ContentValues values = new ContentValues();
        values.put(Attendees.EVENT_ID, eventId);
        values.put(Attendees.ATTENDEE_NAME, "Attender" + seed);
        values.put(Attendees.ATTENDEE_EMAIL, CalendarHelper.generateCalendarOwnerEmail(account));
        values.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_ACCEPTED);
        values.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ORGANIZER);
        values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_NONE);
        Uri uri = mContentResolver.insert(syncUri, values);
        seed++;

        values = new ContentValues();
        values.put(Attendees.EVENT_ID, eventId);
        values.put(Attendees.ATTENDEE_NAME, "Attender" + seed);
        values.put(Attendees.ATTENDEE_EMAIL, "attender" + seed + "@example.com");
        values.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_TENTATIVE);
        values.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_NONE);
        values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_NONE);
        uri = mContentResolver.insert(syncUri, values);
    }

    /**
     * Add some reminders to an event.
     */
    private void addReminders(String account, long eventId, int seed) {
        ContentValues values = new ContentValues();

        values.put(Reminders.EVENT_ID, eventId);
        values.put(Reminders.MINUTES, seed * 5);
        values.put(Reminders.METHOD, Reminders.METHOD_ALERT);

        Uri syncUri = asSyncAdapter(Reminders.CONTENT_URI, account, CTS_TEST_TYPE);
        Uri uri = mContentResolver.insert(syncUri, values);
    }

    /**
     * Creates and removes an event that covers a specific range of dates.  Call this to
     * cause the provider to expand the CalendarMetaData min/max values to include the range.
     * Useful when you want to see the provider expand the instances as the events are added.
     */
    private void expandInstanceRange(String account, long calendarId, String testStart,
            String testEnd, String timeZone) {
        int seed = 0;

        // TODO: this should use an UNTIL rule based on testEnd, not a COUNT
        ContentValues eventValues = EventHelper.getNewRecurringEventValues(account, seed,
                calendarId, true, testStart, "PT1H", "FREQ=DAILY;WKST=SU;COUNT=100");

        /*
         * Some of the helper functions modify "eventValues", so we want to make sure we're
         * passing a copy of anything we want to re-use.
         */
        long eventId = createAndVerifyEvent(account, seed, calendarId, true,
                new ContentValues(eventValues));
        assertTrue(eventId >= 0);

        String[] projection = { Instances.BEGIN, Instances.START_MINUTE };
        Cursor instances = getInstances(timeZone, testStart, testEnd, projection);
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "prep-create");
        }
        assertEquals("initial recurrence instance count", 3, instances.getCount());
        instances.close();

        Uri eventUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventId);
        removeAndVerifyEvent(eventUri, new ContentValues(eventValues), account);

        instances = getInstances(timeZone, testStart, testEnd, projection);
        if (DEBUG_RECURRENCE) {
            dumpInstances(instances, timeZone, "prep-clear");
        }
        assertEquals("initial recurrence instance count", 0, instances.getCount());
        instances.close();

    }

    /**
     * Inserts a new calendar with the given account and seed and verifies it.
     *
     * @param account The account to add the calendar to
     * @param seed A number to use to generate the values
     * @return the created calendar's id
     */
    private long createAndVerifyCalendar(String account, int seed, ContentValues values) {
        // Create a calendar
        if (values == null) {
            values = CalendarHelper.getNewCalendarValues(account, seed);
        }
        Uri syncUri = asSyncAdapter(Calendars.CONTENT_URI, account, CTS_TEST_TYPE);
        Uri uri = mContentResolver.insert(syncUri, values);
        long calendarId = ContentUris.parseId(uri);
        assertTrue(calendarId >= 0);

        verifyCalendar(account, values, calendarId);
        return calendarId;
    }

    /**
     * Deletes a given calendar and verifies no calendars remain on that
     * account.
     *
     * @param account
     * @param id
     */
    private void removeAndVerifyCalendar(String account, long id) {
        // TODO Add code to delete as app and sync adapter and test both

        // Delete
        assertEquals(1, CalendarHelper.deleteCalendarById(mContentResolver, id));

        // Verify
        Cursor c = CalendarHelper.getCalendarsByAccount(mContentResolver, account);
        assertEquals(0, c.getCount());
        c.close();
    }

    /**
     * Check all the fields of a calendar contained in values + id. This assumes
     * a single calendar has been created on the given account.
     *
     * @param account the account of the calendar
     * @param values the values to check against the db
     * @param id the _id of the calendar
     */
    private void verifyCalendar(String account, ContentValues values, long id) {
        // Verify
        Cursor c = CalendarHelper.getCalendarsByAccount(mContentResolver, account);
        assertEquals(1, c.getCount());
        assertTrue(c.moveToFirst());
        assertEquals(id, c.getLong(0));
        for (String key : values.keySet()) {
            int index = c.getColumnIndex(key);
            assertEquals(key, values.getAsString(key), c.getString(index));
        }
        c.close();
    }
}
