/*
 * Copyright (C) 2008-2009 Marc Blank
 * Licensed to The Android Open Source Project.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.exchange.adapter;

import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentUris;
import android.content.ContentValues;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.os.RemoteException;
import android.util.Log;
import android.webkit.MimeTypeMap;

import com.android.emailcommon.internet.MimeMessage;
import com.android.emailcommon.internet.MimeUtility;
import com.android.emailcommon.mail.Address;
import com.android.emailcommon.mail.MeetingInfo;
import com.android.emailcommon.mail.MessagingException;
import com.android.emailcommon.mail.PackedString;
import com.android.emailcommon.mail.Part;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.Attachment;
import com.android.emailcommon.provider.EmailContent.Body;
import com.android.emailcommon.provider.EmailContent.MailboxColumns;
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.provider.Policy;
import com.android.emailcommon.service.SyncWindow;
import com.android.emailcommon.utility.AttachmentUtilities;
import com.android.emailcommon.utility.ConversionUtilities;
import com.android.emailcommon.utility.Utility;
import com.android.exchange.CommandStatusException;
import com.android.exchange.Eas;
import com.android.exchange.EasResponse;
import com.android.exchange.EasSyncService;
import com.android.exchange.MessageMoveRequest;
import com.android.exchange.R;
import com.android.exchange.utility.CalendarUtilities;
import com.google.common.annotations.VisibleForTesting;

import org.apache.http.HttpStatus;
import org.apache.http.entity.ByteArrayEntity;

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

/**
 * Sync adapter for EAS email
 *
 */
public class EmailSyncAdapter extends AbstractSyncAdapter {

    private static final int UPDATES_READ_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 String[] UPDATES_PROJECTION =
        {MessageColumns.FLAG_READ, MessageColumns.MAILBOX_KEY, SyncColumns.SERVER_ID,
            MessageColumns.FLAG_FAVORITE};

    private static final int MESSAGE_ID_SUBJECT_ID_COLUMN = 0;
    private static final int MESSAGE_ID_SUBJECT_SUBJECT_COLUMN = 1;
    private static final String[] MESSAGE_ID_SUBJECT_PROJECTION =
        new String[] { Message.RECORD_ID, MessageColumns.SUBJECT };

    private static final String WHERE_BODY_SOURCE_MESSAGE_KEY = Body.SOURCE_MESSAGE_KEY + "=?";
    private static final String WHERE_MAILBOX_KEY_AND_MOVED =
        MessageColumns.MAILBOX_KEY + "=? AND (" + MessageColumns.FLAGS + "&" +
        EasSyncService.MESSAGE_FLAG_MOVED_MESSAGE + ")!=0";
    private static final String[] FETCH_REQUEST_PROJECTION =
        new String[] {EmailContent.RECORD_ID, SyncColumns.SERVER_ID};
    private static final int FETCH_REQUEST_RECORD_ID = 0;
    private static final int FETCH_REQUEST_SERVER_ID = 1;

    private static final String EMAIL_WINDOW_SIZE = "5";

    @VisibleForTesting
    static final int LAST_VERB_REPLY = 1;
    @VisibleForTesting
    static final int LAST_VERB_REPLY_ALL = 2;
    @VisibleForTesting
    static final int LAST_VERB_FORWARD = 3;

    private final String[] mBindArguments = new String[2];
    private final String[] mBindArgument = new String[1];

    @VisibleForTesting
    ArrayList<Long> mDeletedIdList = new ArrayList<Long>();
    @VisibleForTesting
    ArrayList<Long> mUpdatedIdList = new ArrayList<Long>();
    private final ArrayList<FetchRequest> mFetchRequestList = new ArrayList<FetchRequest>();
    private boolean mFetchNeeded = false;

    // Holds the parser's value for isLooping()
    private boolean mIsLooping = false;

    // The policy (if any) for this adapter's Account
    private final Policy mPolicy;

    public EmailSyncAdapter(EasSyncService service) {
        super(service);
        // If we've got an account with a policy, cache it now
        if (mAccount.mPolicyKey != 0) {
            mPolicy = Policy.restorePolicyWithId(mContext, mAccount.mPolicyKey);
        } else {
            mPolicy = null;
        }
    }

    @Override
    public void wipe() {
        mContentResolver.delete(Message.CONTENT_URI,
                Message.MAILBOX_KEY + "=" + mMailbox.mId, null);
        mContentResolver.delete(Message.DELETED_CONTENT_URI,
                Message.MAILBOX_KEY + "=" + mMailbox.mId, null);
        mContentResolver.delete(Message.UPDATED_CONTENT_URI,
                Message.MAILBOX_KEY + "=" + mMailbox.mId, null);
        mService.clearRequests();
        mFetchRequestList.clear();
        // Delete attachments...
        AttachmentUtilities.deleteAllMailboxAttachmentFiles(mContext, mAccount.mId, mMailbox.mId);
    }

    private String getEmailFilter() {
        int syncLookback = mMailbox.mSyncLookback;
        if (syncLookback == SyncWindow.SYNC_WINDOW_UNKNOWN) {
            syncLookback = mAccount.mSyncLookback;
        }
        switch (syncLookback) {
            case SyncWindow.SYNC_WINDOW_AUTO:
                return Eas.FILTER_AUTO;
            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:
                return Eas.FILTER_1_WEEK;
        }
    }

    /**
     * Holder for fetch request information (record id and server id)
     */
    private static class FetchRequest {
        @SuppressWarnings("unused")
        final long messageId;
        final String serverId;

        FetchRequest(long _messageId, String _serverId) {
            messageId = _messageId;
            serverId = _serverId;
        }
    }

    @Override
    public void sendSyncOptions(Double protocolVersion, Serializer s)
            throws IOException  {
        mFetchRequestList.clear();
        // Find partially loaded messages; this should typically be a rare occurrence
        Cursor c = mContext.getContentResolver().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);
        try {
            // Put all of these messages into a list; we'll need both id and server id
            while (c.moveToNext()) {
                mFetchRequestList.add(new FetchRequest(c.getLong(FETCH_REQUEST_RECORD_ID),
                        c.getString(FETCH_REQUEST_SERVER_ID)));
            }
        } finally {
            c.close();
        }

