package com.android.exchange.service;

import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.Context;
import android.content.OperationApplicationException;
import android.content.SyncResult;
import android.database.Cursor;
import android.os.Bundle;
import android.os.RemoteException;
import android.text.format.DateUtils;

import com.android.emailcommon.TrafficFlags;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Message;
import com.android.emailcommon.provider.EmailContent.MessageColumns;
import com.android.emailcommon.provider.EmailContent.SyncColumns;
import com.android.emailcommon.provider.Mailbox;
import com.android.emailcommon.service.SyncWindow;
import com.android.exchange.Eas;
import com.android.exchange.EasAuthenticationException;
import com.android.exchange.EasResponse;
import com.android.exchange.adapter.AbstractSyncParser;
import com.android.exchange.adapter.EmailSyncAdapter.EasEmailSyncParser;
import com.android.exchange.adapter.MoveItemsParser;
import com.android.exchange.adapter.Serializer;
import com.android.exchange.adapter.Tags;
import com.android.mail.utils.LogUtils;

import org.apache.http.HttpStatus;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;

/**
 * Performs an Exchange mailbox sync for "normal" mailboxes.
 */
public class EasMailboxSyncHandler extends EasSyncHandler {
    private static final String TAG = "EasMailboxSyncHandler";

    /**
     * The projection used for building the fetch request list.
     */
    private static final String[] FETCH_REQUEST_PROJECTION = { SyncColumns.SERVER_ID };
    private static final int FETCH_REQUEST_SERVER_ID = 0;

    /**
     * The projection used for querying message tables for the purpose of determining what needs
     * to be set as a sync update.
     */
    private static final String[] UPDATES_PROJECTION = { MessageColumns.ID,
            MessageColumns.MAILBOX_KEY, SyncColumns.SERVER_ID,
            MessageColumns.FLAGS, MessageColumns.FLAG_READ, MessageColumns.FLAG_FAVORITE };
    private static final int UPDATES_ID_COLUMN = 0;
    private static final int UPDATES_MAILBOX_KEY_COLUMN = 1;
    private static final int UPDATES_SERVER_ID_COLUMN = 2;
    private static final int UPDATES_FLAG_COLUMN = 3;
    private static final int UPDATES_READ_COLUMN = 4;
    private static final int UPDATES_FAVORITE_COLUMN = 5;

    /**
     * Message flags value to signify that the message has been moved, and eventually needs to be
     * deleted.
     */
    public static final int MESSAGE_FLAG_MOVED_MESSAGE = 1 << Message.FLAG_SYNC_ADAPTER_SHIFT;

    /**
     * The selection for moved messages that get deleted after a successful sync.
     */
    private static final String WHERE_MAILBOX_KEY_AND_MOVED =
            MessageColumns.MAILBOX_KEY + "=? AND (" + MessageColumns.FLAGS + "&" +
            MESSAGE_FLAG_MOVED_MESSAGE + ")!=0";

    private static final String EMAIL_WINDOW_SIZE = "5";

    private static final String WHERE_BODY_SOURCE_MESSAGE_KEY =
            EmailContent.Body.SOURCE_MESSAGE_KEY + "=?";

    // State needed across multiple functions during a Sync.
    // TODO: We should perhaps invert the meaning of mDeletedMessages & mUpdatedMessages and
    // store the values we want to *retain* after a successful upsync.

    /**
     * List of message ids that were read from Message_Deletes and were sent in the Commands section
     * of the current sync.
     */
    private final ArrayList<Long> mDeletedMessages = new ArrayList<Long>();

    /**
     * List of message ids that were read from Message_Updates and were sent in the Commands section
     * of the current sync.
     */
    private final ArrayList<Long> mUpdatedMessages = new ArrayList<Long>();

    /**
     * List of server ids for messages to fetch from the server.
     */
    private final ArrayList<String> mMessagesToFetch = new ArrayList<String>();

