package com.android.exchange.service;

import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.Entity;
import android.content.EntityIterator;
import android.content.SyncResult;
import android.database.Cursor;
import android.database.DatabaseUtils;
import android.net.Uri;
import android.os.Bundle;
import android.provider.CalendarContract;
import android.provider.CalendarContract.Attendees;
import android.provider.CalendarContract.Calendars;
import android.provider.CalendarContract.Events;
import android.provider.CalendarContract.EventsEntity;
import android.provider.CalendarContract.ExtendedProperties;
import android.provider.CalendarContract.Reminders;
import android.text.TextUtils;
import android.text.format.DateUtils;

import com.android.calendarcommon2.DateException;
import com.android.calendarcommon2.Duration;
import com.android.emailcommon.TrafficFlags;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent.Message;
import com.android.emailcommon.provider.Mailbox;
import com.android.emailcommon.utility.Utility;
import com.android.exchange.Eas;
import com.android.exchange.R;
import com.android.exchange.adapter.AbstractSyncParser;
import com.android.exchange.adapter.CalendarSyncParser;
import com.android.exchange.adapter.Serializer;
import com.android.exchange.adapter.Tags;
import com.android.exchange.utility.CalendarUtilities;
import com.android.mail.utils.LogUtils;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.UUID;

/**
 * Performs an Exchange Sync for a Calendar collection.
 */
public class EasCalendarSyncHandler extends EasSyncHandler {
    private static final String TAG = "EasCalendarSyncHandler";

    // TODO: Some constants are copied from CalendarSyncAdapter and are still used by the parser.
    // These values need to stay in sync; when the parser is cleaned up, be sure to unify them.

    /** Projection for getting a calendar id. */
    private static final String[] CALENDAR_ID_PROJECTION = { Calendars._ID };
    private static final int CALENDAR_ID_COLUMN = 0;

    /** Content selection for getting a calendar id for an account. */
    private static final String CALENDAR_SELECTION_ACCOUNT_AND_SYNC_ID =
            Calendars.ACCOUNT_NAME + "=? AND " +
            Calendars.ACCOUNT_TYPE + "=? AND " +
            Calendars._SYNC_ID + "=?";

    /** Content selection for getting a calendar id for an account. */
    private static final String CALENDAR_SELECTION_ACCOUNT_AND_NO_SYNC =
            Calendars.ACCOUNT_NAME + "=? AND " +
            Calendars.ACCOUNT_TYPE + "=? AND " +
            Calendars._SYNC_ID + " IS NULL";

    /** The column used to track the timezone of the event. */
    private static final String EVENT_SAVED_TIMEZONE_COLUMN = Events.SYNC_DATA1;

    /** Used to keep track of exception vs. parent event dirtiness. */
    private static final String EVENT_SYNC_MARK = Events.SYNC_DATA8;

    /** The column used to track the Event version sequence number. */
    private static final String EVENT_SYNC_VERSION = Events.SYNC_DATA4;

    /** Projection for getting info about changed events. */
    private static final String[] ORIGINAL_EVENT_PROJECTION = { Events.ORIGINAL_ID, Events._ID };
    private static final int ORIGINAL_EVENT_ORIGINAL_ID_COLUMN = 0;
    private static final int ORIGINAL_EVENT_ID_COLUMN = 1;

    /** Content selection for dirty calendar events. */
    private static final String DIRTY_EXCEPTION_IN_CALENDAR = Events.DIRTY + "=1 AND " +
            Events.ORIGINAL_ID + " NOTNULL AND " + Events.CALENDAR_ID + "=?";

    /** Where clause for updating dirty events. */
    private static final String EVENT_ID_AND_CALENDAR_ID = Events._ID + "=? AND " +
            Events.ORIGINAL_SYNC_ID + " ISNULL AND " + Events.CALENDAR_ID + "=?";

    /** Content selection for dirty or marked top level events. */
    private static final String DIRTY_OR_MARKED_TOP_LEVEL_IN_CALENDAR = "(" + Events.DIRTY +
            "=1 OR " + EVENT_SYNC_MARK + "= 1) AND " + Events.ORIGINAL_ID + " ISNULL AND " +
            Events.CALENDAR_ID + "=?";

    /** Content selection for getting events when handling exceptions. */
    private static final String ORIGINAL_EVENT_AND_CALENDAR = Events.ORIGINAL_SYNC_ID + "=? AND " +
            Events.CALENDAR_ID + "=?";

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

    /** 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 String EXTENDED_PROPERTY_USER_ATTENDEE_STATUS = "userAttendeeStatus";
    private static final String EXTENDED_PROPERTY_ATTENDEES = "attendees";
    private static final String EXTENDED_PROPERTY_CATEGORIES = "categories";

    private final android.accounts.Account mAccountManagerAccount;
    private final long mCalendarId;

    // The following lists are populated as part of upsync, and handled during cleanup.
    /** Ids of events that were deleted in this upsync. */
    private final ArrayList<Long> mDeletedIdList = new ArrayList<Long>();
    /** Ids of events that were changed in this upsync. */
    private final ArrayList<Long> mUploadedIdList = new ArrayList<Long>();
    /** Emails that need to be sent due to this upsync. */
    private final ArrayList<Message> mOutgoingMailList = new ArrayList<Message>();