        // 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 (mFetchRequestList.isEmpty()) {
            s.tag(Tags.SYNC_DELETES_AS_MOVES);
            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")
            String filter = getEmailFilter();
            // We shouldn't get FILTER_AUTO here, but if we do, make it something legal...
            if (filter.equals(Eas.FILTER_AUTO)) {
                filter = Eas.FILTER_3_DAYS;
            }
            s.data(Tags.SYNC_FILTER_TYPE, getEmailFilter());
            // Set the truncation amount for all classes
            if (protocolVersion >= 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 {
            s.start(Tags.SYNC_OPTIONS);
            // Ask for plain text, rather than MIME data.  This guarantees that we'll get a usable
            // text body
            s.data(Tags.SYNC_MIME_SUPPORT, Eas.MIME_BODY_PREFERENCE_TEXT);
            s.data(Tags.SYNC_TRUNCATION, Eas.EAS2_5_TRUNCATION_SIZE);
            s.end();
        }
    }

    @Override
    public boolean parse(InputStream is) throws IOException, CommandStatusException {
        EasEmailSyncParser p = new EasEmailSyncParser(is, this);
        mFetchNeeded = false;
        boolean res = p.parse();
        // Hold on to the parser's value for isLooping() to pass back to the service
        mIsLooping = p.isLooping();
        // If we've need a body fetch, or we've just finished one, return true in order to continue
        if (mFetchNeeded || !mFetchRequestList.isEmpty()) {
            return true;
        }

        // Don't check for "auto" on the initial sync
        if (!("0".equals(mMailbox.mSyncKey))) {
            // We've completed the first successful sync
            if (getEmailFilter().equals(Eas.FILTER_AUTO)) {
                getAutomaticLookback();
             }
        }

        return res;
    }

    private void getAutomaticLookback() throws IOException {
        // If we're using an auto lookback, check how many items in the past week
        // TODO Make the literal ints below constants once we twiddle them a bit
        int items = getEstimate(Eas.FILTER_1_WEEK);
        int lookback;
        if (items > 1050) {
            // Over 150/day, just use one day (smallest)
            lookback = SyncWindow.SYNC_WINDOW_1_DAY;
        } else if (items > 350 || (items == -1)) {
            // 50-150/day, use 3 days (150 to 450 messages synced)
            lookback = SyncWindow.SYNC_WINDOW_3_DAYS;
        } else if (items > 150) {
            // 20-50/day, use 1 week (140 to 350 messages synced)
            lookback = SyncWindow.SYNC_WINDOW_1_WEEK;
        } else if (items > 75) {
            // 10-25/day, use 1 week (140 to 350 messages synced)
            lookback = SyncWindow.SYNC_WINDOW_2_WEEKS;
        } else if (items < 5) {
            // If there are only a couple, see if it makes sense to get everything
            items = getEstimate(Eas.FILTER_ALL);
            if (items >= 0 && items < 100) {
                lookback = SyncWindow.SYNC_WINDOW_ALL;
            } else {
                lookback = SyncWindow.SYNC_WINDOW_1_MONTH;
            }
        } else {
            lookback = SyncWindow.SYNC_WINDOW_1_MONTH;
        }
        // Store the new lookback and persist it
        mMailbox.mSyncLookback = lookback;
        ContentValues cv = new ContentValues();
        cv.put(MailboxColumns.SYNC_LOOKBACK, lookback);
        mContentResolver.update(ContentUris.withAppendedId(
                Mailbox.CONTENT_URI, mMailbox.mId), cv, null, null);
        // STOPSHIP Temporary UI - Let the user know
        CharSequence[] windowEntries = mContext.getResources().getTextArray(
                R.array.account_settings_mail_window_entries);
        Utility.showToast(mContext, "Auto lookback: " + windowEntries[lookback]);
    }

    private static class GetItemEstimateParser extends Parser {
        private static final String TAG = "GetItemEstimateParser";
        private int mEstimate = -1;

        public GetItemEstimateParser(InputStream in) throws IOException {
            super(in);
        }

        @Override
        public boolean parse() throws IOException {
            // Loop here through the remaining xml
            while (nextTag(START_DOCUMENT) != END_DOCUMENT) {
                if (tag == Tags.GIE_GET_ITEM_ESTIMATE) {
                    parseGetItemEstimate();
                } else {
                    skipTag();
                }
            }
            return true;
        }

        public void parseGetItemEstimate() throws IOException {
            while (nextTag(Tags.GIE_GET_ITEM_ESTIMATE) != END) {
                if (tag == Tags.GIE_RESPONSE) {
                    parseResponse();
                } else {
                    skipTag();
                }
            }
        }

        public void parseResponse() throws IOException {
            while (nextTag(Tags.GIE_RESPONSE) != END) {
                if (tag == Tags.GIE_STATUS) {
                    Log.d(TAG, "GIE status: " + getValue());
                } else if (tag == Tags.GIE_COLLECTION) {
                    parseCollection();
                } else {
                    skipTag();
                }
            }
        }

        public void parseCollection() throws IOException {
            while (nextTag(Tags.GIE_COLLECTION) != END) {
                if (tag == Tags.GIE_CLASS) {
                    Log.d(TAG, "GIE class: " + getValue());
                } else if (tag == Tags.GIE_COLLECTION_ID) {
                    Log.d(TAG, "GIE collectionId: " + getValue());
                } else if (tag == Tags.GIE_ESTIMATE) {
                    mEstimate = getValueInt();
                    Log.d(TAG, "GIE estimate: " + mEstimate);
                } else {
                    skipTag();
                }
            }
        }
    }