    /**
     * Holds all the data needed to process a MoveItems request.
     */
    private static class MoveRequest {
        public final long messageId;
        public final String messageServerId;
        public final int messageFlags;
        public final long sourceFolderId;
        public final String sourceFolderServerId;
        public final String destFolderServerId;

        public MoveRequest(final long _messageId, final String _messageServerId,
                final int _messageFlags,
                final long _sourceFolderId, final String _sourceFolderServerId,
                final String _destFolderServerId) {
            messageId = _messageId;
            messageServerId = _messageServerId;
            messageFlags = _messageFlags;
            sourceFolderId = _sourceFolderId;
            sourceFolderServerId = _sourceFolderServerId;
            destFolderServerId = _destFolderServerId;
        }
    }

    /**
     * List of all MoveRequests, i.e. all messages which have different mailboxes than they used to.
     */
    private final ArrayList<MoveRequest> mMessagesToMove = new ArrayList<MoveRequest>();

    public EasMailboxSyncHandler(final Context context, final ContentResolver contentResolver,
            final Account account, final Mailbox mailbox, final Bundle syncExtras,
            final SyncResult syncResult) {
        super(context, contentResolver, account, mailbox, syncExtras, syncResult);
    }

    private String getEmailFilter() {
        int syncLookback = mMailbox.mSyncLookback;
        if (syncLookback == SyncWindow.SYNC_WINDOW_UNKNOWN
                || mMailbox.mType == Mailbox.TYPE_INBOX) {
            syncLookback = mAccount.mSyncLookback;
        }
        switch (syncLookback) {
            case SyncWindow.SYNC_WINDOW_1_DAY:
                return Eas.FILTER_1_DAY;
            case SyncWindow.SYNC_WINDOW_3_DAYS:
                return Eas.FILTER_3_DAYS;
            case SyncWindow.SYNC_WINDOW_1_WEEK:
                return Eas.FILTER_1_WEEK;
            case SyncWindow.SYNC_WINDOW_2_WEEKS:
                return Eas.FILTER_2_WEEKS;
            case SyncWindow.SYNC_WINDOW_1_MONTH:
                return Eas.FILTER_1_MONTH;
            case SyncWindow.SYNC_WINDOW_ALL:
                return Eas.FILTER_ALL;
            default:
                // Auto window is deprecated and will also use the default.
                return Eas.FILTER_1_WEEK;
        }
    }

    /**
     * Find partially loaded messages and add their server ids to {@link #mMessagesToFetch}.
     */
    private void addToFetchRequestList() {
        final Cursor c = mContentResolver.query(Message.CONTENT_URI, FETCH_REQUEST_PROJECTION,
                MessageColumns.FLAG_LOADED + "=" + Message.FLAG_LOADED_PARTIAL + " AND " +
                MessageColumns.MAILBOX_KEY + "=?", new String[] {Long.toString(mMailbox.mId)},
                null);
        if (c != null) {
            try {
                while (c.moveToNext()) {
                    mMessagesToFetch.add(c.getString(FETCH_REQUEST_SERVER_ID));
                }
            } finally {
                c.close();
            }
        }
    }

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

    @Override
    protected String getSyncKey() {
        if (mMailbox == null) {
            return null;
        }
        if (mMailbox.mSyncKey == null) {
            // TODO: Write to DB? Probably not, and just let successful sync do that.
            mMailbox.mSyncKey = "0";
        }
        return mMailbox.mSyncKey;
    }

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

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

    @Override
    protected void setInitialSyncOptions(final Serializer s) {
        // No-op.
    }