    public EasCalendarSyncHandler(final Context context, final ContentResolver contentResolver,
            final android.accounts.Account accountManagerAccount, final Account account,
            final Mailbox mailbox, final Bundle syncExtras, final SyncResult syncResult) {
        super(context, contentResolver, account, mailbox, syncExtras, syncResult);
        mAccountManagerAccount = accountManagerAccount;
        final Cursor c = mContentResolver.query(Calendars.CONTENT_URI, CALENDAR_ID_PROJECTION,
                CALENDAR_SELECTION_ACCOUNT_AND_SYNC_ID,
                new String[] {
                        mAccount.mEmailAddress,
                        Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE,
                        mailbox.mServerId,
                }, null);
        if (c == null) {
            mCalendarId = -1;
        } else {
            try {
                if (c.moveToFirst()) {
                    mCalendarId = c.getLong(CALENDAR_ID_COLUMN);
                } else {
                    long id = -1;
                    // Check if we have a calendar for this account with no server Id. If so, it was
                    // synced with an older version of the sync adapter before serverId's were
                    // supported.
                    final Cursor c1 = mContentResolver.query(Calendars.CONTENT_URI,
                            CALENDAR_ID_PROJECTION,
                            CALENDAR_SELECTION_ACCOUNT_AND_NO_SYNC,
                            new String[] {
                                    mAccount.mEmailAddress,
                                    Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE,
                            }, null);
                    if (c1 != null) {
                        try {
                            if (c1.moveToFirst()) {
                                id = c1.getLong(CALENDAR_ID_COLUMN);
                                final ContentValues values = new ContentValues();
                                values.put(Calendars._SYNC_ID, mMailbox.mServerId);
                                mContentResolver.update(
                                        ContentUris.withAppendedId(
                                                asSyncAdapter(Calendars.CONTENT_URI), id),
                                        values,
                                        null, /* where */
                                        null /* selectionArgs */);
                            }
                        } finally {
                            c1.close();
                        }
                    }

                    if (id >= 0) {
                        mCalendarId = id;
                    } else {
                        mCalendarId = CalendarUtilities.createCalendar(mContext, mContentResolver,
                            mAccount, mMailbox);
                    }
                }
            } finally {
                c.close();
            }
        }
    }

    @Override
    protected int getTrafficFlag() {
        return TrafficFlags.DATA_CALENDAR;
    }

    /**
     * Adds params to a {@link Uri} to indicate that the caller is a sync adapter, and to add the
     * account info.
     * @param uri The {@link Uri} to which to add params.
     * @return The augmented {@link Uri}.
     */
    private static Uri asSyncAdapter(final Uri uri, final String emailAddress) {
        return uri.buildUpon().appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true")
                .appendQueryParameter(Calendars.ACCOUNT_NAME, emailAddress)
                .appendQueryParameter(Calendars.ACCOUNT_TYPE, Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE)
                .build();
    }

    /**
     * Convenience wrapper to {@link #asSyncAdapter(android.net.Uri, String)}.
     */
    private Uri asSyncAdapter(final Uri uri) {
        return asSyncAdapter(uri, mAccount.mEmailAddress);
    }

    @Override
    protected String getFolderClassName() {
        return "Calendar";
    }


    @Override
    protected AbstractSyncParser getParser(final InputStream is) throws IOException {
        return new CalendarSyncParser(mContext, mContentResolver, is,
                mMailbox, mAccount, mAccountManagerAccount, mCalendarId);
    }

    @Override
    protected void setInitialSyncOptions(final Serializer s) throws IOException {
        // Nothing to do for Calendar.
    }

    @Override
    protected void setNonInitialSyncOptions(final Serializer s) throws IOException {
        setPimSyncOptions(s, Eas.FILTER_2_WEEKS);
    }

    /**
     * Find all dirty events for our calendar and mark their parents. Also delete any dirty events
     * that have no parents.
     * @param calendarIdString {@link #mCalendarId}, as a String.
     * @param calendarIdArgument calendarIdString, in a String array.
     */
    private void markParentsOfDirtyEvents(final String calendarIdString,
            final String[] calendarIdArgument) {
        // We've got to handle exceptions as part of the parent when changes occur, so we need
        // to find new/changed exceptions and mark the parent dirty
        final ArrayList<Long> orphanedExceptions = new ArrayList<Long>();
        final Cursor c = mContentResolver.query(Events.CONTENT_URI,
                ORIGINAL_EVENT_PROJECTION, DIRTY_EXCEPTION_IN_CALENDAR, calendarIdArgument, null);
        if (c != null) {
            try {
                final ContentValues cv = new ContentValues(1);
                // We use _sync_mark here to distinguish dirty parents from parents with dirty
                // exceptions
                cv.put(EVENT_SYNC_MARK, "1");
                while (c.moveToNext()) {
                    // Mark the parents of dirty exceptions
                    final long parentId = c.getLong(ORIGINAL_EVENT_ORIGINAL_ID_COLUMN);
                    final int cnt = mContentResolver.update(asSyncAdapter(Events.CONTENT_URI), cv,
                            EVENT_ID_AND_CALENDAR_ID,
                            new String[] { Long.toString(parentId), calendarIdString });
                    // Keep track of any orphaned exceptions
                    if (cnt == 0) {
                        orphanedExceptions.add(c.getLong(ORIGINAL_EVENT_ID_COLUMN));
                    }
                }
            } finally {
                c.close();
            }
        }

        // Delete any orphaned exceptions
        for (final long orphan : orphanedExceptions) {
            LogUtils.i(TAG, "Deleted orphaned exception: %d", orphan);
            mContentResolver.delete(asSyncAdapter(
                    ContentUris.withAppendedId(Events.CONTENT_URI, orphan)), null, null);
        }
    }