    /**
     * Return the estimated number of items to be synced in the current mailbox, based on the
     * passed in filter argument
     * @param filter an EAS "window" filter
     * @return the estimated number of items to be synced, or -1 if unknown
     * @throws IOException
     */
    private int getEstimate(String filter) throws IOException {
        Serializer s = new Serializer();
        boolean ex10 = mService.mProtocolVersionDouble >= Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE;
        boolean ex03 = mService.mProtocolVersionDouble < Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE;
        boolean ex07 = !ex10 && !ex03;

        String className = getCollectionName();
        String syncKey = getSyncKey();
        userLog("gie, sending ", className, " syncKey: ", syncKey);

        s.start(Tags.GIE_GET_ITEM_ESTIMATE).start(Tags.GIE_COLLECTIONS);
        s.start(Tags.GIE_COLLECTION);
        if (ex07) {
            // Exchange 2007 likes collection id first
            s.data(Tags.GIE_COLLECTION_ID, mMailbox.mServerId);
            s.data(Tags.SYNC_FILTER_TYPE, filter);
            s.data(Tags.SYNC_SYNC_KEY, syncKey);
        } else if (ex03) {
            // Exchange 2003 needs the "class" element
            s.data(Tags.GIE_CLASS, className);
            s.data(Tags.SYNC_SYNC_KEY, syncKey);
            s.data(Tags.GIE_COLLECTION_ID, mMailbox.mServerId);
            s.data(Tags.SYNC_FILTER_TYPE, filter);
        } else {
            // Exchange 2010 requires the filter inside an OPTIONS container and sync key first
            s.data(Tags.SYNC_SYNC_KEY, syncKey);
            s.data(Tags.GIE_COLLECTION_ID, mMailbox.mServerId);
            s.start(Tags.SYNC_OPTIONS).data(Tags.SYNC_FILTER_TYPE, filter).end();
        }
        s.end().end().end().done(); // GIE_COLLECTION, GIE_COLLECTIONS, GIE_GET_ITEM_ESTIMATE

        EasResponse resp = mService.sendHttpClientPost("GetItemEstimate",
                new ByteArrayEntity(s.toByteArray()), EasSyncService.COMMAND_TIMEOUT);
        int code = resp.getStatus();
        if (code == HttpStatus.SC_OK) {
            if (!resp.isEmpty()) {
                InputStream is = resp.getInputStream();
                GetItemEstimateParser gieParser = new GetItemEstimateParser(is);
                gieParser.parse();
                // Return the estimated number of items
                return gieParser.mEstimate;
            }
        }
        // If we can't get an estimate, indicate this...
        return -1;
    }

    /**
     * Return the value of isLooping() as returned from the parser
     */
    @Override
    public boolean isLooping() {
        return mIsLooping;
    }

    @Override
    public boolean isSyncable() {
        return true;
    }

    public class EasEmailSyncParser extends AbstractSyncParser {

        private static final String WHERE_SERVER_ID_AND_MAILBOX_KEY =
            SyncColumns.SERVER_ID + "=? and " + MessageColumns.MAILBOX_KEY + "=?";

        private final String mMailboxIdAsString;

        private final ArrayList<Message> newEmails = new ArrayList<Message>();
        private final ArrayList<Message> fetchedEmails = new ArrayList<Message>();
        private final ArrayList<Long> deletedEmails = new ArrayList<Long>();
        private final ArrayList<ServerChange> changedEmails = new ArrayList<ServerChange>();

        public EasEmailSyncParser(InputStream in, EmailSyncAdapter adapter) throws IOException {
            super(in, adapter);
            mMailboxIdAsString = Long.toString(mMailbox.mId);
        }

        public EasEmailSyncParser(Parser parser, EmailSyncAdapter adapter) throws IOException {
            super(parser, adapter);
            mMailboxIdAsString = Long.toString(mMailbox.mId);
        }

        public void addData (Message msg, int endingTag) throws IOException {
            ArrayList<Attachment> atts = new ArrayList<Attachment>();
            boolean truncated = false;

            while (nextTag(endingTag) != END) {
                switch (tag) {
                    case Tags.EMAIL_ATTACHMENTS:
                    case Tags.BASE_ATTACHMENTS: // BASE_ATTACHMENTS is used in EAS 12.0 and up
                        attachmentsParser(atts, msg);
                        break;
                    case Tags.EMAIL_TO:
                        msg.mTo = Address.pack(Address.parse(getValue()));
                        break;
                    case Tags.EMAIL_FROM:
                        Address[] froms = Address.parse(getValue());
                        if (froms != null && froms.length > 0) {
                            msg.mDisplayName = froms[0].toFriendly();
                        }
                        msg.mFrom = Address.pack(froms);
                        break;
                    case Tags.EMAIL_CC:
                        msg.mCc = Address.pack(Address.parse(getValue()));
                        break;
                    case Tags.EMAIL_REPLY_TO:
                        msg.mReplyTo = Address.pack(Address.parse(getValue()));
                        break;
                    case Tags.EMAIL_DATE_RECEIVED:
                        msg.mTimeStamp = Utility.parseEmailDateTimeToMillis(getValue());
                        break;
                    case Tags.EMAIL_SUBJECT:
                        msg.mSubject = getValue();
                        break;
                    case Tags.EMAIL_READ:
                        msg.mFlagRead = getValueInt() == 1;
                        break;
                    case Tags.BASE_BODY:
                        bodyParser(msg);
                        break;
                    case Tags.EMAIL_FLAG:
                        msg.mFlagFavorite = flagParser();
                        break;
                    case Tags.EMAIL_MIME_TRUNCATED:
                        truncated = getValueInt() == 1;
                        break;
                    case Tags.EMAIL_MIME_DATA:
                        // We get MIME data for EAS 2.5.  First we parse it, then we take the
                        // html and/or plain text data and store it in the message
                        if (truncated) {
                            // If the MIME data is truncated, don't bother parsing it, because
                            // it will take time and throw an exception anyway when EOF is reached
                            // In this case, we will load the body separately by tagging the message
                            // "partially loaded".
                            // Get the data (and ignore it)
                            getValue();
                            userLog("Partially loaded: ", msg.mServerId);
                            msg.mFlagLoaded = Message.FLAG_LOADED_PARTIAL;
                            mFetchNeeded = true;
                        } else {
                            mimeBodyParser(msg, getValue());
                        }
                        break;
                    case Tags.EMAIL_BODY:
                        String text = getValue();
                        msg.mText = text;
                        break;
                    case Tags.EMAIL_MESSAGE_CLASS:
                        String messageClass = getValue();
                        if (messageClass.equals("IPM.Schedule.Meeting.Request")) {
                            msg.mFlags |= Message.FLAG_INCOMING_MEETING_INVITE;
                        } else if (messageClass.equals("IPM.Schedule.Meeting.Canceled")) {
                            msg.mFlags |= Message.FLAG_INCOMING_MEETING_CANCEL;
                        }
                        break;
                    case Tags.EMAIL_MEETING_REQUEST:
                        meetingRequestParser(msg);
                        break;
                    case Tags.RIGHTS_LICENSE:
                        skipParser(tag);
                        break;
                    case Tags.EMAIL2_CONVERSATION_ID:
                    case Tags.EMAIL2_CONVERSATION_INDEX:
                        // Note that the value of these two tags is a byte array
                        getValueBytes();
                        break;
                    case Tags.EMAIL2_LAST_VERB_EXECUTED:
                        int val = getValueInt();
                        if (val == LAST_VERB_REPLY || val == LAST_VERB_REPLY_ALL) {
                            // We aren't required to distinguish between reply and reply all here
                            msg.mFlags |= Message.FLAG_REPLIED_TO;
                        } else if (val == LAST_VERB_FORWARD) {
                            msg.mFlags |= Message.FLAG_FORWARDED;
                        }
                        break;
                    default:
                        skipTag();
                }
            }

            if (atts.size() > 0) {
                msg.mAttachments = atts;
            }
        }