    @Override
    protected void setNonInitialSyncOptions(final Serializer s) throws IOException {
        // Check for messages that aren't fully loaded.
        addToFetchRequestList();
        // The "empty" case is typical; we send a request for changes, and also specify a sync
        // window, body preference type (HTML for EAS 12.0 and later; MIME for EAS 2.5), and
        // truncation
        // If there are fetch requests, we only want the fetches (i.e. no changes from the server)
        // so we turn MIME support off.  Note that we are always using EAS 2.5 if there are fetch
        // requests
        if (mMessagesToFetch.isEmpty()) {
            // Permanently delete if in trash mailbox
            // In Exchange 2003, deletes-as-moves tag = true; no tag = false
            // In Exchange 2007 and up, deletes-as-moves tag is "0" (false) or "1" (true)
            final boolean isTrashMailbox = mMailbox.mType == Mailbox.TYPE_TRASH;
            if (getProtocolVersion() < Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
                if (!isTrashMailbox) {
                    s.tag(Tags.SYNC_DELETES_AS_MOVES);
                }
            } else {
                s.data(Tags.SYNC_DELETES_AS_MOVES, isTrashMailbox ? "0" : "1");
            }
            s.tag(Tags.SYNC_GET_CHANGES);
            s.data(Tags.SYNC_WINDOW_SIZE, EMAIL_WINDOW_SIZE);
            s.start(Tags.SYNC_OPTIONS);
            // Set the lookback appropriately (EAS calls this a "filter")
            s.data(Tags.SYNC_FILTER_TYPE, getEmailFilter());
            // Set the truncation amount for all classes
            if (getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
                s.start(Tags.BASE_BODY_PREFERENCE);
                // HTML for email
                s.data(Tags.BASE_TYPE, Eas.BODY_PREFERENCE_HTML);
                s.data(Tags.BASE_TRUNCATION_SIZE, Eas.EAS12_TRUNCATION_SIZE);
                s.end();
            } else {
                // Use MIME data for EAS 2.5
                s.data(Tags.SYNC_MIME_SUPPORT, Eas.MIME_BODY_PREFERENCE_MIME);
                s.data(Tags.SYNC_MIME_TRUNCATION, Eas.EAS2_5_TRUNCATION_SIZE);
            }
            s.end();
        } else {
            // If we have any messages that are not fully loaded, ask for plain text rather than
            // MIME, to guarantee we'll get usable text body. This also means we should NOT ask for
            // new messages -- we only want data for the message explicitly fetched.
            s.start(Tags.SYNC_OPTIONS);
            s.data(Tags.SYNC_MIME_SUPPORT, Eas.MIME_BODY_PREFERENCE_TEXT);
            s.data(Tags.SYNC_TRUNCATION, Eas.EAS2_5_TRUNCATION_SIZE);
            s.end();
        }
    }

    /**
     * Check whether a message is referenced by another (and therefore must be kept around).
     * @param messageId The id of the message to check.
     * @return Whether the message in question is referenced by another message.
     */
    private boolean messageReferenced(final long messageId) {
        final Cursor c = mContentResolver.query(EmailContent.Body.CONTENT_URI,
                EmailContent.Body.ID_PROJECTION, WHERE_BODY_SOURCE_MESSAGE_KEY,
                new String[] {Long.toString(messageId)}, null);
        if (c != null) {
            try {
                return c.moveToFirst();
            } finally {
                c.close();
            }
        }
        return false;
    }

    /**
     * Write the command to delete a message to the {@link Serializer}.
     * @param s The {@link Serializer} for this sync command.
     * @param serverId The server id for the message to delete.
     * @param firstCommand Whether any sync commands have already been written to s.
     * @throws IOException
     */
    private void addDeleteMessageCommand(final Serializer s, final String serverId,
            final boolean firstCommand) throws IOException {
        if (firstCommand) {
            s.start(Tags.SYNC_COMMANDS);
        }
        s.start(Tags.SYNC_DELETE).data(Tags.SYNC_SERVER_ID, serverId).end();
    }

