package com.android.exchange.adapter;

import android.content.ContentProviderOperation;
import android.content.ContentProviderResult;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.net.Uri;
import android.os.RemoteException;
import android.os.TransactionTooLargeException;
import android.provider.CalendarContract;
import android.provider.CalendarContract.Attendees;
import android.provider.CalendarContract.Calendars;
import android.provider.CalendarContract.Events;
import android.provider.CalendarContract.ExtendedProperties;
import android.provider.CalendarContract.Reminders;
import android.provider.CalendarContract.SyncState;
import android.provider.SyncStateContract;
import android.text.format.DateUtils;

import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.Mailbox;
import com.android.emailcommon.utility.Utility;
import com.android.exchange.Eas;
import com.android.exchange.adapter.AbstractSyncAdapter.Operation;
import com.android.exchange.service.EasCalendarSyncHandler;
import com.android.exchange.utility.CalendarUtilities;
import com.android.mail.utils.LogUtils;
import com.google.common.annotations.VisibleForTesting;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.Map.Entry;
import java.util.TimeZone;

public class CalendarSyncParser extends AbstractSyncParser {
    private static final String TAG = Eas.LOG_TAG;

    private final TimeZone UTC_TIMEZONE = TimeZone.getTimeZone("UTC");
    private final TimeZone mLocalTimeZone = TimeZone.getDefault();

    private final long mCalendarId;
    private final android.accounts.Account mAccountManagerAccount;
    private final Uri mAsSyncAdapterAttendees;
    private final Uri mAsSyncAdapterEvents;

    private final String[] mBindArgument = new String[1];
    private final CalendarOperations mOps;


    private static final String EVENT_SAVED_TIMEZONE_COLUMN = Events.SYNC_DATA1;
    // Since exceptions will have the same _SYNC_ID as the original event we have to check that
    // there's no original event when finding an item by _SYNC_ID
    private static final String SERVER_ID_AND_CALENDAR_ID = Events._SYNC_ID + "=? AND " +
        Events.ORIGINAL_SYNC_ID + " ISNULL AND " + Events.CALENDAR_ID + "=?";
    private static final String CLIENT_ID_SELECTION = Events.SYNC_DATA2 + "=?";
    private static final String ATTENDEES_EXCEPT_ORGANIZER = Attendees.EVENT_ID + "=? AND " +
        Attendees.ATTENDEE_RELATIONSHIP + "!=" + Attendees.RELATIONSHIP_ORGANIZER;
    private static final String[] ID_PROJECTION = new String[] {Events._ID};
    private static final String EVENT_ID_AND_NAME =
        ExtendedProperties.EVENT_ID + "=? AND " + ExtendedProperties.NAME + "=?";

    private static final String[] EXTENDED_PROPERTY_PROJECTION =
        new String[] {ExtendedProperties._ID};
    private static final int EXTENDED_PROPERTY_ID = 0;

    private static final String CATEGORY_TOKENIZER_DELIMITER = "\\";
    private static final String ATTENDEE_TOKENIZER_DELIMITER = CATEGORY_TOKENIZER_DELIMITER;

    private static final String EXTENDED_PROPERTY_USER_ATTENDEE_STATUS = "userAttendeeStatus";
    private static final String EXTENDED_PROPERTY_ATTENDEES = "attendees";
    private static final String EXTENDED_PROPERTY_DTSTAMP = "dtstamp";
    private static final String EXTENDED_PROPERTY_MEETING_STATUS = "meeting_status";
    private static final String EXTENDED_PROPERTY_CATEGORIES = "categories";
    // Used to indicate that we removed the attendee list because it was too large
    private static final String EXTENDED_PROPERTY_ATTENDEES_REDACTED = "attendeesRedacted";
    // Used to indicate that upsyncs aren't allowed (we catch this in sendLocalChanges)
    private static final String EXTENDED_PROPERTY_UPSYNC_PROHIBITED = "upsyncProhibited";

    private static final Operation PLACEHOLDER_OPERATION =
        new Operation(ContentProviderOperation.newInsert(Uri.EMPTY));

    private static final long SEPARATOR_ID = Long.MAX_VALUE;

    // Maximum number of allowed attendees; above this number, we mark the Event with the
    // attendeesRedacted extended property and don't allow the event to be upsynced to the server
    private static final int MAX_SYNCED_ATTENDEES = 50;
    // We set the organizer to this when the user is the organizer and we've redacted the
    // attendee list.  By making the meeting organizer OTHER than the user, we cause the UI to
    // prevent edits to this event (except local changes like reminder).
    private static final String BOGUS_ORGANIZER_EMAIL = "upload_disallowed@uploadisdisallowed.aaa";
    // Maximum number of CPO's before we start redacting attendees in exceptions
    // The number 500 has been determined empirically; 1500 CPOs appears to be the limit before
    // binder failures occur, but we need room at any point for additional events/exceptions so
    // we set our limit at 1/3 of the apparent maximum for extra safety
    // TODO Find a better solution to this workaround
    private static final int MAX_OPS_BEFORE_EXCEPTION_ATTENDEE_REDACTION = 500;

    public CalendarSyncParser(final Context context, final ContentResolver resolver,
            final InputStream in, final Mailbox mailbox, final Account account,
            final android.accounts.Account accountManagerAccount,
            final long calendarId) throws IOException {
        super(context, resolver, in, mailbox, account);
        mAccountManagerAccount = accountManagerAccount;
        mCalendarId = calendarId;
        mAsSyncAdapterAttendees = asSyncAdapter(Attendees.CONTENT_URI,
                mAccount.mEmailAddress, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE);
        mAsSyncAdapterEvents = asSyncAdapter(Events.CONTENT_URI,
                mAccount.mEmailAddress, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE);
        mOps = new CalendarOperations(resolver, mAsSyncAdapterAttendees, mAsSyncAdapterEvents,
                asSyncAdapter(Reminders.CONTENT_URI, mAccount.mEmailAddress,
                        Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE),
                asSyncAdapter(ExtendedProperties.CONTENT_URI, mAccount.mEmailAddress,
                        Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE));
    }

    protected static class CalendarOperations extends ArrayList<Operation> {
        private static final long serialVersionUID = 1L;
        public int mCount = 0;
        private int mEventStart = 0;
        private final ContentResolver mContentResolver;
        private final Uri mAsSyncAdapterAttendees;
        private final Uri mAsSyncAdapterEvents;
        private final Uri mAsSyncAdapterReminders;
        private final Uri mAsSyncAdapterExtendedProperties;

        public CalendarOperations(final ContentResolver contentResolver,
                final Uri asSyncAdapterAttendees, final Uri asSyncAdapterEvents,
                final Uri asSyncAdapterReminders, final Uri asSyncAdapterExtendedProperties) {
            mContentResolver = contentResolver;
            mAsSyncAdapterAttendees = asSyncAdapterAttendees;
            mAsSyncAdapterEvents = asSyncAdapterEvents;
            mAsSyncAdapterReminders = asSyncAdapterReminders;
            mAsSyncAdapterExtendedProperties = asSyncAdapterExtendedProperties;
        }