    /**
     * Get the version number of the current event, incrementing it if it's already there.
     * @param entityValues The {@link ContentValues} for this event.
     * @return The new version number for this event (i.e. 0 if it's a new event, or the old version
     *     number + 1).
     */
    private static String getEntityVersion(final ContentValues entityValues) {
        final String version = entityValues.getAsString(EVENT_SYNC_VERSION);
        // This should never be null, but catch this error anyway
        // Version should be "0" when we create the event, so use that
        if (version != null) {
            // Increment and save
            try {
                return Integer.toString((Integer.parseInt(version) + 1));
            } catch (final NumberFormatException e) {
                // Handle the case in which someone writes a non-integer here;
                // shouldn't happen, but we don't want to kill the sync for his
            }
        }
        return "0";
    }

    /**
     * Convenience method for sending an email to the organizer declining the meeting.
     * @param entity The {@link Entity} for this event.
     * @param clientId The client id for this event.
     */
    private void sendDeclinedEmail(final Entity entity, final String clientId) {
        final Message msg =
                CalendarUtilities.createMessageForEntity(mContext, entity,
                        Message.FLAG_OUTGOING_MEETING_DECLINE, clientId, mAccount);
        if (msg != null) {
            LogUtils.i(TAG, "Queueing declined response to %s", msg.mTo);
            mOutgoingMailList.add(msg);
        }
    }

    /**
     * Get an integer value from a {@link ContentValues}, or 0 if the value isn't there.
     * @param cv The {@link ContentValues} to find the value in.
     * @param column The name of the column in cv to get.
     * @return The appropriate value as an integer, or 0 if it's not there.
     */
    private static int getInt(final ContentValues cv, final String column) {
        final Integer i = cv.getAsInteger(column);
        if (i == null) return 0;
        return i;
    }

    /**
     * Convert {@link Events} visibility values to EAS visibility values.
     * @param visibility The {@link Events} visibility value.
     * @return The corresponding EAS visibility value.
     */
    private static String decodeVisibility(final int visibility) {
        final int easVisibility;
        switch(visibility) {
            case Events.ACCESS_DEFAULT:
                easVisibility = 0;
                break;
            case Events.ACCESS_PUBLIC:
                easVisibility = 1;
                break;
            case Events.ACCESS_PRIVATE:
                easVisibility = 2;
                break;
            case Events.ACCESS_CONFIDENTIAL:
                easVisibility = 3;
                break;
            default:
                easVisibility = 0;
                break;
        }
        return Integer.toString(easVisibility);
    }