    /**
     * Adds a sync delete command for all messages in the Message_Deletes table.
     * @param s The {@link Serializer} for this sync command.
     * @param hasCommands Whether any Commands have already been written to s.
     * @return Whether this function wrote any commands to s.
     * @throws IOException
     */
    private boolean addDeletedCommands(final Serializer s, final boolean hasCommands)
            throws IOException {
        boolean wroteCommands = false;
        final Cursor c = mContentResolver.query(Message.DELETED_CONTENT_URI,
                Message.ID_COLUMNS_PROJECTION, MessageColumns.MAILBOX_KEY + '=' + mMailbox.mId,
                null, null);
        if (c != null) {
            try {
                while (c.moveToNext()) {
                    final String serverId = c.getString(Message.ID_COLUMNS_SYNC_SERVER_ID);
                    final long messageId = c.getLong(Message.ID_COLUMNS_ID_COLUMN);
                    // Only upsync delete commands for messages that have server ids and are not
                    // referenced by other messages.
                    if (serverId != null && !messageReferenced(messageId)) {
                        addDeleteMessageCommand(s, serverId, wroteCommands || hasCommands);
                        wroteCommands = true;
                        mDeletedMessages.add(messageId);
                    }
                }
            } finally {
                c.close();
            }
        }

        return wroteCommands;
    }

    /**
     * Create date/time in RFC8601 format.  Oddly enough, for calendar date/time, Microsoft uses
     * a different format that excludes the punctuation (this is why I'm not putting this in a
     * parent class)
     */
    private static String formatDateTime(final Calendar calendar) {
        final StringBuilder sb = new StringBuilder();
        //YYYY-MM-DDTHH:MM:SS.MSSZ
        sb.append(calendar.get(Calendar.YEAR));
        sb.append('-');
        sb.append(String.format(Locale.US, "%02d", calendar.get(Calendar.MONTH) + 1));
        sb.append('-');
        sb.append(String.format(Locale.US, "%02d", calendar.get(Calendar.DAY_OF_MONTH)));
        sb.append('T');
        sb.append(String.format(Locale.US, "%02d", calendar.get(Calendar.HOUR_OF_DAY)));
        sb.append(':');
        sb.append(String.format(Locale.US, "%02d", calendar.get(Calendar.MINUTE)));
        sb.append(':');
        sb.append(String.format(Locale.US, "%02d", calendar.get(Calendar.SECOND)));
        sb.append(".000Z");
        return sb.toString();
    }

    /**
     * Get the server id for a mailbox from the content provider.
     * @param mailboxId The id of the mailbox we're interested in.
     * @return The server id for the mailbox.
     */
    private String getServerIdForMailbox(final long mailboxId) {
        final Cursor c = mContentResolver.query(
                ContentUris.withAppendedId(Mailbox.CONTENT_URI, mailboxId),
                new String [] { EmailContent.MailboxColumns.SERVER_ID }, null, null, null);
        if (c != null) {
            try {
                if (c.moveToNext()) {
                    return c.getString(0);
                }
            } finally {
                c.close();
            }
        }
        return null;
    }