        @Override
        public boolean add(Operation op) {
            super.add(op);
            mCount++;
            return true;
        }

        public int newEvent(Operation op) {
            mEventStart = mCount;
            add(op);
            return mEventStart;
        }

        public int newDelete(long id, String serverId) {
            int offset = mCount;
            delete(id, serverId);
            return offset;
        }

        public void newAttendee(ContentValues cv) {
            newAttendee(cv, mEventStart);
        }

        public void newAttendee(ContentValues cv, int eventStart) {
            add(new Operation(ContentProviderOperation.newInsert(mAsSyncAdapterAttendees)
                    .withValues(cv),
                    Attendees.EVENT_ID,
                    eventStart));
        }

        public void updatedAttendee(ContentValues cv, long id) {
            cv.put(Attendees.EVENT_ID, id);
            add(new Operation(ContentProviderOperation.newInsert(mAsSyncAdapterAttendees)
                    .withValues(cv)));
        }

        public void newException(ContentValues cv) {
            add(new Operation(ContentProviderOperation.newInsert(mAsSyncAdapterEvents)
                    .withValues(cv)));
        }

        public void newExtendedProperty(String name, String value) {
            add(new Operation(ContentProviderOperation.newInsert(mAsSyncAdapterExtendedProperties)
                    .withValue(ExtendedProperties.NAME, name)
                    .withValue(ExtendedProperties.VALUE, value),
                    ExtendedProperties.EVENT_ID,
                    mEventStart));
        }

        public void updatedExtendedProperty(String name, String value, long id) {
            // Find an existing ExtendedProperties row for this event and property name
            Cursor c = mContentResolver.query(ExtendedProperties.CONTENT_URI,
                    EXTENDED_PROPERTY_PROJECTION, EVENT_ID_AND_NAME,
                    new String[] {Long.toString(id), name}, null);
            long extendedPropertyId = -1;
            // If there is one, capture its _id
            if (c != null) {
                try {
                    if (c.moveToFirst()) {
                        extendedPropertyId = c.getLong(EXTENDED_PROPERTY_ID);
                    }
                } finally {
                    c.close();
                }
            }
            // Either do an update or an insert, depending on whether one
            // already exists
            if (extendedPropertyId >= 0) {
                add(new Operation(ContentProviderOperation
                        .newUpdate(
                                ContentUris.withAppendedId(mAsSyncAdapterExtendedProperties,
                                        extendedPropertyId))
                        .withValue(ExtendedProperties.VALUE, value)));
            } else {
                newExtendedProperty(name, value);
            }
        }

        public void newReminder(int mins, int eventStart) {
            add(new Operation(ContentProviderOperation.newInsert(mAsSyncAdapterReminders)
                    .withValue(Reminders.MINUTES, mins)
                    .withValue(Reminders.METHOD, Reminders.METHOD_ALERT),
                    ExtendedProperties.EVENT_ID,
                    eventStart));
        }

        public void newReminder(int mins) {
            newReminder(mins, mEventStart);
        }

        public void delete(long id, String syncId) {
            add(new Operation(ContentProviderOperation.newDelete(
                    ContentUris.withAppendedId(mAsSyncAdapterEvents, id))));
            // Delete the exceptions for this Event (CalendarProvider doesn't do this)
            add(new Operation(ContentProviderOperation
                    .newDelete(mAsSyncAdapterEvents)
                    .withSelection(Events.ORIGINAL_SYNC_ID + "=?", new String[] {syncId})));
        }
    }

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