    /**
     * Write an event to the {@link Serializer} for this upsync.
     * @param entity The {@link Entity} for this event.
     * @param clientId The client id for this event.
     * @param s The {@link Serializer} for this Sync request.
     * @throws IOException
     * TODO: This can probably be refactored/cleaned up more.
     */
    private void sendEvent(final Entity entity, final String clientId, final Serializer s)
            throws IOException {
        // Serialize for EAS here
        // Set uid with the client id we created
        // 1) Serialize the top-level event
        // 2) Serialize attendees and reminders from subvalues
        // 3) Look for exceptions and serialize with the top-level event
        final ContentValues entityValues = entity.getEntityValues();
        final boolean isException = (clientId == null);
        boolean hasAttendees = false;
        final boolean isChange = entityValues.containsKey(Events._SYNC_ID);
        final boolean allDay =
            CalendarUtilities.getIntegerValueAsBoolean(entityValues, Events.ALL_DAY);
        final TimeZone localTimeZone = TimeZone.getDefault();

        // NOTE: Exchange 2003 (EAS 2.5) seems to require the "exception deleted" and "exception
        // start time" data before other data in exceptions.  Failure to do so results in a
        // status 6 error during sync
        if (isException) {
           // Send exception deleted flag if necessary
            final Integer deleted = entityValues.getAsInteger(Events.DELETED);
            final boolean isDeleted = deleted != null && deleted == 1;
            final Integer eventStatus = entityValues.getAsInteger(Events.STATUS);
            final boolean isCanceled =
                    eventStatus != null && eventStatus.equals(Events.STATUS_CANCELED);
            if (isDeleted || isCanceled) {
                s.data(Tags.CALENDAR_EXCEPTION_IS_DELETED, "1");
                // If we're deleted, the UI will continue to show this exception until we mark
                // it canceled, so we'll do that here...
                if (isDeleted && !isCanceled) {
                    final long eventId = entityValues.getAsLong(Events._ID);
                    final ContentValues cv = new ContentValues(1);
                    cv.put(Events.STATUS, Events.STATUS_CANCELED);
                    mContentResolver.update(
                            asSyncAdapter(ContentUris.withAppendedId(Events.CONTENT_URI, eventId)),
                            cv, null, null);
                }
            } else {
                s.data(Tags.CALENDAR_EXCEPTION_IS_DELETED, "0");
            }

            // TODO Add reminders to exceptions (allow them to be specified!)
            Long originalTime = entityValues.getAsLong(Events.ORIGINAL_INSTANCE_TIME);
            if (originalTime != null) {
                final boolean originalAllDay =
                    CalendarUtilities.getIntegerValueAsBoolean(entityValues,
                            Events.ORIGINAL_ALL_DAY);
                if (originalAllDay) {
                    // For all day events, we need our local all-day time
                    originalTime =
                        CalendarUtilities.getLocalAllDayCalendarTime(originalTime, localTimeZone);
                }
                s.data(Tags.CALENDAR_EXCEPTION_START_TIME,
                        CalendarUtilities.millisToEasDateTime(originalTime));
            } else {
                // Illegal; what should we do?
            }
        }

        if (!isException) {
            // A time zone is required in all EAS events; we'll use the default if none is set
            // Exchange 2003 seems to require this first... :-)
            String timeZoneName = entityValues.getAsString(
                    allDay ? EVENT_SAVED_TIMEZONE_COLUMN : Events.EVENT_TIMEZONE);
            if (timeZoneName == null) {
                timeZoneName = localTimeZone.getID();
            }
            s.data(Tags.CALENDAR_TIME_ZONE,
                    CalendarUtilities.timeZoneToTziString(TimeZone.getTimeZone(timeZoneName)));
        }

        s.data(Tags.CALENDAR_ALL_DAY_EVENT, allDay ? "1" : "0");

        // DTSTART is always supplied
        long startTime = entityValues.getAsLong(Events.DTSTART);
        // Determine endTime; it's either provided as DTEND or we calculate using DURATION
        // If no DURATION is provided, we default to one hour
        long endTime;
        if (entityValues.containsKey(Events.DTEND)) {
            endTime = entityValues.getAsLong(Events.DTEND);
        } else {
            long durationMillis = DateUtils.HOUR_IN_MILLIS;
            if (entityValues.containsKey(Events.DURATION)) {
                final Duration duration = new Duration();
                try {
                    duration.parse(entityValues.getAsString(Events.DURATION));
                    durationMillis = duration.getMillis();
                } catch (DateException e) {
                    // Can't do much about this; use the default (1 hour)
                }
            }
            endTime = startTime + durationMillis;
        }
        if (allDay) {
            startTime = CalendarUtilities.getLocalAllDayCalendarTime(startTime, localTimeZone);
            endTime = CalendarUtilities.getLocalAllDayCalendarTime(endTime, localTimeZone);
        }
        s.data(Tags.CALENDAR_START_TIME, CalendarUtilities.millisToEasDateTime(startTime));
        s.data(Tags.CALENDAR_END_TIME, CalendarUtilities.millisToEasDateTime(endTime));

        s.data(Tags.CALENDAR_DTSTAMP,
                CalendarUtilities.millisToEasDateTime(System.currentTimeMillis()));

        String loc = entityValues.getAsString(Events.EVENT_LOCATION);
        if (!TextUtils.isEmpty(loc)) {
            if (getProtocolVersion() < Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
                // EAS 2.5 doesn't like bare line feeds
                loc = Utility.replaceBareLfWithCrlf(loc);
            }
            s.data(Tags.CALENDAR_LOCATION, loc);
        }
        s.writeStringValue(entityValues, Events.TITLE, Tags.CALENDAR_SUBJECT);

        if (getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
            s.start(Tags.BASE_BODY);
            s.data(Tags.BASE_TYPE, "1");
            s.writeStringValue(entityValues, Events.DESCRIPTION, Tags.BASE_DATA);
            s.end();
        } else {
            // EAS 2.5 doesn't like bare line feeds
            s.writeStringValue(entityValues, Events.DESCRIPTION, Tags.CALENDAR_BODY);
        }

        if (!isException) {
            // For Exchange 2003, only upsync if the event is new
            if ((getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) || !isChange) {
                s.writeStringValue(entityValues, Events.ORGANIZER, Tags.CALENDAR_ORGANIZER_EMAIL);
            }

            final String rrule = entityValues.getAsString(Events.RRULE);
            if (rrule != null) {
                CalendarUtilities.recurrenceFromRrule(rrule, startTime, s);
            }

            // Handle associated data EXCEPT for attendees, which have to be grouped
            final ArrayList<Entity.NamedContentValues> subValues = entity.getSubValues();
            // The earliest of the reminders for this Event; we can only send one reminder...
            int earliestReminder = -1;
            for (final Entity.NamedContentValues ncv: subValues) {
                final Uri ncvUri = ncv.uri;
                final ContentValues ncvValues = ncv.values;
                if (ncvUri.equals(ExtendedProperties.CONTENT_URI)) {
                    final String propertyName = ncvValues.getAsString(ExtendedProperties.NAME);
                    final String propertyValue = ncvValues.getAsString(ExtendedProperties.VALUE);
                    if (TextUtils.isEmpty(propertyValue)) {
                        continue;
                    }
                    if (propertyName.equals(EXTENDED_PROPERTY_CATEGORIES)) {
                        // Send all the categories back to the server
                        // We've saved them as a String of delimited tokens
                        final StringTokenizer st =
                            new StringTokenizer(propertyValue, CATEGORY_TOKENIZER_DELIMITER);
                        if (st.countTokens() > 0) {
                            s.start(Tags.CALENDAR_CATEGORIES);
                            while (st.hasMoreTokens()) {
                                s.data(Tags.CALENDAR_CATEGORY, st.nextToken());
                            }
                            s.end();
                        }
                    }
                } else if (ncvUri.equals(Reminders.CONTENT_URI)) {
                    Integer mins = ncvValues.getAsInteger(Reminders.MINUTES);
                    if (mins != null) {
                        // -1 means "default", which for Exchange, is 30
                        if (mins < 0) {
                            mins = 30;
                        }
                        // Save this away if it's the earliest reminder (greatest minutes)
                        if (mins > earliestReminder) {
                            earliestReminder = mins;
                        }
                    }
                }
            }

            // If we have a reminder, send it to the server
            if (earliestReminder >= 0) {
                s.data(Tags.CALENDAR_REMINDER_MINS_BEFORE, Integer.toString(earliestReminder));
            }

            // We've got to send a UID, unless this is an exception.  If the event is new, we've
            // generated one; if not, we should have gotten one from extended properties.
            if (clientId != null) {
                s.data(Tags.CALENDAR_UID, clientId);
            }

            // Handle attendee data here; keep track of organizer and stream it afterward
            String organizerName = null;
            String organizerEmail = null;
            for (final Entity.NamedContentValues ncv: subValues) {
                final Uri ncvUri = ncv.uri;
                final ContentValues ncvValues = ncv.values;
                if (ncvUri.equals(Attendees.CONTENT_URI)) {
                    final Integer relationship =
                            ncvValues.getAsInteger(Attendees.ATTENDEE_RELATIONSHIP);
                    // If there's no relationship, we can't create this for EAS
                    // Similarly, we need an attendee email for each invitee
                    if (relationship != null && ncvValues.containsKey(Attendees.ATTENDEE_EMAIL)) {
                        // Organizer isn't among attendees in EAS
                        if (relationship == Attendees.RELATIONSHIP_ORGANIZER) {
                            organizerName = ncvValues.getAsString(Attendees.ATTENDEE_NAME);
                            organizerEmail = ncvValues.getAsString(Attendees.ATTENDEE_EMAIL);
                            continue;
                        }
                        if (!hasAttendees) {
                            s.start(Tags.CALENDAR_ATTENDEES);
                            hasAttendees = true;
                        }
                        s.start(Tags.CALENDAR_ATTENDEE);
                        final String attendeeEmail =
                                ncvValues.getAsString(Attendees.ATTENDEE_EMAIL);
                        String attendeeName = ncvValues.getAsString(Attendees.ATTENDEE_NAME);
                        if (attendeeName == null) {
                            attendeeName = attendeeEmail;
                        }
                        s.data(Tags.CALENDAR_ATTENDEE_NAME, attendeeName);
                        s.data(Tags.CALENDAR_ATTENDEE_EMAIL, attendeeEmail);
                        if (getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
                            s.data(Tags.CALENDAR_ATTENDEE_TYPE, "1"); // Required
                        }
                        s.end(); // Attendee
                     }
                }
            }
            if (hasAttendees) {
                s.end();  // Attendees
            }

            // Get busy status from availability
            final int availability = entityValues.getAsInteger(Events.AVAILABILITY);
            final int busyStatus = CalendarUtilities.busyStatusFromAvailability(availability);
            s.data(Tags.CALENDAR_BUSY_STATUS, Integer.toString(busyStatus));

            // Meeting status, 0 = appointment, 1 = meeting, 3 = attendee
            // In JB, organizer won't be an attendee
            if (organizerEmail == null && entityValues.containsKey(Events.ORGANIZER)) {
                organizerEmail = entityValues.getAsString(Events.ORGANIZER);
            }
            if (mAccount.mEmailAddress.equalsIgnoreCase(organizerEmail)) {
                s.data(Tags.CALENDAR_MEETING_STATUS, hasAttendees ? "1" : "0");
            } else {
                s.data(Tags.CALENDAR_MEETING_STATUS, "3");
            }

            // For Exchange 2003, only upsync if the event is new
            if (((getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) || !isChange) &&
                    organizerName != null) {
                s.data(Tags.CALENDAR_ORGANIZER_NAME, organizerName);
            }

            // NOTE: Sensitivity must NOT be sent to the server for exceptions in Exchange 2003
            // The result will be a status 6 failure during sync
            final Integer visibility = entityValues.getAsInteger(Events.ACCESS_LEVEL);
            if (visibility != null) {
                s.data(Tags.CALENDAR_SENSITIVITY, decodeVisibility(visibility));
            } else {
                // Default to private if not set
                s.data(Tags.CALENDAR_SENSITIVITY, "1");
            }
        }
    }

