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.SyncStateContract;
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.text.format.DateUtils;

import com.android.emailcommon.Logging;
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.TimeZone;
import java.util.Map.Entry;

public class CalendarSyncParser extends AbstractSyncParser {
    private static final String TAG = Logging.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.i(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.i(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);
    }
}