        /**
         * Set up the meetingInfo field in the message with various pieces of information gleaned
         * from MeetingRequest tags.  This information will be used later to generate an appropriate
         * reply email if the user chooses to respond
         * @param msg the Message being built
         * @throws IOException
         */
        private void meetingRequestParser(Message msg) throws IOException {
            PackedString.Builder packedString = new PackedString.Builder();
            while (nextTag(Tags.EMAIL_MEETING_REQUEST) != END) {
                switch (tag) {
                    case Tags.EMAIL_DTSTAMP:
                        packedString.put(MeetingInfo.MEETING_DTSTAMP, getValue());
                        break;
                    case Tags.EMAIL_START_TIME:
                        packedString.put(MeetingInfo.MEETING_DTSTART, getValue());
                        break;
                    case Tags.EMAIL_END_TIME:
                        packedString.put(MeetingInfo.MEETING_DTEND, getValue());
                        break;
                    case Tags.EMAIL_ORGANIZER:
                        packedString.put(MeetingInfo.MEETING_ORGANIZER_EMAIL, getValue());
                        break;
                    case Tags.EMAIL_LOCATION:
                        packedString.put(MeetingInfo.MEETING_LOCATION, getValue());
                        break;
                    case Tags.EMAIL_GLOBAL_OBJID:
                        packedString.put(MeetingInfo.MEETING_UID,
                                CalendarUtilities.getUidFromGlobalObjId(getValue()));
                        break;
                    case Tags.EMAIL_CATEGORIES:
                        skipParser(tag);
                        break;
                    case Tags.EMAIL_RECURRENCES:
                        recurrencesParser();
                        break;
                    case Tags.EMAIL_RESPONSE_REQUESTED:
                        packedString.put(MeetingInfo.MEETING_RESPONSE_REQUESTED, getValue());
                        break;
                    default:
                        skipTag();
                }
            }
            if (msg.mSubject != null) {
                packedString.put(MeetingInfo.MEETING_TITLE, msg.mSubject);
            }
            msg.mMeetingInfo = packedString.toString();
        }

        private void recurrencesParser() throws IOException {
            while (nextTag(Tags.EMAIL_RECURRENCES) != END) {
                switch (tag) {
                    case Tags.EMAIL_RECURRENCE:
                        skipParser(tag);
                        break;
                    default:
                        skipTag();
                }
            }
        }

        /**
         * Parse a message from the server stream.
         * @return the parsed Message
         * @throws IOException
         */
        private Message addParser() throws IOException, CommandStatusException {
            Message msg = new Message();
            msg.mAccountKey = mAccount.mId;
            msg.mMailboxKey = mMailbox.mId;
            msg.mFlagLoaded = Message.FLAG_LOADED_COMPLETE;
            // Default to 1 (success) in case we don't get this tag
            int status = 1;

            while (nextTag(Tags.SYNC_ADD) != END) {
                switch (tag) {
                    case Tags.SYNC_SERVER_ID:
                        msg.mServerId = getValue();
                        break;
                    case Tags.SYNC_STATUS:
                        status = getValueInt();
                        break;
                    case Tags.SYNC_APPLICATION_DATA:
                        addData(msg, tag);
                        break;
                    default:
                        skipTag();
                }
            }
            // For sync, status 1 = success
            if (status != 1) {
                throw new CommandStatusException(status, msg.mServerId);
            }
            return msg;
        }

        // For now, we only care about the "active" state
        private Boolean flagParser() throws IOException {
            Boolean state = false;
            while (nextTag(Tags.EMAIL_FLAG) != END) {
                switch (tag) {
                    case Tags.EMAIL_FLAG_STATUS:
                        state = getValueInt() == 2;
                        break;
                    default:
                        skipTag();
                }
            }
            return state;
        }