    /**
     * Handle exceptions to an event's recurrance pattern.
     * @param s The {@link Serializer} for this upsync.
     * @param entity The {@link Entity} for this event.
     * @param entityValues The {@link ContentValues} for entity.
     * @param serverId The server side id for this event.
     * @param clientId The client side id for this event.
     * @param calendarIdString The calendar id, as a {@link String}.
     * @param selfOrganizer Whether the user is the organizer of this event.
     * @throws IOException
     */
    private void handleExceptionsToRecurrenceRules(final Serializer s, final Entity entity,
            final ContentValues entityValues, final String serverId, final String clientId,
            final String calendarIdString, final boolean selfOrganizer) throws IOException {
        final EntityIterator exIterator = EventsEntity.newEntityIterator(mContentResolver.query(
                asSyncAdapter(Events.CONTENT_URI), null, ORIGINAL_EVENT_AND_CALENDAR,
                new String[] { serverId, calendarIdString }, null), mContentResolver);
        boolean exFirst = true;
        while (exIterator.hasNext()) {
            final Entity exEntity = exIterator.next();
            if (exFirst) {
                s.start(Tags.CALENDAR_EXCEPTIONS);
                exFirst = false;
            }
            s.start(Tags.CALENDAR_EXCEPTION);
            sendEvent(exEntity, null, s);
            final ContentValues exValues = exEntity.getEntityValues();
            if (getInt(exValues, Events.DIRTY) == 1) {
                // This is a new/updated exception, so we've got to notify our
                // attendees about it
                final long exEventId = exValues.getAsLong(Events._ID);

                // Copy subvalues into the exception; otherwise, we won't see the
                // attendees when preparing the message
                for (final Entity.NamedContentValues ncv: entity.getSubValues()) {
                    exEntity.addSubValue(ncv.uri, ncv.values);
                }

                final int flag;
                if ((getInt(exValues, Events.DELETED) == 1) ||
                        (getInt(exValues, Events.STATUS) == Events.STATUS_CANCELED)) {
                    flag = Message.FLAG_OUTGOING_MEETING_CANCEL;
                    if (!selfOrganizer) {
                        // Send a cancellation notice to the organizer
                        // Since CalendarProvider2 sets the organizer of exceptions
                        // to the user, we have to reset it first to the original
                        // organizer
                        exValues.put(Events.ORGANIZER, entityValues.getAsString(Events.ORGANIZER));
                        sendDeclinedEmail(exEntity, clientId);
                    }
                } else {
                    flag = Message.FLAG_OUTGOING_MEETING_INVITE;
                }
                // Add the eventId of the exception to the uploaded id list, so that
                // the dirty/mark bits are cleared
                mUploadedIdList.add(exEventId);

                // Copy version so the ics attachment shows the proper sequence #
                exValues.put(EVENT_SYNC_VERSION,
                        entityValues.getAsString(EVENT_SYNC_VERSION));
                // Copy location so that it's included in the outgoing email
                if (entityValues.containsKey(Events.EVENT_LOCATION)) {
                    exValues.put(Events.EVENT_LOCATION,
                            entityValues.getAsString(Events.EVENT_LOCATION));
                }

                if (selfOrganizer) {
                    final Message msg = CalendarUtilities.createMessageForEntity(mContext, exEntity,
                            flag, clientId, mAccount);
                    if (msg != null) {
                        LogUtils.i(TAG, "Queueing exception update to %s", msg.mTo);
                        mOutgoingMailList.add(msg);
                    }
                }
            }
            s.end(); // EXCEPTION
        }
        if (!exFirst) {
            s.end(); // EXCEPTIONS
        }
    }