    /**
     * For a message that's in the Message_Updates table, add a sync command to the
     * {@link Serializer} if appropriate, and add the message to a list if it should be removed from
     * Message_Updates.
     * @param updatedMessageCursor The {@link Cursor} positioned at the message from Message_Updates
     *                             that we're processing.
     * @param s The {@link Serializer} for this sync command.
     * @param hasCommands Whether the {@link Serializer} already has sync commands added to it.
     * @param trashMailboxId The id for the trash mailbox.
     * @return Whether we added a sync command to s.
     * @throws IOException
     */
    private boolean handleOneUpdatedMessage(final Cursor updatedMessageCursor, final Serializer s,
            final boolean hasCommands, final long trashMailboxId) throws IOException {
        final long messageId = updatedMessageCursor.getLong(UPDATES_ID_COLUMN);
        // Get the current state of this message (updated table has original state).
        final Cursor currentCursor = mContentResolver.query(
                ContentUris.withAppendedId(Message.CONTENT_URI, messageId),
                UPDATES_PROJECTION, null, null, null);
        if (currentCursor == null) {
            // If, somehow, the message isn't still around, we still want to handle it as having
            // been updated so that it gets removed from the updated table.
            mUpdatedMessages.add(messageId);
            return false;
        }

        try {
            if (currentCursor.moveToFirst()) {
                final String serverId = currentCursor.getString(UPDATES_SERVER_ID_COLUMN);
                if (serverId == null) {
                    // No serverId means there's nothing to do, but we should still remove from the
                    // updated table.
                    mUpdatedMessages.add(messageId);
                    return false;
                }

                final long currentMailboxId = currentCursor.getLong(UPDATES_MAILBOX_KEY_COLUMN);
                final int currentFlags = currentCursor.getInt(UPDATES_FLAG_COLUMN);

                // Handle message deletion (i.e. move to trash).
                if (currentMailboxId == trashMailboxId) {
                    mUpdatedMessages.add(messageId);
                    addDeleteMessageCommand(s, serverId, !hasCommands);
                    // Also mark the message as moved in the DB (so the copy will be deleted if/when
                    // the server version is synced)
                    final ContentValues cv = new ContentValues(1);
                    cv.put(MessageColumns.FLAGS, currentFlags | MESSAGE_FLAG_MOVED_MESSAGE);
                    mContentResolver.update(
                            ContentUris.withAppendedId(Message.CONTENT_URI, messageId),
                            cv, null, null);
                    return true;
                }

                // Handle message moved.
                final long originalMailboxId =
                        updatedMessageCursor.getLong(UPDATES_MAILBOX_KEY_COLUMN);
                if (currentMailboxId != originalMailboxId) {
                    final String sourceMailboxId = getServerIdForMailbox(originalMailboxId);
                    final String destMailboxId;
                    if (sourceMailboxId != null) {
                        destMailboxId = getServerIdForMailbox(currentMailboxId);
                    } else {
                        destMailboxId = null;
                    }
                    if (destMailboxId != null) {
                        mMessagesToMove.add(
                                new MoveRequest(messageId, serverId, currentFlags,
                                        originalMailboxId, sourceMailboxId, destMailboxId));
                        // Since we don't want to remove this message from updated table until it
                        // downsyncs, we do not add it to updatedIds.
                    } else {
                        // TODO: If the message's mailboxes aren't there, handle it better.
                    }
                } else {
                    mUpdatedMessages.add(messageId);
                }

                final int favorite;
                final boolean favoriteChanged;
                // We can only send flag changes to the server in 12.0 or later
                if (getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
                    favorite = currentCursor.getInt(UPDATES_FAVORITE_COLUMN);
                    favoriteChanged =
                            favorite != updatedMessageCursor.getInt(UPDATES_FAVORITE_COLUMN);
                } else {
                    favorite = 0;
                    favoriteChanged = false;
                }

                final int read = currentCursor.getInt(UPDATES_READ_COLUMN);
                final boolean readChanged =
                        read != updatedMessageCursor.getInt(UPDATES_READ_COLUMN);

                if (favoriteChanged || readChanged) {
                    if (!hasCommands) {
                        s.start(Tags.SYNC_COMMANDS);
                    }
                    s.start(Tags.SYNC_CHANGE);
                    s.data(Tags.SYNC_SERVER_ID, serverId);
                    s.start(Tags.SYNC_APPLICATION_DATA);
                    if (readChanged) {
                        s.data(Tags.EMAIL_READ, Integer.toString(read));
                    }

                    // "Flag" is a relatively complex concept in EAS 12.0 and above.  It is not only
                    // the boolean "favorite" that we think of in Gmail, but it also represents a
                    // follow up action, which can include a subject, start and due dates, and even
                    // recurrences.  We don't support any of this as yet, but EAS 12.0 and higher
                    // require that a flag contain a status, a type, and four date fields, two each
                    // for start date and end (due) date.
                    if (favoriteChanged) {
                        if (favorite != 0) {
                            // Status 2 = set flag
                            s.start(Tags.EMAIL_FLAG).data(Tags.EMAIL_FLAG_STATUS, "2");
                            // "FollowUp" is the standard type
                            s.data(Tags.EMAIL_FLAG_TYPE, "FollowUp");
                            final long now = System.currentTimeMillis();
                            final Calendar calendar =
                                GregorianCalendar.getInstance(TimeZone.getTimeZone("GMT"));
                            calendar.setTimeInMillis(now);
                            // Flags are required to have a start date and end date (duplicated)
                            // First, we'll set the current date/time in GMT as the start time
                            String utc = formatDateTime(calendar);
                            s.data(Tags.TASK_START_DATE, utc).data(Tags.TASK_UTC_START_DATE, utc);
                            // And then we'll use one week from today for completion date
                            calendar.setTimeInMillis(now + DateUtils.WEEK_IN_MILLIS);
                            utc = formatDateTime(calendar);
                            s.data(Tags.TASK_DUE_DATE, utc).data(Tags.TASK_UTC_DUE_DATE, utc);
                            s.end();
                        } else {
                            s.tag(Tags.EMAIL_FLAG);
                        }
                    }
                    s.end().end();  // SYNC_APPLICATION_DATA, SYNC_CHANGE
                    return true;
                }
            }
        } finally {
            currentCursor.close();
        }
        return false;
    }