        private void bodyParser(Message msg) throws IOException {
            String bodyType = Eas.BODY_PREFERENCE_TEXT;
            String body = "";
            while (nextTag(Tags.EMAIL_BODY) != END) {
                switch (tag) {
                    case Tags.BASE_TYPE:
                        bodyType = getValue();
                        break;
                    case Tags.BASE_DATA:
                        body = getValue();
                        break;
                    default:
                        skipTag();
                }
            }
            // We always ask for TEXT or HTML; there's no third option
            if (bodyType.equals(Eas.BODY_PREFERENCE_HTML)) {
                msg.mHtml = body;
            } else {
                msg.mText = body;
            }
        }

        /**
         * Parses untruncated MIME data, saving away the text parts
         * @param msg the message we're building
         * @param mimeData the MIME data we've received from the server
         * @throws IOException
         */
        private void mimeBodyParser(Message msg, String mimeData) throws IOException {
            try {
                ByteArrayInputStream in = new ByteArrayInputStream(mimeData.getBytes());
                // The constructor parses the message
                MimeMessage mimeMessage = new MimeMessage(in);
                // Now process body parts & attachments
                ArrayList<Part> viewables = new ArrayList<Part>();
                // We'll ignore the attachments, as we'll get them directly from EAS
                ArrayList<Part> attachments = new ArrayList<Part>();
                MimeUtility.collectParts(mimeMessage, viewables, attachments);
                Body tempBody = new Body();
                // updateBodyFields fills in the content fields of the Body
                ConversionUtilities.updateBodyFields(tempBody, msg, viewables);
                // But we need them in the message itself for handling during commit()
                msg.mHtml = tempBody.mHtmlContent;
                msg.mText = tempBody.mTextContent;
            } catch (MessagingException e) {
                // This would most likely indicate a broken stream
                throw new IOException(e);
            }
        }

        private void attachmentsParser(ArrayList<Attachment> atts, Message msg) throws IOException {
            while (nextTag(Tags.EMAIL_ATTACHMENTS) != END) {
                switch (tag) {
                    case Tags.EMAIL_ATTACHMENT:
                    case Tags.BASE_ATTACHMENT:  // BASE_ATTACHMENT is used in EAS 12.0 and up
                        attachmentParser(atts, msg);
                        break;
                    default:
                        skipTag();
                }
            }
        }

        private void attachmentParser(ArrayList<Attachment> atts, Message msg) throws IOException {
            String fileName = null;
            String length = null;
            String location = null;

            while (nextTag(Tags.EMAIL_ATTACHMENT) != END) {
                switch (tag) {
                    // We handle both EAS 2.5 and 12.0+ attachments here
                    case Tags.EMAIL_DISPLAY_NAME:
                    case Tags.BASE_DISPLAY_NAME:
                        fileName = getValue();
                        break;
                    case Tags.EMAIL_ATT_NAME:
                    case Tags.BASE_FILE_REFERENCE:
                        location = getValue();
                        break;
                    case Tags.EMAIL_ATT_SIZE:
                    case Tags.BASE_ESTIMATED_DATA_SIZE:
                        length = getValue();
                        break;
                    default:
                        skipTag();
                }
            }

            if ((fileName != null) && (length != null) && (location != null)) {
                Attachment att = new Attachment();
                att.mEncoding = "base64";
                att.mSize = Long.parseLong(length);
                att.mFileName = fileName;
                att.mLocation = location;
                att.mMimeType = getMimeTypeFromFileName(fileName);
                att.mAccountKey = mService.mAccount.mId;
                // Check if this attachment can't be downloaded due to an account policy
                if (mPolicy != null) {
                    if (mPolicy.mDontAllowAttachments ||
                            (mPolicy.mMaxAttachmentSize > 0 &&
                                    (att.mSize > mPolicy.mMaxAttachmentSize))) {
                        att.mFlags = Attachment.FLAG_POLICY_DISALLOWS_DOWNLOAD;
                    }
                }
                atts.add(att);
                msg.mFlagAttachment = true;
            }
        }

        /**
         * Returns an appropriate mimetype for the given file name's extension. If a mimetype
         * cannot be determined, {@code application/<<x>>} [where @{code <<x>> is the extension,
         * if it exists or {@code application/octet-stream}].
         * At the moment, this is somewhat lame, since many file types aren't recognized
         * @param fileName the file name to ponder
         */
        // Note: The MimeTypeMap method currently uses a very limited set of mime types
        // A bug has been filed against this issue.
        public String getMimeTypeFromFileName(String fileName) {
            String mimeType;
            int lastDot = fileName.lastIndexOf('.');
            String extension = null;
            if ((lastDot > 0) && (lastDot < fileName.length() - 1)) {
                extension = fileName.substring(lastDot + 1).toLowerCase();
            }
            if (extension == null) {
                // A reasonable default for now.
                mimeType = "application/octet-stream";
            } else {
                mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension);
                if (mimeType == null) {
                    mimeType = "application/" + extension;
                }
            }
            return mimeType;
        }

        private Cursor getServerIdCursor(String serverId, String[] projection) {
            mBindArguments[0] = serverId;
            mBindArguments[1] = mMailboxIdAsString;
            return mContentResolver.query(Message.CONTENT_URI, projection,
                    WHERE_SERVER_ID_AND_MAILBOX_KEY, mBindArguments, null);
        }

        @VisibleForTesting
        void deleteParser(ArrayList<Long> deletes, int entryTag) throws IOException {
            while (nextTag(entryTag) != END) {
                switch (tag) {
                    case Tags.SYNC_SERVER_ID:
                        String serverId = getValue();
                        // Find the message in this mailbox with the given serverId
                        Cursor c = getServerIdCursor(serverId, MESSAGE_ID_SUBJECT_PROJECTION);
                        try {
                            if (c.moveToFirst()) {
                                deletes.add(c.getLong(MESSAGE_ID_SUBJECT_ID_COLUMN));
                                if (Eas.USER_LOG) {
                                    userLog("Deleting ", serverId + ", "
                                            + c.getString(MESSAGE_ID_SUBJECT_SUBJECT_COLUMN));
                                }
                            }
                        } finally {
                            c.close();
                        }
                        break;
                    default:
                        skipTag();
                }
            }
        }