    /**
     * Update the event properties with the attendee list, and send mail as appropriate.
     * @param entity The {@link Entity} for this event.
     * @param entityValues The {@link ContentValues} for entity.
     * @param selfOrganizer Whether the user is the organizer of this event.
     * @param eventId The id for this event.
     * @param clientId The client side id for this event.
     */
    private void updateAttendeesAndSendMail(final Entity entity, final ContentValues entityValues,
            final boolean selfOrganizer, final long eventId, final String clientId) {
        // Go through the extended properties of this Event and pull out our tokenized
        // attendees list and the user attendee status; we will need them later
        String attendeeString = null;
        long attendeeStringId = -1;
        String userAttendeeStatus = null;
        long userAttendeeStatusId = -1;
        for (final Entity.NamedContentValues ncv: entity.getSubValues()) {
            if (ncv.uri.equals(ExtendedProperties.CONTENT_URI)) {
                final ContentValues ncvValues = ncv.values;
                final String propertyName = ncvValues.getAsString(ExtendedProperties.NAME);
                if (propertyName.equals(EXTENDED_PROPERTY_ATTENDEES)) {
                    attendeeString = ncvValues.getAsString(ExtendedProperties.VALUE);
                    attendeeStringId = ncvValues.getAsLong(ExtendedProperties._ID);
                } else if (propertyName.equals(EXTENDED_PROPERTY_USER_ATTENDEE_STATUS)) {
                    userAttendeeStatus = ncvValues.getAsString(ExtendedProperties.VALUE);
                    userAttendeeStatusId = ncvValues.getAsLong(ExtendedProperties._ID);
                }
            }
        }

        // Send the meeting invite if there are attendees and we're the organizer AND
        // if the Event itself is dirty (we might be syncing only because an exception
        // is dirty, in which case we DON'T send email about the Event)
        if (selfOrganizer && (getInt(entityValues, Events.DIRTY) == 1)) {
            final Message msg =
                CalendarUtilities.createMessageForEventId(mContext, eventId,
                        Message.FLAG_OUTGOING_MEETING_INVITE, clientId, mAccount);
            if (msg != null) {
                LogUtils.i(TAG, "Queueing invitation to %s", msg.mTo);
                mOutgoingMailList.add(msg);
            }
            // Make a list out of our tokenized attendees, if we have any
            final ArrayList<String> originalAttendeeList = new ArrayList<String>();
            if (attendeeString != null) {
                final StringTokenizer st =
                    new StringTokenizer(attendeeString, ATTENDEE_TOKENIZER_DELIMITER);
                while (st.hasMoreTokens()) {
                    originalAttendeeList.add(st.nextToken());
                }
            }
            final StringBuilder newTokenizedAttendees = new StringBuilder();
            // See if any attendees have been dropped and while we're at it, build
            // an updated String with tokenized attendee addresses
            for (final Entity.NamedContentValues ncv: entity.getSubValues()) {
                if (ncv.uri.equals(Attendees.CONTENT_URI)) {
                    final String attendeeEmail = ncv.values.getAsString(Attendees.ATTENDEE_EMAIL);
                    // Remove all found attendees
                    originalAttendeeList.remove(attendeeEmail);
                    newTokenizedAttendees.append(attendeeEmail);
                    newTokenizedAttendees.append(ATTENDEE_TOKENIZER_DELIMITER);
                }
            }
            // Update extended properties with the new attendee list, if we have one
            // Otherwise, create one (this would be the case for Events created on
            // device or "legacy" events (before this code was added)
            final ContentValues cv = new ContentValues();
            cv.put(ExtendedProperties.VALUE, newTokenizedAttendees.toString());
            if (attendeeString != null) {
                mContentResolver.update(asSyncAdapter(ContentUris.withAppendedId(
                        ExtendedProperties.CONTENT_URI, attendeeStringId)), cv, null, null);
            } else {
                // If there wasn't an "attendees" property, insert one
                cv.put(ExtendedProperties.NAME, EXTENDED_PROPERTY_ATTENDEES);
                cv.put(ExtendedProperties.EVENT_ID, eventId);
                mContentResolver.insert(asSyncAdapter(ExtendedProperties.CONTENT_URI), cv);
            }
            // Whoever is left has been removed from the attendee list; send them
            // a cancellation
            for (final String removedAttendee: originalAttendeeList) {
                // Send a cancellation message to each of them
                final Message cancelMsg = CalendarUtilities.createMessageForEventId(mContext,
                        eventId, Message.FLAG_OUTGOING_MEETING_CANCEL, clientId, mAccount,
                        removedAttendee);
                if (cancelMsg != null) {
                    // Just send it to the removed attendee
                    LogUtils.i(TAG, "Queueing cancellation to removed attendee %s", cancelMsg.mTo);
                    mOutgoingMailList.add(cancelMsg);
                }
            }
        } else if (!selfOrganizer) {
            // If we're not the organizer, see if we've changed our attendee status
            // Our last synced attendee status is in ExtendedProperties, and we've
            // retrieved it above as userAttendeeStatus
            final int currentStatus = entityValues.getAsInteger(Events.SELF_ATTENDEE_STATUS);
            int syncStatus = Attendees.ATTENDEE_STATUS_NONE;
            if (userAttendeeStatus != null) {
                try {
                    syncStatus = Integer.parseInt(userAttendeeStatus);
                } catch (NumberFormatException e) {
                    // Just in case somebody else mucked with this and it's not Integer
                }
            }
            if ((currentStatus != syncStatus) &&
                    (currentStatus != Attendees.ATTENDEE_STATUS_NONE)) {
                // If so, send a meeting reply
                final int messageFlag;
                switch (currentStatus) {
                    case Attendees.ATTENDEE_STATUS_ACCEPTED:
                        messageFlag = Message.FLAG_OUTGOING_MEETING_ACCEPT;
                        break;
                    case Attendees.ATTENDEE_STATUS_DECLINED:
                        messageFlag = Message.FLAG_OUTGOING_MEETING_DECLINE;
                        break;
                    case Attendees.ATTENDEE_STATUS_TENTATIVE:
                        messageFlag = Message.FLAG_OUTGOING_MEETING_TENTATIVE;
                        break;
                    default:
                        messageFlag = 0;
                        break;
                }
                // Make sure we have a valid status (messageFlag should never be zero)
                if (messageFlag != 0 && userAttendeeStatusId >= 0) {
                    // Save away the new status
                    final ContentValues cv = new ContentValues(1);
                    cv.put(ExtendedProperties.VALUE, Integer.toString(currentStatus));
                    mContentResolver.update(asSyncAdapter(ContentUris.withAppendedId(
                            ExtendedProperties.CONTENT_URI, userAttendeeStatusId)),
                            cv, null, null);
                    // Send mail to the organizer advising of the new status
                    final Message msg = CalendarUtilities.createMessageForEventId(mContext, eventId,
                            messageFlag, clientId, mAccount);
                    if (msg != null) {
                        LogUtils.i(TAG, "Queueing invitation reply to %s", msg.mTo);
                        mOutgoingMailList.add(msg);
                    }
                }
            }
        }
    }