    /**
     * Send all message move requests and process responses.
     * TODO: Make this just one request/response, which requires changes to the parser.
     * @throws IOException
     */
    private void performMessageMove() throws IOException {

        for (final MoveRequest req : mMessagesToMove) {
            final Serializer s = new Serializer();
            s.start(Tags.MOVE_MOVE_ITEMS);
            s.start(Tags.MOVE_MOVE);
            s.data(Tags.MOVE_SRCMSGID, req.messageServerId);
            s.data(Tags.MOVE_SRCFLDID, req.sourceFolderServerId);
            s.data(Tags.MOVE_DSTFLDID, req.destFolderServerId);
            s.end();
            s.end().done();
            final EasResponse resp = sendHttpClientPost("MoveItems", s.toByteArray());
            try {
                final int status = resp.getStatus();
                if (status == HttpStatus.SC_OK) {
                    if (!resp.isEmpty()) {
                        final MoveItemsParser p = new MoveItemsParser(resp.getInputStream());
                        p.parse();
                        final int statusCode = p.getStatusCode();
                        final ContentValues cv = new ContentValues();
                        if (statusCode == MoveItemsParser.STATUS_CODE_REVERT) {
                            // Restore the old mailbox id
                            cv.put(MessageColumns.MAILBOX_KEY, req.sourceFolderId);
                            mContentResolver.update(
                                    ContentUris.withAppendedId(Message.CONTENT_URI, req.messageId),
                                    cv, null, null);
                        } else if (statusCode == MoveItemsParser.STATUS_CODE_SUCCESS) {
                            // Update with the new server id
                            cv.put(SyncColumns.SERVER_ID, p.getNewServerId());
                            cv.put(Message.FLAGS, req.messageFlags | MESSAGE_FLAG_MOVED_MESSAGE);
                            mContentResolver.update(
                                    ContentUris.withAppendedId(Message.CONTENT_URI, req.messageId),
                                    cv, null, null);
                        }
                        if (statusCode == MoveItemsParser.STATUS_CODE_SUCCESS
                                || statusCode == MoveItemsParser.STATUS_CODE_REVERT) {
                            // If we revert or succeed, we no longer need the update information
                            // OR the now-duplicate email (the new copy will be synced down)
                            mContentResolver.delete(ContentUris.withAppendedId(
                                    Message.UPDATED_CONTENT_URI, req.messageId), null, null);
                        } else {
                            // In this case, we're retrying, so do nothing.  The request will be
                            // handled next sync
                        }
                    }
                } else if (EasResponse.isAuthError(status)) {
                    throw new EasAuthenticationException();
                } else {
                    LogUtils.i(TAG, "Move items request failed, code: %d", status);
                    throw new IOException();
                }
            } finally {
                resp.close();
            }
        }
    }