        @VisibleForTesting
        class ServerChange {
            final long id;
            final Boolean read;
            final Boolean flag;
            final Integer flags;

            ServerChange(long _id, Boolean _read, Boolean _flag, Integer _flags) {
                id = _id;
                read = _read;
                flag = _flag;
                flags = _flags;
            }
        }

        @VisibleForTesting
        void changeParser(ArrayList<ServerChange> changes) throws IOException {
            String serverId = null;
            Boolean oldRead = false;
            Boolean oldFlag = false;
            int flags = 0;
            long id = 0;
            while (nextTag(Tags.SYNC_CHANGE) != END) {
                switch (tag) {
                    case Tags.SYNC_SERVER_ID:
                        serverId = getValue();
                        Cursor c = getServerIdCursor(serverId, Message.LIST_PROJECTION);
                        try {
                            if (c.moveToFirst()) {
                                userLog("Changing ", serverId);
                                oldRead = c.getInt(Message.LIST_READ_COLUMN) == Message.READ;
                                oldFlag = c.getInt(Message.LIST_FAVORITE_COLUMN) == 1;
                                flags = c.getInt(Message.LIST_FLAGS_COLUMN);
                                id = c.getLong(Message.LIST_ID_COLUMN);
                            }
                        } finally {
                            c.close();
                        }
                        break;
                    case Tags.SYNC_APPLICATION_DATA:
                        changeApplicationDataParser(changes, oldRead, oldFlag, flags, id);
                        break;
                    default:
                        skipTag();
                }
            }
        }

        private void changeApplicationDataParser(ArrayList<ServerChange> changes, Boolean oldRead,
                Boolean oldFlag, int oldFlags, long id) throws IOException {
            Boolean read = null;
            Boolean flag = null;
            Integer flags = null;
            while (nextTag(Tags.SYNC_APPLICATION_DATA) != END) {
                switch (tag) {
                    case Tags.EMAIL_READ:
                        read = getValueInt() == 1;
                        break;
                    case Tags.EMAIL_FLAG:
                        flag = flagParser();
                        break;
                    case Tags.EMAIL2_LAST_VERB_EXECUTED:
                        int val = getValueInt();
                        // Clear out the old replied/forward flags and add in the new flag
                        flags = oldFlags & ~(Message.FLAG_REPLIED_TO | Message.FLAG_FORWARDED);
                        if (val == LAST_VERB_REPLY || val == LAST_VERB_REPLY_ALL) {
                            // We aren't required to distinguish between reply and reply all here
                            flags |= Message.FLAG_REPLIED_TO;
                        } else if (val == LAST_VERB_FORWARD) {
                            flags |= Message.FLAG_FORWARDED;
                        }
                        break;
                    default:
                        skipTag();
                }
            }
            // See if there are flag changes re: read, flag (favorite) or replied/forwarded
            if (((read != null) && !oldRead.equals(read)) ||
                    ((flag != null) && !oldFlag.equals(flag)) || (flags != null)) {
                changes.add(new ServerChange(id, read, flag, flags));
            }
        }

        /* (non-Javadoc)
         * @see com.android.exchange.adapter.EasContentParser#commandsParser()
         */
        @Override
        public void commandsParser() throws IOException, CommandStatusException {
            while (nextTag(Tags.SYNC_COMMANDS) != END) {
                if (tag == Tags.SYNC_ADD) {
                    newEmails.add(addParser());
                    incrementChangeCount();
                } else if (tag == Tags.SYNC_DELETE || tag == Tags.SYNC_SOFT_DELETE) {
                    deleteParser(deletedEmails, tag);
                    incrementChangeCount();
                } else if (tag == Tags.SYNC_CHANGE) {
                    changeParser(changedEmails);
                    incrementChangeCount();
                } else
                    skipTag();
            }
        }

        @Override
        public void responsesParser() throws IOException {
            while (nextTag(Tags.SYNC_RESPONSES) != END) {
                if (tag == Tags.SYNC_ADD || tag == Tags.SYNC_CHANGE || tag == Tags.SYNC_DELETE) {
                    // We can ignore all of these
                } else if (tag == Tags.SYNC_FETCH) {
                    try {
                        fetchedEmails.add(addParser());
                    } catch (CommandStatusException sse) {
                        if (sse.mStatus == 8) {
                            // 8 = object not found; delete the message from EmailProvider
                            // No other status should be seen in a fetch response, except, perhaps,
                            // for some temporary server failure
                            mBindArguments[0] = sse.mItemId;
                            mBindArguments[1] = mMailboxIdAsString;
                            mContentResolver.delete(Message.CONTENT_URI,
                                    WHERE_SERVER_ID_AND_MAILBOX_KEY, mBindArguments);
                        }
                    }
                }
            }
        }