    /**
     * Process a single event, adding to the {@link Serializer} as necessary.
     * @param s The {@link Serializer} for this Sync request.
     * @param entity The {@link Entity} for this event.
     * @param calendarIdString The calendar's id, as a {@link String}.
     * @param first Whether this would be the first event added to s.
     * @return Whether this function added anything to s.
     * @throws IOException
     */
    private boolean handleEntity(final Serializer s, final Entity entity,
            final String calendarIdString, final boolean first) throws IOException {
        // For each of these entities, create the change commands
        final ContentValues entityValues = entity.getEntityValues();
        // We first need to check whether we can upsync this event; our test for this
        // is currently the value of EXTENDED_PROPERTY_ATTENDEES_REDACTED
        // If this is set to "1", we can't upsync the event
        for (final Entity.NamedContentValues ncv: entity.getSubValues()) {
            if (ncv.uri.equals(ExtendedProperties.CONTENT_URI)) {
                final ContentValues ncvValues = ncv.values;
                if (ncvValues.getAsString(ExtendedProperties.NAME).equals(
                        EXTENDED_PROPERTY_UPSYNC_PROHIBITED)) {
                    if ("1".equals(ncvValues.getAsString(ExtendedProperties.VALUE))) {
                        // Make sure we mark this to clear the dirty flag
                        mUploadedIdList.add(entityValues.getAsLong(Events._ID));
                        return false;
                    }
                }
            }
        }

        // EAS 2.5 needs: BusyStatus DtStamp EndTime Sensitivity StartTime TimeZone UID
        // We can generate all but what we're testing for below
        final String organizerEmail = entityValues.getAsString(Events.ORGANIZER);
        if (organizerEmail == null || !entityValues.containsKey(Events.DTSTART) ||
                (!entityValues.containsKey(Events.DURATION)
                        && !entityValues.containsKey(Events.DTEND))) {
            return false;
        }

        if (first) {
            s.start(Tags.SYNC_COMMANDS);
            LogUtils.i(TAG, "Sending Calendar changes to the server");
        }

        final boolean selfOrganizer = organizerEmail.equalsIgnoreCase(mAccount.mEmailAddress);
        // Find our uid in the entity; otherwise create one
        String clientId = entityValues.getAsString(Events.SYNC_DATA2);
        if (clientId == null) {
            clientId = UUID.randomUUID().toString();
        }
        final String serverId = entityValues.getAsString(Events._SYNC_ID);
        final long eventId = entityValues.getAsLong(Events._ID);
        if (serverId == null) {
            // This is a new event; create a clientId
            LogUtils.i(TAG, "Creating new event with clientId: %s", clientId);
            s.start(Tags.SYNC_ADD).data(Tags.SYNC_CLIENT_ID, clientId);
            // And save it in the Event as the local id
            final ContentValues cv = new ContentValues(2);
            cv.put(Events.SYNC_DATA2, clientId);
            cv.put(EVENT_SYNC_VERSION, "0");
            mContentResolver.update(
                    asSyncAdapter(ContentUris.withAppendedId(Events.CONTENT_URI, eventId)),
                    cv, null, null);
        } else if (entityValues.getAsInteger(Events.DELETED) == 1) {
            LogUtils.i(TAG, "Deleting event with serverId: %s", serverId);
            s.start(Tags.SYNC_DELETE).data(Tags.SYNC_SERVER_ID, serverId).end();
            mDeletedIdList.add(eventId);
            if (selfOrganizer) {
                final Message msg = CalendarUtilities.createMessageForEventId(mContext,
                        eventId, Message.FLAG_OUTGOING_MEETING_CANCEL, null, mAccount);
                if (msg != null) {
                    LogUtils.i(TAG, "Queueing cancellation to %s", msg.mTo);
                    mOutgoingMailList.add(msg);
                }
            } else {
                sendDeclinedEmail(entity, clientId);
            }
            // For deletions, we don't need to add application data, so just bail here.
            return true;
        } else {
            LogUtils.i(TAG, "Upsync change to event with serverId: %s", serverId);
            s.start(Tags.SYNC_CHANGE).data(Tags.SYNC_SERVER_ID, serverId);
            // Save to the ContentResolver.
            final String version = getEntityVersion(entityValues);
            final ContentValues cv = new ContentValues(1);
            cv.put(EVENT_SYNC_VERSION, version);
            mContentResolver.update(
                    asSyncAdapter( ContentUris.withAppendedId(Events.CONTENT_URI, eventId)),
                    cv, null, null);
            // Also save in entityValues so that we send it this time around
            entityValues.put(EVENT_SYNC_VERSION, version);
        }
        s.start(Tags.SYNC_APPLICATION_DATA);
        sendEvent(entity, clientId, s);

        // Now, the hard part; find exceptions for this event
        if (serverId != null) {
            handleExceptionsToRecurrenceRules(s, entity, entityValues, serverId, clientId,
                    calendarIdString, selfOrganizer);
        }

        s.end().end();  // ApplicationData & Add/Change
        mUploadedIdList.add(eventId);
        updateAttendeesAndSendMail(entity, entityValues, selfOrganizer, eventId, clientId);
        return true;
    }