    private static void addOrganizerToAttendees(CalendarOperations ops, long eventId,
            String organizerName, String organizerEmail) {
        // Handle the organizer (who IS an attendee on device, but NOT in EAS)
        if (organizerName != null || organizerEmail != null) {
            ContentValues attendeeCv = new ContentValues();
            if (organizerName != null) {
                attendeeCv.put(Attendees.ATTENDEE_NAME, organizerName);
            }
            if (organizerEmail != null) {
                attendeeCv.put(Attendees.ATTENDEE_EMAIL, organizerEmail);
            }
            attendeeCv.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ORGANIZER);
            attendeeCv.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_REQUIRED);
            attendeeCv.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_ACCEPTED);
            if (eventId < 0) {
                ops.newAttendee(attendeeCv);
            } else {
                ops.updatedAttendee(attendeeCv, eventId);
            }
        }
    }

    /**
     * Set DTSTART, DTEND, DURATION and EVENT_TIMEZONE as appropriate for the given Event
     * The follow rules are enforced by CalendarProvider2:
     *   Events that aren't exceptions MUST have either 1) a DTEND or 2) a DURATION
     *   Recurring events (i.e. events with RRULE) must have a DURATION
     *   All-day recurring events MUST have a DURATION that is in the form P<n>D
     *   Other events MAY have a DURATION in any valid form (we use P<n>M)
     *   All-day events MUST have hour, minute, and second = 0; in addition, they must have
     *   the EVENT_TIMEZONE set to UTC
     *   Also, exceptions to all-day events need to have an ORIGINAL_INSTANCE_TIME that has
     *   hour, minute, and second = 0 and be set in UTC
     * @param cv the ContentValues for the Event
     * @param startTime the start time for the Event
     * @param endTime the end time for the Event
     * @param allDayEvent whether this is an all day event (1) or not (0)
     */
    /*package*/ void setTimeRelatedValues(ContentValues cv, long startTime, long endTime,
            int allDayEvent) {
        // If there's no startTime, the event will be found to be invalid, so return
        if (startTime < 0) return;
        // EAS events can arrive without an end time, but CalendarProvider requires them
        // so we'll default to 30 minutes; this will be superceded if this is an all-day event
        if (endTime < 0) endTime = startTime + (30 * DateUtils.MINUTE_IN_MILLIS);

        // If this is an all-day event, set hour, minute, and second to zero, and use UTC
        if (allDayEvent != 0) {
            startTime = CalendarUtilities.getUtcAllDayCalendarTime(startTime, mLocalTimeZone);
            endTime = CalendarUtilities.getUtcAllDayCalendarTime(endTime, mLocalTimeZone);
            String originalTimeZone = cv.getAsString(Events.EVENT_TIMEZONE);
            cv.put(EVENT_SAVED_TIMEZONE_COLUMN, originalTimeZone);
            cv.put(Events.EVENT_TIMEZONE, UTC_TIMEZONE.getID());
        }

        // If this is an exception, and the original was an all-day event, make sure the
        // original instance time has hour, minute, and second set to zero, and is in UTC
        if (cv.containsKey(Events.ORIGINAL_INSTANCE_TIME) &&
                cv.containsKey(Events.ORIGINAL_ALL_DAY)) {
            Integer ade = cv.getAsInteger(Events.ORIGINAL_ALL_DAY);
            if (ade != null && ade != 0) {
                long exceptionTime = cv.getAsLong(Events.ORIGINAL_INSTANCE_TIME);
                final GregorianCalendar cal = new GregorianCalendar(UTC_TIMEZONE);
                exceptionTime = CalendarUtilities.getUtcAllDayCalendarTime(exceptionTime,
                        mLocalTimeZone);
                cal.setTimeInMillis(exceptionTime);
                cal.set(GregorianCalendar.HOUR_OF_DAY, 0);
                cal.set(GregorianCalendar.MINUTE, 0);
                cal.set(GregorianCalendar.SECOND, 0);
                cv.put(Events.ORIGINAL_INSTANCE_TIME, cal.getTimeInMillis());
            }
        }

        // Always set DTSTART
        cv.put(Events.DTSTART, startTime);
        // For recurring events, set DURATION.  Use P<n>D format for all day events
        if (cv.containsKey(Events.RRULE)) {
            if (allDayEvent != 0) {
                cv.put(Events.DURATION, "P" + ((endTime - startTime) / DateUtils.DAY_IN_MILLIS) + "D");
            }
            else {
                cv.put(Events.DURATION, "P" + ((endTime - startTime) / DateUtils.MINUTE_IN_MILLIS) + "M");
            }
        // For other events, set DTEND and LAST_DATE
        } else {
            cv.put(Events.DTEND, endTime);
            cv.put(Events.LAST_DATE, endTime);
        }
    }

    public void addEvent(CalendarOperations ops, String serverId, boolean update)
            throws IOException {
        ContentValues cv = new ContentValues();
        cv.put(Events.CALENDAR_ID, mCalendarId);
        cv.put(Events._SYNC_ID, serverId);
        cv.put(Events.HAS_ATTENDEE_DATA, 1);
        cv.put(Events.SYNC_DATA2, "0");

        int allDayEvent = 0;
        String organizerName = null;
        String organizerEmail = null;
        int eventOffset = -1;
        int deleteOffset = -1;
        int busyStatus = CalendarUtilities.BUSY_STATUS_TENTATIVE;
        int responseType = CalendarUtilities.RESPONSE_TYPE_NONE;

        boolean firstTag = true;
        long eventId = -1;
        long startTime = -1;
        long endTime = -1;
        TimeZone timeZone = null;

        // Keep track of the attendees; exceptions will need them
        ArrayList<ContentValues> attendeeValues = new ArrayList<ContentValues>();
        int reminderMins = -1;
        String dtStamp = null;
        boolean organizerAdded = false;

        while (nextTag(Tags.SYNC_APPLICATION_DATA) != END) {
            if (update && firstTag) {
                // Find the event that's being updated
                Cursor c = getServerIdCursor(serverId);
                long id = -1;
                try {
                    if (c != null && c.moveToFirst()) {
                        id = c.getLong(0);
                    }
                } finally {
                    if (c != null) c.close();
                }
                if (id > 0) {
                    // DTSTAMP can come first, and we simply need to track it
                    if (tag == Tags.CALENDAR_DTSTAMP) {
                        dtStamp = getValue();
                        continue;
                    } else if (tag == Tags.CALENDAR_ATTENDEES) {
                        // This is an attendees-only update; just
                        // delete/re-add attendees
                        mBindArgument[0] = Long.toString(id);
                        ops.add(new Operation(ContentProviderOperation
                                .newDelete(mAsSyncAdapterAttendees)
                                .withSelection(ATTENDEES_EXCEPT_ORGANIZER, mBindArgument)));
                        eventId = id;
                    } else {
                        // Otherwise, delete the original event and recreate it
                        userLog("Changing (delete/add) event ", serverId);
                        deleteOffset = ops.newDelete(id, serverId);
                        // Add a placeholder event so that associated tables can reference
                        // this as a back reference.  We add the event at the end of the method
                        eventOffset = ops.newEvent(PLACEHOLDER_OPERATION);
                    }
                } else {
                    // The changed item isn't found. We'll treat this as a new item
                    eventOffset = ops.newEvent(PLACEHOLDER_OPERATION);
                    userLog(TAG, "Changed item not found; treating as new.");
                }
            } else if (firstTag) {
                // Add a placeholder event so that associated tables can reference
                // this as a back reference.  We add the event at the end of the method
               eventOffset = ops.newEvent(PLACEHOLDER_OPERATION);
            }
            firstTag = false;
            switch (tag) {
                case Tags.CALENDAR_ALL_DAY_EVENT:
                    allDayEvent = getValueInt();
                    if (allDayEvent != 0 && timeZone != null) {
                        // If the event doesn't start at midnight local time, we won't consider
                        // this an all-day event in the local time zone (this is what OWA does)
                        GregorianCalendar cal = new GregorianCalendar(mLocalTimeZone);
                        cal.setTimeInMillis(startTime);
                        userLog("All-day event arrived in: " + timeZone.getID());
                        if (cal.get(GregorianCalendar.HOUR_OF_DAY) != 0 ||
                                cal.get(GregorianCalendar.MINUTE) != 0) {
                            allDayEvent = 0;
                            userLog("Not an all-day event locally: " + mLocalTimeZone.getID());
                        }
                    }
                    cv.put(Events.ALL_DAY, allDayEvent);
                    break;
                case Tags.CALENDAR_ATTACHMENTS:
                    attachmentsParser();
                    break;
                case Tags.CALENDAR_ATTENDEES:
                    // If eventId >= 0, this is an update; otherwise, a new Event
                    attendeeValues = attendeesParser();
                    break;
                case Tags.BASE_BODY:
                    cv.put(Events.DESCRIPTION, bodyParser());
                    break;
                case Tags.CALENDAR_BODY:
                    cv.put(Events.DESCRIPTION, getValue());
                    break;
                case Tags.CALENDAR_TIME_ZONE:
                    timeZone = CalendarUtilities.tziStringToTimeZone(getValue());
                    if (timeZone == null) {
                        timeZone = mLocalTimeZone;
                    }
                    cv.put(Events.EVENT_TIMEZONE, timeZone.getID());
                    break;
                case Tags.CALENDAR_START_TIME:
                    startTime = Utility.parseDateTimeToMillis(getValue());
                    break;
                case Tags.CALENDAR_END_TIME:
                    endTime = Utility.parseDateTimeToMillis(getValue());
                    break;
                case Tags.CALENDAR_EXCEPTIONS:
                    // For exceptions to show the organizer, the organizer must be added before
                    // we call exceptionsParser
                    addOrganizerToAttendees(ops, eventId, organizerName, organizerEmail);
                    organizerAdded = true;
                    exceptionsParser(ops, cv, attendeeValues, reminderMins, busyStatus,
                            startTime, endTime);
                    break;
                case Tags.CALENDAR_LOCATION:
                    cv.put(Events.EVENT_LOCATION, getValue());
                    break;
                case Tags.CALENDAR_RECURRENCE:
                    String rrule = recurrenceParser();
                    if (rrule != null) {
                        cv.put(Events.RRULE, rrule);
                    }
                    break;
                case Tags.CALENDAR_ORGANIZER_EMAIL:
                    organizerEmail = getValue();
                    cv.put(Events.ORGANIZER, organizerEmail);
                    break;
                case Tags.CALENDAR_SUBJECT:
                    cv.put(Events.TITLE, getValue());
                    break;
                case Tags.CALENDAR_SENSITIVITY:
                    cv.put(Events.ACCESS_LEVEL, encodeVisibility(getValueInt()));
                    break;
                case Tags.CALENDAR_ORGANIZER_NAME:
                    organizerName = getValue();
                    break;
                case Tags.CALENDAR_REMINDER_MINS_BEFORE:
                    // Save away whether this tag has content; Exchange 2010 sends an empty tag
                    // rather than not sending one (as with Ex07 and Ex03)
                    boolean hasContent = !noContent;
                    reminderMins = getValueInt();
                    if (hasContent) {
                        ops.newReminder(reminderMins);
                        cv.put(Events.HAS_ALARM, 1);
                    }
                    break;
                // The following are fields we should save (for changes), though they don't
                // relate to data used by CalendarProvider at this point
                case Tags.CALENDAR_UID:
                    cv.put(Events.SYNC_DATA2, getValue());
                    break;
                case Tags.CALENDAR_DTSTAMP:
                    dtStamp = getValue();
                    break;
                case Tags.CALENDAR_MEETING_STATUS:
                    ops.newExtendedProperty(EXTENDED_PROPERTY_MEETING_STATUS, getValue());
                    break;
                case Tags.CALENDAR_BUSY_STATUS:
                    // We'll set the user's status in the Attendees table below
                    // Don't set selfAttendeeStatus or CalendarProvider will create a duplicate
                    // attendee!
                    busyStatus = getValueInt();
                    break;
                case Tags.CALENDAR_RESPONSE_TYPE:
                    // EAS 14+ uses this for the user's response status; we'll use this instead
                    // of busy status, if it appears
                    responseType = getValueInt();
                    break;
                case Tags.CALENDAR_CATEGORIES:
                    String categories = categoriesParser();
                    if (categories.length() > 0) {
                        ops.newExtendedProperty(EXTENDED_PROPERTY_CATEGORIES, categories);
                    }
                    break;
                default:
                    skipTag();
            }
        }

        // Enforce CalendarProvider required properties
        setTimeRelatedValues(cv, startTime, endTime, allDayEvent);

        // Set user's availability
        cv.put(Events.AVAILABILITY, CalendarUtilities.availabilityFromBusyStatus(busyStatus));

        // If we haven't added the organizer to attendees, do it now
        if (!organizerAdded) {
            addOrganizerToAttendees(ops, eventId, organizerName, organizerEmail);
        }

        // Note that organizerEmail can be null with a DTSTAMP only change from the server
        boolean selfOrganizer = (mAccount.mEmailAddress.equals(organizerEmail));

        // Store email addresses of attendees (in a tokenizable string) in ExtendedProperties
        // If the user is an attendee, set the attendee status using busyStatus (note that the
        // busyStatus is inherited from the parent unless it's specified in the exception)
        // Add the insert/update operation for each attendee (based on whether it's add/change)
        int numAttendees = attendeeValues.size();
        if (numAttendees > MAX_SYNCED_ATTENDEES) {
            // Indicate that we've redacted attendees.  If we're the organizer, disable edit
            // by setting organizerEmail to a bogus value and by setting the upsync prohibited
            // extended properly.
            // Note that we don't set ANY attendees if we're in this branch; however, the
            // organizer has already been included above, and WILL show up (which is good)
            if (eventId < 0) {
                ops.newExtendedProperty(EXTENDED_PROPERTY_ATTENDEES_REDACTED, "1");
                if (selfOrganizer) {
                    ops.newExtendedProperty(EXTENDED_PROPERTY_UPSYNC_PROHIBITED, "1");
                }
            } else {
                ops.updatedExtendedProperty(EXTENDED_PROPERTY_ATTENDEES_REDACTED, "1", eventId);
                if (selfOrganizer) {
                    ops.updatedExtendedProperty(EXTENDED_PROPERTY_UPSYNC_PROHIBITED, "1",
                            eventId);
                }
            }
            if (selfOrganizer) {
                organizerEmail = BOGUS_ORGANIZER_EMAIL;
                cv.put(Events.ORGANIZER, organizerEmail);
            }
            // Tell UI that we don't have any attendees
            cv.put(Events.HAS_ATTENDEE_DATA, "0");
            LogUtils.d(TAG, "Maximum number of attendees exceeded; redacting");
        } else if (numAttendees > 0) {
            StringBuilder sb = new StringBuilder();
            for (ContentValues attendee: attendeeValues) {
                String attendeeEmail = attendee.getAsString(Attendees.ATTENDEE_EMAIL);
                sb.append(attendeeEmail);
                sb.append(ATTENDEE_TOKENIZER_DELIMITER);
                if (mAccount.mEmailAddress.equalsIgnoreCase(attendeeEmail)) {
                    int attendeeStatus;
                    // We'll use the response type (EAS 14), if we've got one; otherwise, we'll
                    // try to infer it from busy status
                    if (responseType != CalendarUtilities.RESPONSE_TYPE_NONE) {
                        attendeeStatus =
                            CalendarUtilities.attendeeStatusFromResponseType(responseType);
                    } else if (!update) {
                        // For new events in EAS < 14, we have no idea what the busy status
                        // means, so we show "none", allowing the user to select an option.
                        attendeeStatus = Attendees.ATTENDEE_STATUS_NONE;
                    } else {
                        // For updated events, we'll try to infer the attendee status from the
                        // busy status
                        attendeeStatus =
                            CalendarUtilities.attendeeStatusFromBusyStatus(busyStatus);
                    }
                    attendee.put(Attendees.ATTENDEE_STATUS, attendeeStatus);
                    // If we're an attendee, save away our initial attendee status in the
                    // event's ExtendedProperties (we look for differences between this and
                    // the user's current attendee status to determine whether an email needs
                    // to be sent to the organizer)
                    // organizerEmail will be null in the case that this is an attendees-only
                    // change from the server
                    if (organizerEmail == null ||
                            !organizerEmail.equalsIgnoreCase(attendeeEmail)) {
                        if (eventId < 0) {
                            ops.newExtendedProperty(EXTENDED_PROPERTY_USER_ATTENDEE_STATUS,
                                    Integer.toString(attendeeStatus));
                        } else {
                            ops.updatedExtendedProperty(EXTENDED_PROPERTY_USER_ATTENDEE_STATUS,
                                    Integer.toString(attendeeStatus), eventId);

                        }
                    }
                }
                if (eventId < 0) {
                    ops.newAttendee(attendee);
                } else {
                    ops.updatedAttendee(attendee, eventId);
                }
            }
            if (eventId < 0) {
                ops.newExtendedProperty(EXTENDED_PROPERTY_ATTENDEES, sb.toString());
                ops.newExtendedProperty(EXTENDED_PROPERTY_ATTENDEES_REDACTED, "0");
                ops.newExtendedProperty(EXTENDED_PROPERTY_UPSYNC_PROHIBITED, "0");
            } else {
                ops.updatedExtendedProperty(EXTENDED_PROPERTY_ATTENDEES, sb.toString(),
                        eventId);
                ops.updatedExtendedProperty(EXTENDED_PROPERTY_ATTENDEES_REDACTED, "0", eventId);
                ops.updatedExtendedProperty(EXTENDED_PROPERTY_UPSYNC_PROHIBITED, "0", eventId);
            }
        }

        // Put the real event in the proper place in the ops ArrayList
        if (eventOffset >= 0) {
            // Store away the DTSTAMP here
            if (dtStamp != null) {
                ops.newExtendedProperty(EXTENDED_PROPERTY_DTSTAMP, dtStamp);
            }

            if (isValidEventValues(cv)) {
                ops.set(eventOffset,
                        new Operation(ContentProviderOperation
                                .newInsert(mAsSyncAdapterEvents).withValues(cv)));
            } else {
                // If we can't add this event (it's invalid), remove all of the inserts
                // we've built for it
                int cnt = ops.mCount - eventOffset;
                userLog(TAG, "Removing " + cnt + " inserts from mOps");
                for (int i = 0; i < cnt; i++) {
                    ops.remove(eventOffset);
                }
                ops.mCount = eventOffset;
                // If this is a change, we need to also remove the deletion that comes
                // before the addition
                if (deleteOffset >= 0) {
                    // Remove the deletion
                    ops.remove(deleteOffset);
                    // And the deletion of exceptions
                    ops.remove(deleteOffset);
                    userLog(TAG, "Removing deletion ops from mOps");
                    ops.mCount = deleteOffset;
                }
            }
        }
        // Mark the end of the event
        addSeparatorOperation(ops, Events.CONTENT_URI);
    }

    private void logEventColumns(ContentValues cv, String reason) {
        if (Eas.USER_LOG) {
            StringBuilder sb =
                new StringBuilder("Event invalid, " + reason + ", skipping: Columns = ");
            for (Entry<String, Object> entry: cv.valueSet()) {
                sb.append(entry.getKey());
                sb.append('/');
            }
            userLog(TAG, sb.toString());
        }
    }

    /*package*/ boolean isValidEventValues(ContentValues cv) {
        boolean isException = cv.containsKey(Events.ORIGINAL_INSTANCE_TIME);
        // All events require DTSTART
        if (!cv.containsKey(Events.DTSTART)) {
            logEventColumns(cv, "DTSTART missing");
            return false;
        // If we're a top-level event, we must have _SYNC_DATA (uid)
        } else if (!isException && !cv.containsKey(Events.SYNC_DATA2)) {
            logEventColumns(cv, "_SYNC_DATA missing");
            return false;
        // We must also have DTEND or DURATION if we're not an exception
        } else if (!isException && !cv.containsKey(Events.DTEND) &&
                !cv.containsKey(Events.DURATION)) {
            logEventColumns(cv, "DTEND/DURATION missing");
            return false;
        // Exceptions require DTEND
        } else if (isException && !cv.containsKey(Events.DTEND)) {
            logEventColumns(cv, "Exception missing DTEND");
            return false;
        // If this is a recurrence, we need a DURATION (in days if an all-day event)
        } else if (cv.containsKey(Events.RRULE)) {
            String duration = cv.getAsString(Events.DURATION);
            if (duration == null) return false;
            if (cv.containsKey(Events.ALL_DAY)) {
                Integer ade = cv.getAsInteger(Events.ALL_DAY);
                if (ade != null && ade != 0 && !duration.endsWith("D")) {
                    return false;
                }
            }
        }
        return true;
    }

    public String recurrenceParser() throws IOException {
        // Turn this information into an RRULE
        int type = -1;
        int occurrences = -1;
        int interval = -1;
        int dow = -1;
        int dom = -1;
        int wom = -1;
        int moy = -1;
        String until = null;

        while (nextTag(Tags.CALENDAR_RECURRENCE) != END) {
            switch (tag) {
                case Tags.CALENDAR_RECURRENCE_TYPE:
                    type = getValueInt();
                    break;
                case Tags.CALENDAR_RECURRENCE_INTERVAL:
                    interval = getValueInt();
                    break;
                case Tags.CALENDAR_RECURRENCE_OCCURRENCES:
                    occurrences = getValueInt();
                    break;
                case Tags.CALENDAR_RECURRENCE_DAYOFWEEK:
                    dow = getValueInt();
                    break;
                case Tags.CALENDAR_RECURRENCE_DAYOFMONTH:
                    dom = getValueInt();
                    break;
                case Tags.CALENDAR_RECURRENCE_WEEKOFMONTH:
                    wom = getValueInt();
                    break;
                case Tags.CALENDAR_RECURRENCE_MONTHOFYEAR:
                    moy = getValueInt();
                    break;
                case Tags.CALENDAR_RECURRENCE_UNTIL:
                    until = getValue();
                    break;
                default:
                   skipTag();
            }
        }

        return CalendarUtilities.rruleFromRecurrence(type, occurrences, interval,
                dow, dom, wom, moy, until);
    }

    private void exceptionParser(CalendarOperations ops, ContentValues parentCv,
            ArrayList<ContentValues> attendeeValues, int reminderMins, int busyStatus,
            long startTime, long endTime) throws IOException {
        ContentValues cv = new ContentValues();
        cv.put(Events.CALENDAR_ID, mCalendarId);

        // It appears that these values have to be copied from the parent if they are to appear
        // Note that they can be overridden below
        cv.put(Events.ORGANIZER, parentCv.getAsString(Events.ORGANIZER));
        cv.put(Events.TITLE, parentCv.getAsString(Events.TITLE));
        cv.put(Events.DESCRIPTION, parentCv.getAsString(Events.DESCRIPTION));
        cv.put(Events.ORIGINAL_ALL_DAY, parentCv.getAsInteger(Events.ALL_DAY));
        cv.put(Events.EVENT_LOCATION, parentCv.getAsString(Events.EVENT_LOCATION));
        cv.put(Events.ACCESS_LEVEL, parentCv.getAsString(Events.ACCESS_LEVEL));
        cv.put(Events.EVENT_TIMEZONE, parentCv.getAsString(Events.EVENT_TIMEZONE));
        // Exceptions should always have this set to zero, since EAS has no concept of
        // separate attendee lists for exceptions; if we fail to do this, then the UI will
        // allow the user to change attendee data, and this change would never get reflected
        // on the server.
        cv.put(Events.HAS_ATTENDEE_DATA, 0);

        int allDayEvent = 0;

        // This column is the key that links the exception to the serverId
        cv.put(Events.ORIGINAL_SYNC_ID, parentCv.getAsString(Events._SYNC_ID));

        String exceptionStartTime = "_noStartTime";
        while (nextTag(Tags.SYNC_APPLICATION_DATA) != END) {
            switch (tag) {
                case Tags.CALENDAR_ATTACHMENTS:
                    attachmentsParser();
                    break;
                case Tags.CALENDAR_EXCEPTION_START_TIME:
                    exceptionStartTime = getValue();
                    cv.put(Events.ORIGINAL_INSTANCE_TIME,
                            Utility.parseDateTimeToMillis(exceptionStartTime));
                    break;
                case Tags.CALENDAR_EXCEPTION_IS_DELETED:
                    if (getValueInt() == 1) {
                        cv.put(Events.STATUS, Events.STATUS_CANCELED);
                    }
                    break;
                case Tags.CALENDAR_ALL_DAY_EVENT:
                    allDayEvent = getValueInt();
                    cv.put(Events.ALL_DAY, allDayEvent);
                    break;
                case Tags.BASE_BODY:
                    cv.put(Events.DESCRIPTION, bodyParser());
                    break;
                case Tags.CALENDAR_BODY:
                    cv.put(Events.DESCRIPTION, getValue());
                    break;
                case Tags.CALENDAR_START_TIME:
                    startTime = Utility.parseDateTimeToMillis(getValue());
                    break;
                case Tags.CALENDAR_END_TIME:
                    endTime = Utility.parseDateTimeToMillis(getValue());
                    break;
                case Tags.CALENDAR_LOCATION:
                    cv.put(Events.EVENT_LOCATION, getValue());
                    break;
                case Tags.CALENDAR_RECURRENCE:
                    String rrule = recurrenceParser();
                    if (rrule != null) {
                        cv.put(Events.RRULE, rrule);
                    }
                    break;
                case Tags.CALENDAR_SUBJECT:
                    cv.put(Events.TITLE, getValue());
                    break;
                case Tags.CALENDAR_SENSITIVITY:
                    cv.put(Events.ACCESS_LEVEL, encodeVisibility(getValueInt()));
                    break;
                case Tags.CALENDAR_BUSY_STATUS:
                    busyStatus = getValueInt();
                    // Don't set selfAttendeeStatus or CalendarProvider will create a duplicate
                    // attendee!
                    break;
                    // TODO How to handle these items that are linked to event id!
//                case Tags.CALENDAR_DTSTAMP:
//                    ops.newExtendedProperty("dtstamp", getValue());
//                    break;
//                case Tags.CALENDAR_REMINDER_MINS_BEFORE:
//                    ops.newReminder(getValueInt());
//                    break;
                default:
                    skipTag();
            }
        }

        // We need a _sync_id, but it can't be the parent's id, so we generate one
        cv.put(Events._SYNC_ID, parentCv.getAsString(Events._SYNC_ID) + '_' +
                exceptionStartTime);

        // Enforce CalendarProvider required properties
        setTimeRelatedValues(cv, startTime, endTime, allDayEvent);

        // Don't insert an invalid exception event
        if (!isValidEventValues(cv)) return;

        // Add the exception insert
        int exceptionStart = ops.mCount;
        ops.newException(cv);
        // Also add the attendees, because they need to be copied over from the parent event
        boolean attendeesRedacted = false;
        if (attendeeValues != null) {
            for (ContentValues attValues: attendeeValues) {
                // If this is the user, use his busy status for attendee status
                String attendeeEmail = attValues.getAsString(Attendees.ATTENDEE_EMAIL);
                // Note that the exception at which we surpass the redaction limit might have
                // any number of attendees shown; since this is an edge case and a workaround,
                // it seems to be an acceptable implementation
                if (mAccount.mEmailAddress.equalsIgnoreCase(attendeeEmail)) {
                    attValues.put(Attendees.ATTENDEE_STATUS,
                            CalendarUtilities.attendeeStatusFromBusyStatus(busyStatus));
                    ops.newAttendee(attValues, exceptionStart);
                } else if (ops.size() < MAX_OPS_BEFORE_EXCEPTION_ATTENDEE_REDACTION) {
                    ops.newAttendee(attValues, exceptionStart);
                } else {
                    attendeesRedacted = true;
                }
            }
        }
        // And add the parent's reminder value
        if (reminderMins > 0) {
            ops.newReminder(reminderMins, exceptionStart);
        }
        if (attendeesRedacted) {
            LogUtils.d(TAG, "Attendees redacted in this exception");
        }
    }

    private static int encodeVisibility(int easVisibility) {
        int visibility = 0;
        switch(easVisibility) {
            case 0:
                visibility = Events.ACCESS_DEFAULT;
                break;
            case 1:
                visibility = Events.ACCESS_PUBLIC;
                break;
            case 2:
                visibility = Events.ACCESS_PRIVATE;
                break;
            case 3:
                visibility = Events.ACCESS_CONFIDENTIAL;
                break;
        }
        return visibility;
    }

    private void exceptionsParser(CalendarOperations ops, ContentValues cv,
            ArrayList<ContentValues> attendeeValues, int reminderMins, int busyStatus,
            long startTime, long endTime) throws IOException {
        while (nextTag(Tags.CALENDAR_EXCEPTIONS) != END) {
            switch (tag) {
                case Tags.CALENDAR_EXCEPTION:
                    exceptionParser(ops, cv, attendeeValues, reminderMins, busyStatus,
                            startTime, endTime);
                    break;
                default:
                    skipTag();
            }
        }
    }

    private String categoriesParser() throws IOException {
        StringBuilder categories = new StringBuilder();
        while (nextTag(Tags.CALENDAR_CATEGORIES) != END) {
            switch (tag) {
                case Tags.CALENDAR_CATEGORY:
                    // TODO Handle categories (there's no similar concept for gdata AFAIK)
                    // We need to save them and spit them back when we update the event
                    categories.append(getValue());
                    categories.append(CATEGORY_TOKENIZER_DELIMITER);
                    break;
                default:
                    skipTag();
            }
        }
        return categories.toString();
    }

    /**
     * For now, we ignore (but still have to parse) event attachments; these are new in EAS 14
     */
    private void attachmentsParser() throws IOException {
        while (nextTag(Tags.CALENDAR_ATTACHMENTS) != END) {
            switch (tag) {
                case Tags.CALENDAR_ATTACHMENT:
                    skipParser(Tags.CALENDAR_ATTACHMENT);
                    break;
                default:
                    skipTag();
            }
        }
    }

    private ArrayList<ContentValues> attendeesParser()
            throws IOException {
        int attendeeCount = 0;
        ArrayList<ContentValues> attendeeValues = new ArrayList<ContentValues>();
        while (nextTag(Tags.CALENDAR_ATTENDEES) != END) {
            switch (tag) {
                case Tags.CALENDAR_ATTENDEE:
                    ContentValues cv = attendeeParser();
                    // If we're going to redact these attendees anyway, let's avoid unnecessary
                    // memory pressure, and not keep them around
                    // We still need to parse them all, however
                    attendeeCount++;
                    // Allow one more than MAX_ATTENDEES, so that the check for "too many" will
                    // succeed in addEvent
                    if (attendeeCount <= (MAX_SYNCED_ATTENDEES+1)) {
                        attendeeValues.add(cv);
                    }
                    break;
                default:
                    skipTag();
            }
        }
        return attendeeValues;
    }

    private ContentValues attendeeParser()
            throws IOException {
        ContentValues cv = new ContentValues();
        while (nextTag(Tags.CALENDAR_ATTENDEE) != END) {
            switch (tag) {
                case Tags.CALENDAR_ATTENDEE_EMAIL:
                    cv.put(Attendees.ATTENDEE_EMAIL, getValue());
                    break;
                case Tags.CALENDAR_ATTENDEE_NAME:
                    cv.put(Attendees.ATTENDEE_NAME, getValue());
                    break;
                case Tags.CALENDAR_ATTENDEE_STATUS:
                    int status = getValueInt();
                    cv.put(Attendees.ATTENDEE_STATUS,
                            (status == 2) ? Attendees.ATTENDEE_STATUS_TENTATIVE :
                            (status == 3) ? Attendees.ATTENDEE_STATUS_ACCEPTED :
                            (status == 4) ? Attendees.ATTENDEE_STATUS_DECLINED :
                            (status == 5) ? Attendees.ATTENDEE_STATUS_INVITED :
                                Attendees.ATTENDEE_STATUS_NONE);
                    break;
                case Tags.CALENDAR_ATTENDEE_TYPE:
                    int type = Attendees.TYPE_NONE;
                    // EAS types: 1 = req'd, 2 = opt, 3 = resource
                    switch (getValueInt()) {
                        case 1:
                            type = Attendees.TYPE_REQUIRED;
                            break;
                        case 2:
                            type = Attendees.TYPE_OPTIONAL;
                            break;
                    }
                    cv.put(Attendees.ATTENDEE_TYPE, type);
                    break;
                default:
                    skipTag();
            }
        }
        cv.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE);
        return cv;
    }

    private String bodyParser() throws IOException {
        String body = null;
        while (nextTag(Tags.BASE_BODY) != END) {
            switch (tag) {
                case Tags.BASE_DATA:
                    body = getValue();
                    break;
                default:
                    skipTag();
            }
        }

        // Handle null data without error
        if (body == null) return "";
        // Remove \r's from any body text
        return body.replace("\r\n", "\n");
    }

    public void addParser(CalendarOperations ops) throws IOException {
        String serverId = null;
        while (nextTag(Tags.SYNC_ADD) != END) {
            switch (tag) {
                case Tags.SYNC_SERVER_ID: // same as
                    serverId = getValue();
                    break;
                case Tags.SYNC_APPLICATION_DATA:
                    addEvent(ops, serverId, false);
                    break;
                default:
                    skipTag();
            }
        }
    }

    private Cursor getServerIdCursor(String serverId) {
        return mContentResolver.query(Events.CONTENT_URI, ID_PROJECTION,
                SERVER_ID_AND_CALENDAR_ID, new String[] {serverId, Long.toString(mCalendarId)},
                null);
    }

    private Cursor getClientIdCursor(String clientId) {
        mBindArgument[0] = clientId;
        return mContentResolver.query(Events.CONTENT_URI, ID_PROJECTION, CLIENT_ID_SELECTION,
                mBindArgument, null);
    }

    public void deleteParser(CalendarOperations ops) throws IOException {
        while (nextTag(Tags.SYNC_DELETE) != END) {
            switch (tag) {
                case Tags.SYNC_SERVER_ID:
                    String serverId = getValue();
                    // Find the event with the given serverId
                    Cursor c = getServerIdCursor(serverId);
                    try {
                        if (c.moveToFirst()) {
                            userLog("Deleting ", serverId);
                            ops.delete(c.getLong(0), serverId);
                        }
                    } finally {
                        c.close();
                    }
                    break;
                default:
                    skipTag();
            }
        }
    }

    /**
     * A change is handled as a delete (including all exceptions) and an add
     * This isn't as efficient as attempting to traverse the original and all of its exceptions,
     * but changes happen infrequently and this code is both simpler and easier to maintain
     * @param ops the array of pending ContactProviderOperations.
     * @throws IOException
     */
    public void changeParser(CalendarOperations ops) throws IOException {
        String serverId = null;
        while (nextTag(Tags.SYNC_CHANGE) != END) {
            switch (tag) {
                case Tags.SYNC_SERVER_ID:
                    serverId = getValue();
                    break;
                case Tags.SYNC_APPLICATION_DATA:
                    userLog("Changing " + serverId);
                    addEvent(ops, serverId, true);
                    break;
                default:
                    skipTag();
            }
        }
    }

    @Override
    public void commandsParser() throws IOException {
        while (nextTag(Tags.SYNC_COMMANDS) != END) {
            if (tag == Tags.SYNC_ADD) {
                addParser(mOps);
            } else if (tag == Tags.SYNC_DELETE) {
                deleteParser(mOps);
            } else if (tag == Tags.SYNC_CHANGE) {
                changeParser(mOps);
            } else
                skipTag();
        }
    }

    @Override
    public void commit() throws IOException {
        userLog("Calendar SyncKey saved as: ", mMailbox.mSyncKey);
        // Save the syncKey here, using the Helper provider by Calendar provider
        mOps.add(new Operation(SyncStateContract.Helpers.newSetOperation(
                asSyncAdapter(SyncState.CONTENT_URI, mAccount.mEmailAddress,
                        Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE),
                mAccountManagerAccount,
                mMailbox.mSyncKey.getBytes())));

        // Execute our CPO's safely
        try {
            safeExecute(mContentResolver, CalendarContract.AUTHORITY, mOps);
        } catch (RemoteException e) {
            throw new IOException("Remote exception caught; will retry");
        }
    }

    public void addResponsesParser() throws IOException {
        String serverId = null;
        String clientId = null;
        int status = -1;
        ContentValues cv = new ContentValues();
        while (nextTag(Tags.SYNC_ADD) != END) {
            switch (tag) {
                case Tags.SYNC_SERVER_ID:
                    serverId = getValue();
                    break;
                case Tags.SYNC_CLIENT_ID:
                    clientId = getValue();
                    break;
                case Tags.SYNC_STATUS:
                    status = getValueInt();
                    if (status != 1) {
                        userLog("Attempt to add event failed with status: " + status);
                    }
                    break;
                default:
                    skipTag();
            }
        }

        if (clientId == null) return;
        if (serverId == null) {
            // TODO Reconsider how to handle this
            serverId = "FAIL:" + status;
        }

        Cursor c = getClientIdCursor(clientId);
        try {
            if (c.moveToFirst()) {
                cv.put(Events._SYNC_ID, serverId);
                cv.put(Events.SYNC_DATA2, clientId);
                long id = c.getLong(0);
                // Write the serverId into the Event
                mOps.add(new Operation(ContentProviderOperation
                        .newUpdate(ContentUris.withAppendedId(mAsSyncAdapterEvents, id))
                        .withValues(cv)));
                userLog("New event " + clientId + " was given serverId: " + serverId);
            }
        } finally {
            c.close();
        }
    }

    public void changeResponsesParser() throws IOException {
        String serverId = null;
        String status = null;
        while (nextTag(Tags.SYNC_CHANGE) != END) {
            switch (tag) {
                case Tags.SYNC_SERVER_ID:
                    serverId = getValue();
                    break;
                case Tags.SYNC_STATUS:
                    status = getValue();
                    break;
                default:
                    skipTag();
            }
        }
        if (serverId != null && status != null) {
            userLog("Changed event " + serverId + " failed with status: " + status);
        }
    }


    @Override
    public void responsesParser() throws IOException {
        // Handle server responses here (for Add and Change)
        while (nextTag(Tags.SYNC_RESPONSES) != END) {
            if (tag == Tags.SYNC_ADD) {
                addResponsesParser();
            } else if (tag == Tags.SYNC_CHANGE) {
                changeResponsesParser();
            } else
                skipTag();
        }
    }

    /**
     * We apply the batch of CPO's here.  We synchronize on the service to avoid thread-nasties,
     * and we just return quickly if the service has already been stopped.
     */
    private static ContentProviderResult[] execute(final ContentResolver contentResolver,
            final String authority, final ArrayList<ContentProviderOperation> ops)
            throws RemoteException, OperationApplicationException {
        if (!ops.isEmpty()) {
            ContentProviderResult[] result = contentResolver.applyBatch(authority, ops);
            //mService.userLog("Results: " + result.length);
            return result;
        }
        return new ContentProviderResult[0];
    }

    /**
     * Convert an Operation to a CPO; if the Operation has a back reference, apply it with the
     * passed-in offset
     */
    @VisibleForTesting
    static ContentProviderOperation operationToContentProviderOperation(Operation op, int offset) {
        if (op.mOp != null) {
            return op.mOp;
        } else if (op.mBuilder == null) {
            throw new IllegalArgumentException("Operation must have CPO.Builder");
        }
        ContentProviderOperation.Builder builder = op.mBuilder;
        if (op.mColumnName != null) {
            builder.withValueBackReference(op.mColumnName, op.mOffset - offset);
        }
        return builder.build();
    }

    /**
     * Create a list of CPOs from a list of Operations, and then apply them in a batch
     */
    private static ContentProviderResult[] applyBatch(final ContentResolver contentResolver,
            final String authority, final ArrayList<Operation> ops, final int offset)
            throws RemoteException, OperationApplicationException {
        // Handle the empty case
        if (ops.isEmpty()) {
            return new ContentProviderResult[0];
        }
        ArrayList<ContentProviderOperation> cpos = new ArrayList<ContentProviderOperation>();
        for (Operation op: ops) {
            cpos.add(operationToContentProviderOperation(op, offset));
        }
        return execute(contentResolver, authority, cpos);
    }

    /**
     * Apply the list of CPO's in the provider and copy the "mini" result into our full result array
     */
    private static void applyAndCopyResults(final ContentResolver contentResolver,
            final String authority, final ArrayList<Operation> mini,
            final ContentProviderResult[] result, final int offset) throws RemoteException {
        // Empty lists are ok; we just ignore them
        if (mini.isEmpty()) return;
        try {
            ContentProviderResult[] miniResult = applyBatch(contentResolver, authority, mini,
                    offset);
            // Copy the results from this mini-batch into our results array
            System.arraycopy(miniResult, 0, result, offset, miniResult.length);
        } catch (OperationApplicationException e) {
            // Not possible since we're building the ops ourselves
        }
    }

    /**
     * Called by a sync adapter to execute a list of Operations in the ContentProvider handling
     * the passed-in authority.  If the attempt to apply the batch fails due to a too-large
     * binder transaction, we split the Operations as directed by separators.  If any of the
     * "mini" batches fails due to a too-large transaction, we're screwed, but this would be
     * vanishingly rare.  Other, possibly transient, errors are handled by throwing a
     * RemoteException, which the caller will likely re-throw as an IOException so that the sync
     * can be attempted again.
     *
     * Callers MAY leave a dangling separator at the end of the list; note that the separators
     * themselves are only markers and are not sent to the provider.
     */
    protected static ContentProviderResult[] safeExecute(final ContentResolver contentResolver,
            final String authority, final ArrayList<Operation> ops) throws RemoteException {
        //mService.userLog("Try to execute ", ops.size(), " CPO's for " + authority);
        ContentProviderResult[] result = null;
        try {
            // Try to execute the whole thing
            return applyBatch(contentResolver, authority, ops, 0);
        } catch (TransactionTooLargeException e) {
            // Nope; split into smaller chunks, demarcated by the separator operation
            //mService.userLog("Transaction too large; spliting!");
            ArrayList<Operation> mini = new ArrayList<Operation>();
            // Build a result array with the total size we're sending
            result = new ContentProviderResult[ops.size()];
            int count = 0;
            int offset = 0;
            for (Operation op: ops) {
                if (op.mSeparator) {
                    //mService.userLog("Try mini-batch of ", mini.size(), " CPO's");
                    applyAndCopyResults(contentResolver, authority, mini, result, offset);
                    mini.clear();
                    // Save away the offset here; this will need to be subtracted out of the
                    // value originally set by the adapter
                    offset = count + 1; // Remember to add 1 for the separator!
                } else {
                    mini.add(op);
                }
                count++;
            }
            // Check out what's left; if it's more than just a separator, apply the batch
            int miniSize = mini.size();
            if ((miniSize > 0) && !(miniSize == 1 && mini.get(0).mSeparator)) {
                applyAndCopyResults(contentResolver, authority, mini, result, offset);
            }
        } catch (RemoteException e) {
            throw e;
        } catch (OperationApplicationException e) {
            // Not possible since we're building the ops ourselves
        }
        return result;
    }

    /**
     * Called by a sync adapter to indicate a relatively safe place to split a batch of CPO's
     */
    protected static void addSeparatorOperation(ArrayList<Operation> ops, Uri uri) {
        Operation op = new Operation(
                ContentProviderOperation.newDelete(ContentUris.withAppendedId(uri, SEPARATOR_ID)));
        op.mSeparator = true;
        ops.add(op);
    }

    @Override
    protected void wipe() {
        LogUtils.w(TAG, "Wiping calendar for account %d", mAccount.mId);
        EasCalendarSyncHandler.wipeAccountFromContentProvider(mContext,
                mAccount.mEmailAddress);
    }
}