        @Override
        public void commit() {
            // Use a batch operation to handle the changes
            // TODO New mail notifications?  Who looks for these?
            ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();

            for (Message msg: fetchedEmails) {
                // Find the original message's id (by serverId and mailbox)
                Cursor c = getServerIdCursor(msg.mServerId, EmailContent.ID_PROJECTION);
                String id = null;
                try {
                    if (c.moveToFirst()) {
                        id = c.getString(EmailContent.ID_PROJECTION_COLUMN);
                    }
                } finally {
                    c.close();
                }

                // If we find one, we do two things atomically: 1) set the body text for the
                // message, and 2) mark the message loaded (i.e. completely loaded)
                if (id != null) {
                    userLog("Fetched body successfully for ", id);
                    mBindArgument[0] = id;
                    ops.add(ContentProviderOperation.newUpdate(Body.CONTENT_URI)
                            .withSelection(Body.MESSAGE_KEY + "=?", mBindArgument)
                            .withValue(Body.TEXT_CONTENT, msg.mText)
                            .build());
                    ops.add(ContentProviderOperation.newUpdate(Message.CONTENT_URI)
                            .withSelection(EmailContent.RECORD_ID + "=?", mBindArgument)
                            .withValue(Message.FLAG_LOADED, Message.FLAG_LOADED_COMPLETE)
                            .build());
                }
            }

            for (Message msg: newEmails) {
                msg.addSaveOps(ops);
            }

            for (Long id : deletedEmails) {
                ops.add(ContentProviderOperation.newDelete(
                        ContentUris.withAppendedId(Message.CONTENT_URI, id)).build());
                AttachmentUtilities.deleteAllAttachmentFiles(mContext, mAccount.mId, id);
            }

            if (!changedEmails.isEmpty()) {
                // Server wins in a conflict...
                for (ServerChange change : changedEmails) {
                     ContentValues cv = new ContentValues();
                    if (change.read != null) {
                        cv.put(MessageColumns.FLAG_READ, change.read);
                    }
                    if (change.flag != null) {
                        cv.put(MessageColumns.FLAG_FAVORITE, change.flag);
                    }
                    if (change.flags != null) {
                        cv.put(MessageColumns.FLAGS, change.flags);
                    }
                    ops.add(ContentProviderOperation.newUpdate(
                            ContentUris.withAppendedId(Message.CONTENT_URI, change.id))
                                .withValues(cv)
                                .build());
                }
            }

            // We only want to update the sync key here
            ContentValues mailboxValues = new ContentValues();
            mailboxValues.put(Mailbox.SYNC_KEY, mMailbox.mSyncKey);
            ops.add(ContentProviderOperation.newUpdate(
                    ContentUris.withAppendedId(Mailbox.CONTENT_URI, mMailbox.mId))
                        .withValues(mailboxValues).build());

            addCleanupOps(ops);

            // No commits if we're stopped
            synchronized (mService.getSynchronizer()) {
                if (mService.isStopped()) return;
                try {
                    mContentResolver.applyBatch(EmailContent.AUTHORITY, ops);
                    userLog(mMailbox.mDisplayName, " SyncKey saved as: ", mMailbox.mSyncKey);
                } catch (RemoteException e) {
                    // There is nothing to be done here; fail by returning null
                } catch (OperationApplicationException e) {
                    // There is nothing to be done here; fail by returning null
                }
            }
        }
    }

    @Override
    public String getCollectionName() {
        return "Email";
    }

    private void addCleanupOps(ArrayList<ContentProviderOperation> ops) {
        // If we've sent local deletions, clear out the deleted table
        for (Long id: mDeletedIdList) {
            ops.add(ContentProviderOperation.newDelete(
                    ContentUris.withAppendedId(Message.DELETED_CONTENT_URI, id)).build());
        }
        // And same with the updates
        for (Long id: mUpdatedIdList) {
            ops.add(ContentProviderOperation.newDelete(
                    ContentUris.withAppendedId(Message.UPDATED_CONTENT_URI, id)).build());
        }
        // 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.
        mBindArgument[0] = Long.toString(mMailbox.mId);
        ops.add(ContentProviderOperation.newDelete(Message.CONTENT_URI)
                .withSelection(WHERE_MAILBOX_KEY_AND_MOVED, mBindArgument).build());
    }

    @Override
    public void cleanup() {
        if (!mDeletedIdList.isEmpty() || !mUpdatedIdList.isEmpty()) {
            ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
            addCleanupOps(ops);
            try {
                mContext.getContentResolver()
                    .applyBatch(EmailContent.AUTHORITY, ops);
            } catch (RemoteException e) {
                // There is nothing to be done here; fail by returning null
            } catch (OperationApplicationException e) {
                // There is nothing to be done here; fail by returning null
            }
        }
    }

    private String formatTwo(int num) {
        if (num < 10) {
            return "0" + (char)('0' + num);
        } else
            return Integer.toString(num);
    }

    /**
     * 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)
     */
    public String formatDateTime(Calendar calendar) {
        StringBuilder sb = new StringBuilder();
        //YYYY-MM-DDTHH:MM:SS.MSSZ
        sb.append(calendar.get(Calendar.YEAR));
        sb.append('-');
        sb.append(formatTwo(calendar.get(Calendar.MONTH) + 1));
        sb.append('-');
        sb.append(formatTwo(calendar.get(Calendar.DAY_OF_MONTH)));
        sb.append('T');
        sb.append(formatTwo(calendar.get(Calendar.HOUR_OF_DAY)));
        sb.append(':');
        sb.append(formatTwo(calendar.get(Calendar.MINUTE)));
        sb.append(':');
        sb.append(formatTwo(calendar.get(Calendar.SECOND)));
        sb.append(".000Z");
        return sb.toString();
    }

    /**
     * Note that messages in the deleted database preserve the message's unique id; therefore, we
     * can utilize this id to find references to the message.  The only reference situation at this
     * point is in the Body table; it is when sending messages via SmartForward and SmartReply
     */
    private boolean messageReferenced(ContentResolver cr, long id) {
        mBindArgument[0] = Long.toString(id);
        // See if this id is referenced in a body
        Cursor c = cr.query(Body.CONTENT_URI, Body.ID_PROJECTION, WHERE_BODY_SOURCE_MESSAGE_KEY,
                mBindArgument, null);
        try {
            return c.moveToFirst();
        } finally {
            c.close();
        }
    }

    /*private*/ /**
     * Serialize commands to delete items from the server; as we find items to delete, add their
     * id's to the deletedId's array
     *
     * @param s the Serializer we're using to create post data
     * @param deletedIds ids whose deletions are being sent to the server
     * @param first whether or not this is the first command being sent
     * @return true if SYNC_COMMANDS hasn't been sent (false otherwise)
     * @throws IOException
     */
    @VisibleForTesting
    boolean sendDeletedItems(Serializer s, ArrayList<Long> deletedIds, boolean first)
            throws IOException {
        ContentResolver cr = mContext.getContentResolver();

        // Find any of our deleted items
        Cursor c = cr.query(Message.DELETED_CONTENT_URI, Message.LIST_PROJECTION,
                MessageColumns.MAILBOX_KEY + '=' + mMailbox.mId, null, null);
        // We keep track of the list of deleted item id's so that we can remove them from the
        // deleted table after the server receives our command
        deletedIds.clear();
        try {
            while (c.moveToNext()) {
                String serverId = c.getString(Message.LIST_SERVER_ID_COLUMN);
                // Keep going if there's no serverId
                if (serverId == null) {
                    continue;
                // Also check if this message is referenced elsewhere
                } else if (messageReferenced(cr, c.getLong(Message.CONTENT_ID_COLUMN))) {
                    userLog("Postponing deletion of referenced message: ", serverId);
                    continue;
                } else if (first) {
                    s.start(Tags.SYNC_COMMANDS);
                    first = false;
                }
                // Send the command to delete this message
                s.start(Tags.SYNC_DELETE).data(Tags.SYNC_SERVER_ID, serverId).end();
                deletedIds.add(c.getLong(Message.LIST_ID_COLUMN));
            }
        } finally {
            c.close();
        }

       return first;
    }

    @Override
    public boolean sendLocalChanges(Serializer s) throws IOException {
        ContentResolver cr = mContext.getContentResolver();

        if (getSyncKey().equals("0")) {
            return false;
        }

        // Never upsync from these folders
        if (mMailbox.mType == Mailbox.TYPE_DRAFTS || mMailbox.mType == Mailbox.TYPE_OUTBOX) {
            return false;
        }

        // This code is split out for unit testing purposes
        boolean firstCommand = sendDeletedItems(s, mDeletedIdList, true);

        if (!mFetchRequestList.isEmpty()) {
            // 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)
            if (firstCommand) {
                s.start(Tags.SYNC_COMMANDS);
                firstCommand = false;
            }
            for (FetchRequest req: mFetchRequestList) {
                s.start(Tags.SYNC_FETCH).data(Tags.SYNC_SERVER_ID, req.serverId).end();
            }
        }

        // Find our trash mailbox, since deletions will have been moved there...
        long trashMailboxId =
            Mailbox.findMailboxOfType(mContext, mMailbox.mAccountKey, Mailbox.TYPE_TRASH);

        // Do the same now for updated items
        Cursor c = cr.query(Message.UPDATED_CONTENT_URI, Message.LIST_PROJECTION,
                MessageColumns.MAILBOX_KEY + '=' + mMailbox.mId, null, null);

        // We keep track of the list of updated item id's as we did above with deleted items
        mUpdatedIdList.clear();
        try {
            while (c.moveToNext()) {
                long id = c.getLong(Message.LIST_ID_COLUMN);
                // Say we've handled this update
                mUpdatedIdList.add(id);
                // We have the id of the changed item.  But first, we have to find out its current
                // state, since the updated table saves the opriginal state
                Cursor currentCursor = cr.query(ContentUris.withAppendedId(Message.CONTENT_URI, id),
                        UPDATES_PROJECTION, null, null, null);
                try {
                    // If this item no longer exists (shouldn't be possible), just move along
                    if (!currentCursor.moveToFirst()) {
                         continue;
                    }
                    // Keep going if there's no serverId
                    String serverId = currentCursor.getString(UPDATES_SERVER_ID_COLUMN);
                    if (serverId == null) {
                        continue;
                    }
                    // If the message is now in the trash folder, it has been deleted by the user
                    if (currentCursor.getLong(UPDATES_MAILBOX_KEY_COLUMN) == trashMailboxId) {
                         if (firstCommand) {
                            s.start(Tags.SYNC_COMMANDS);
                            firstCommand = false;
                        }
                        // Send the command to delete this message
                        s.start(Tags.SYNC_DELETE).data(Tags.SYNC_SERVER_ID, serverId).end();
                        continue;
                    }

                    boolean flagChange = false;
                    boolean readChange = false;

                    long mailbox = currentCursor.getLong(UPDATES_MAILBOX_KEY_COLUMN);
                    if (mailbox != c.getLong(Message.LIST_MAILBOX_KEY_COLUMN)) {
                        // The message has moved to another mailbox; add a request for this
                        // Note: The Sync command doesn't handle moving messages, so we need
                        // to handle this as a "request" (similar to meeting response and
                        // attachment load)
                        mService.addRequest(new MessageMoveRequest(id, mailbox));
                        // Regardless of other changes that might be made, we don't want to indicate
                        // that this message has been updated until the move request has been
                        // handled (without this, a crash between the flag upsync and the move
                        // would cause the move to be lost)
                        mUpdatedIdList.remove(id);
                    }

                    // We can only send flag changes to the server in 12.0 or later
                    int flag = 0;
                    if (mService.mProtocolVersionDouble >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) {
                        flag = currentCursor.getInt(UPDATES_FLAG_COLUMN);
                        if (flag != c.getInt(Message.LIST_FAVORITE_COLUMN)) {
                            flagChange = true;
                        }
                    }

                    int read = currentCursor.getInt(UPDATES_READ_COLUMN);
                    if (read != c.getInt(Message.LIST_READ_COLUMN)) {
                        readChange = true;
                    }

                    if (!flagChange && !readChange) {
                        // In this case, we've got nothing to send to the server
                        continue;
                    }

                    if (firstCommand) {
                        s.start(Tags.SYNC_COMMANDS);
                        firstCommand = false;
                    }
                    // Send the change to "read" and "favorite" (flagged)
                    s.start(Tags.SYNC_CHANGE)
                        .data(Tags.SYNC_SERVER_ID, c.getString(Message.LIST_SERVER_ID_COLUMN))
                        .start(Tags.SYNC_APPLICATION_DATA);
                    if (readChange) {
                        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 (flagChange) {
                        if (flag != 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");
                            long now = System.currentTimeMillis();
                            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 + 1*WEEKS);
                            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
                } finally {
                    currentCursor.close();
                }
            }
        } finally {
            c.close();
        }

        if (!firstCommand) {
            s.end(); // SYNC_COMMANDS
        }
        return false;
    }
}
