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 = Eas.LOG_TAG;

    // 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, int numWindows) throws IOException {
        final int windowSize = numWindows * PIM_WINDOW_SIZE_CALENDAR;
        if (windowSize > MAX_WINDOW_SIZE  + PIM_WINDOW_SIZE_CALENDAR) {
            throw new IOException("Max window size reached and still no data");
        }
        setPimSyncOptions(s, Eas.FILTER_2_WEEKS,
                windowSize < MAX_WINDOW_SIZE ? windowSize : MAX_WINDOW_SIZE);
    }

    /**
     * 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, localTimeZone, 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);
    }
}