    @Override
    protected void setUpsyncCommands(final Serializer s) throws IOException {
        final String calendarIdString = Long.toString(mCalendarId);
        final String[] calendarIdArgument = { calendarIdString };

        markParentsOfDirtyEvents(calendarIdString, calendarIdArgument);

        // Now go through dirty/marked top-level events and send them back to the server
        final EntityIterator eventIterator = EventsEntity.newEntityIterator(
                mContentResolver.query(asSyncAdapter(Events.CONTENT_URI), null,
                DIRTY_OR_MARKED_TOP_LEVEL_IN_CALENDAR, calendarIdArgument, null), mContentResolver);

        try {
            boolean first = true;
            while (eventIterator.hasNext()) {
                final boolean addedCommand =
                        handleEntity(s, eventIterator.next(), calendarIdString, first);
                if (addedCommand) {
                    first = false;
                }
            }
            if (!first) {
                s.end();  // Commands
            }
        } finally {
            eventIterator.close();
        }
    }

    @Override
    protected void cleanup(final int syncResult) {
        if (syncResult != SYNC_RESULT_FAILED) {
            // Clear dirty and mark flags for updates sent to server
            if (!mUploadedIdList.isEmpty()) {
                final ContentValues cv = new ContentValues(2);
                cv.put(Events.DIRTY, 0);
                cv.put(EVENT_SYNC_MARK, "0");
                for (final long eventId : mUploadedIdList) {
                    mContentResolver.update(asSyncAdapter(ContentUris.withAppendedId(
                            Events.CONTENT_URI, eventId)), cv, null, null);
                }
            }
            // Delete events marked for deletion
            if (!mDeletedIdList.isEmpty()) {
                for (final long eventId : mDeletedIdList) {
                    mContentResolver.delete(asSyncAdapter(ContentUris.withAppendedId(
                            Events.CONTENT_URI, eventId)), null, null);
                }
            }
            // Send all messages that were created during this sync.
            for (final Message msg : mOutgoingMailList) {
                sendMessage(mAccount, msg);
            }
        }
        // Clear our lists for the next Sync request, if necessary.
        if (syncResult != SYNC_RESULT_MORE_AVAILABLE) {
            mDeletedIdList.clear();
            mUploadedIdList.clear();
            mOutgoingMailList.clear();
        }
    }

    /**
     * Delete an account from the Calendar provider.
     * @param context Our {@link Context}
     * @param emailAddress The email address of the account we wish to delete
     */
    public static void wipeAccountFromContentProvider(final Context context,
            final String emailAddress) {
        context.getContentResolver().delete(asSyncAdapter(Calendars.CONTENT_URI, emailAddress),
                Calendars.ACCOUNT_NAME + "=" + DatabaseUtils.sqlEscapeString(emailAddress)
                        + " AND " + Calendars.ACCOUNT_TYPE + "="+ DatabaseUtils.sqlEscapeString(
                        context.getString(R.string.account_manager_type_exchange)), null);
    }
}