    /**
     * For each message in Message_Updates, add a sync command if appropriate, and add its id to
     * our list of processed messages if appropriate.
     * @param s The {@link Serializer} for this sync request.
     * @param hasCommands Whether sync commands have already been written to s.
     * @return Whether this function added any sync commands to s.
     * @throws IOException
     */
    private boolean addUpdatedCommands(final Serializer s, final boolean hasCommands)
            throws IOException {
        // Find our trash mailbox, since deletions will have been moved there.
        final long trashMailboxId =
                Mailbox.findMailboxOfType(mContext, mMailbox.mAccountKey, Mailbox.TYPE_TRASH);
        final Cursor c = mContentResolver.query(Message.UPDATED_CONTENT_URI, UPDATES_PROJECTION,
                MessageColumns.MAILBOX_KEY + '=' + mMailbox.mId, null, null);
        boolean addedCommands = false;
        if (c != null) {
            try {
                while (c.moveToNext()) {
                    addedCommands |= handleOneUpdatedMessage(c, s, hasCommands || addedCommands,
                            trashMailboxId);
                }
            } finally {
                c.close();
            }
        }

        // mMessagesToMove is now populated. If it's non-empty, let's send the move request now.
        if (!mMessagesToMove.isEmpty()) {
            performMessageMove();
        }

        return addedCommands;
    }

    /**
     * Add FETCH commands for messages that need a body (i.e. we didn't find it during our earlier
     * sync; this happens only in EAS 2.5 where the body couldn't be found after parsing the
     * message's MIME data).
     * @param s The {@link Serializer} for this sync request.
     * @param hasCommands Whether sync commands have already been written to s.
     * @return Whether this function added any sync commands to s.
     * @throws IOException
     */
    private boolean addFetchCommands(final Serializer s, final boolean hasCommands)
            throws IOException {
        if (!hasCommands && !mMessagesToFetch.isEmpty()) {
            s.start(Tags.SYNC_COMMANDS);
        }
        for (final String serverId : mMessagesToFetch) {
            s.start(Tags.SYNC_FETCH).data(Tags.SYNC_SERVER_ID, serverId).end();
        }

        return !mMessagesToFetch.isEmpty();
    }

    @Override
    protected void setUpsyncCommands(final Serializer s) throws IOException {
        boolean addedCommands = addDeletedCommands(s, false);
        addedCommands = addFetchCommands(s, addedCommands);
        addedCommands = addUpdatedCommands(s, addedCommands);
        if (addedCommands) {
            s.end();
        }
    }

    @Override
    protected void cleanup(final int syncResult) {
        // After a successful sync, we have things to delete from the DB.
        if (syncResult != SYNC_RESULT_FAILED) {
            ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
            // Delete any moved messages (since we've just synced the mailbox, and no longer need
            // the placeholder message); this prevents duplicates from appearing in the mailbox.
            // TODO: Verify this still makes sense.
            ops.add(ContentProviderOperation.newDelete(Message.CONTENT_URI)
                    .withSelection(WHERE_MAILBOX_KEY_AND_MOVED,
                            new String[] {Long.toString(mMailbox.mId)}).build());
            // Delete any entries in Message_Updates and Message_Deletes that were upsynced.
            for (final long id: mDeletedMessages) {
                ops.add(ContentProviderOperation.newDelete(
                        ContentUris.withAppendedId(Message.DELETED_CONTENT_URI, id)).build());
            }
            for (final long id: mUpdatedMessages) {
                ops.add(ContentProviderOperation.newDelete(
                        ContentUris.withAppendedId(Message.UPDATED_CONTENT_URI, id)).build());
            }
            try {
                mContentResolver.applyBatch(EmailContent.AUTHORITY, ops);
            } catch (final RemoteException e) {
                // TODO: Improve handling.
            } catch (final OperationApplicationException e) {
                // TODO: Improve handing.
            }
        }

        if (syncResult == SYNC_RESULT_MORE_AVAILABLE) {
            // Prepare our member variables for another sync request.
            mDeletedMessages.clear();
            mUpdatedMessages.clear();
            mMessagesToFetch.clear();
            mMessagesToMove.clear();
        }
    }
}
