package com.android.exchange.adapter;

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.database.Cursor;
import android.os.Parcel;
import android.os.RemoteException;
import android.os.TransactionTooLargeException;
import android.provider.CalendarContract;
import android.text.Html;
import android.text.SpannedString;
import android.text.TextUtils;
import android.util.Base64;
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.Account;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.Mailbox;
import com.android.emailcommon.provider.Policy;
import com.android.emailcommon.provider.ProviderUnavailableException;
import com.android.emailcommon.utility.AttachmentUtilities;
import com.android.emailcommon.utility.ConversionUtilities;
import com.android.emailcommon.utility.TextUtilities;
import com.android.emailcommon.utility.Utility;
import com.android.exchange.CommandStatusException;
import com.android.exchange.Eas;
import com.android.exchange.utility.CalendarUtilities;
import com.android.mail.utils.LogUtils;
import com.google.common.annotations.VisibleForTesting;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;

/**
 * Parser for Sync on an email collection.
 */
public class EmailSyncParser extends AbstractSyncParser {
    private static final String TAG = Eas.LOG_TAG;

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

    private final String mMailboxIdAsString;

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

    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[] { EmailContent.Message.RECORD_ID, EmailContent.MessageColumns.SUBJECT };

    @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 Policy mPolicy;

    // Max times to retry when we get a TransactionTooLargeException exception
    private static final int MAX_RETRIES = 10;

    // Max number of ops per batch. It could end up more than this but once we detect we are at or
    // above this number, we flush.
    private static final int MAX_OPS_PER_BATCH = 50;

    private boolean mFetchNeeded = false;

    private final Map<String, Integer> mMessageUpdateStatus = new HashMap();

    public EmailSyncParser(final Context context, final ContentResolver resolver,
            final InputStream in, final Mailbox mailbox, final Account account)
            throws IOException {
        super(context, resolver, in, mailbox, account);
        mMailboxIdAsString = Long.toString(mMailbox.mId);
        if (mAccount.mPolicyKey != 0) {
            mPolicy = Policy.restorePolicyWithId(mContext, mAccount.mPolicyKey);
        } else {
            mPolicy = null;
        }
    }

    public boolean fetchNeeded() {
        return mFetchNeeded;
    }

    public Map<String, Integer> getMessageStatuses() {
        return mMessageUpdateStatus;
    }

    public void addData (EmailContent.Message msg, int endingTag) throws IOException {
        ArrayList<EmailContent.Attachment> atts = new ArrayList<EmailContent.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 = EmailContent.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 |= EmailContent.Message.FLAG_INCOMING_MEETING_INVITE;
                    } else if (messageClass.equals("IPM.Schedule.Meeting.Canceled")) {
                        msg.mFlags |= EmailContent.Message.FLAG_INCOMING_MEETING_CANCEL;
                    }
                    break;
                case Tags.EMAIL_MEETING_REQUEST:
                    meetingRequestParser(msg);
                    break;
                case Tags.EMAIL_THREAD_TOPIC:
                    msg.mThreadTopic = getValue();
                    break;
                case Tags.RIGHTS_LICENSE:
                    skipParser(tag);
                    break;
                case Tags.EMAIL2_CONVERSATION_ID:
                    msg.mServerConversationId =
                            Base64.encodeToString(getValueBytes(), Base64.URL_SAFE);
                    break;
                case Tags.EMAIL2_CONVERSATION_INDEX:
                    // Ignore this byte array since we're not constructing a tree.
                    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 |= EmailContent.Message.FLAG_REPLIED_TO;
                    } else if (val == LAST_VERB_FORWARD) {
                        msg.mFlags |= EmailContent.Message.FLAG_FORWARDED;
                    }
                    break;
                default:
                    skipTag();
            }
        }

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

        if ((msg.mFlags & EmailContent.Message.FLAG_INCOMING_MEETING_MASK) != 0) {
            String text = TextUtilities.makeSnippetFromHtmlText(
                    msg.mText != null ? msg.mText : msg.mHtml);
            if (TextUtils.isEmpty(text)) {
                // Create text for this invitation
                String meetingInfo = msg.mMeetingInfo;
                if (!TextUtils.isEmpty(meetingInfo)) {
                    PackedString ps = new PackedString(meetingInfo);
                    ContentValues values = new ContentValues();
                    putFromMeeting(ps, MeetingInfo.MEETING_LOCATION, values,
                            CalendarContract.Events.EVENT_LOCATION);
                    String dtstart = ps.get(MeetingInfo.MEETING_DTSTART);
                    if (!TextUtils.isEmpty(dtstart)) {
                        long startTime = Utility.parseEmailDateTimeToMillis(dtstart);
                        values.put(CalendarContract.Events.DTSTART, startTime);
                    }
                    putFromMeeting(ps, MeetingInfo.MEETING_ALL_DAY, values,
                            CalendarContract.Events.ALL_DAY);
                    msg.mText = CalendarUtilities.buildMessageTextFromEntityValues(
                            mContext, values, null);
                    msg.mHtml = Html.toHtml(new SpannedString(msg.mText));
                }
            }
        }
    }

    private static void putFromMeeting(PackedString ps, String field, ContentValues values,
            String column) {
        String val = ps.get(field);
        if (!TextUtils.isEmpty(val)) {
            values.put(column, val);
        }
    }

    /**
     * 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(EmailContent.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;
                case Tags.EMAIL_ALL_DAY_EVENT:
                    if (getValueInt() == 1) {
                        packedString.put(MeetingInfo.MEETING_ALL_DAY, "1");
                    }
                    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 EmailContent.Message addParser() throws IOException, CommandStatusException {
        EmailContent.Message msg = new EmailContent.Message();
        msg.mAccountKey = mAccount.mId;
        msg.mMailboxKey = mMailbox.mId;
        msg.mFlagLoaded = EmailContent.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(EmailContent.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 static void mimeBodyParser(EmailContent.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);
            // parseBodyFields fills in the content fields of the Body
            ConversionUtilities.BodyFieldData data =
                    ConversionUtilities.parseBodyFields(viewables);
            // But we need them in the message itself for handling during commit()
            msg.setFlags(data.isQuotedReply, data.isQuotedForward);
            msg.mSnippet = data.snippet;
            msg.mHtml = data.htmlContent;
            msg.mText = data.textContent;
        } catch (MessagingException e) {
            // This would most likely indicate a broken stream
            throw new IOException(e);
        }
    }

    private void attachmentsParser(ArrayList<EmailContent.Attachment> atts,
            EmailContent.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<EmailContent.Attachment> atts,
            EmailContent.Message msg) throws IOException {
        String fileName = null;
        String length = null;
        String location = null;
        boolean isInline = false;
        String contentId = 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;
                case Tags.BASE_IS_INLINE:
                    isInline = getValueInt() == 1;
                    break;
                case Tags.BASE_CONTENT_ID:
                    contentId = getValue();
                    break;
                default:
                    skipTag();
            }
        }

        if ((fileName != null) && (length != null) && (location != null)) {
            EmailContent.Attachment att = new EmailContent.Attachment();
            att.mEncoding = "base64";
            att.mSize = Long.parseLong(length);
            att.mFileName = fileName;
            att.mLocation = location;
            att.mMimeType = getMimeTypeFromFileName(fileName);
            att.mAccountKey = mAccount.mId;
            // Save away the contentId, if we've got one (for inline images); note that the
            // EAS docs appear to be wrong about the tags used; inline images come with
            // contentId rather than contentLocation, when sent from Ex03, Ex07, and Ex10
            if (isInline && !TextUtils.isEmpty(contentId)) {
                att.mContentId = contentId;
            }
            // 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 = EmailContent.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) {
        Cursor c = mContentResolver.query(EmailContent.Message.CONTENT_URI, projection,
                WHERE_SERVER_ID_AND_MAILBOX_KEY, new String[] {serverId, mMailboxIdAsString},
                null);
        if (c == null) throw new ProviderUnavailableException();
        if (c.getCount() > 1) {
            userLog("Multiple messages with the same serverId/mailbox: " + serverId);
        }
        return c;
    }

    @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, EmailContent.Message.LIST_PROJECTION);
                    try {
                        if (c.moveToFirst()) {
                            userLog("Changing ", serverId);
                            oldRead = c.getInt(EmailContent.Message.LIST_READ_COLUMN)
                                    == EmailContent.Message.READ;
                            oldFlag = c.getInt(EmailContent.Message.LIST_FAVORITE_COLUMN) == 1;
                            flags = c.getInt(EmailContent.Message.LIST_FLAGS_COLUMN);
                            id = c.getLong(EmailContent.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 & ~(EmailContent.Message.FLAG_REPLIED_TO
                            | EmailContent.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 |= EmailContent.Message.FLAG_REPLIED_TO;
                    } else if (val == LAST_VERB_FORWARD) {
                        flags |= EmailContent.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());
            } else if (tag == Tags.SYNC_DELETE || tag == Tags.SYNC_SOFT_DELETE) {
                deleteParser(deletedEmails, tag);
            } else if (tag == Tags.SYNC_CHANGE) {
                changeParser(changedEmails);
            } else
                skipTag();
        }
    }

    // EAS values for status element of sync responses.
    // TODO: Not all are used yet, but I wanted to transcribe all possible values.
    public static final int EAS_SYNC_STATUS_SUCCESS = 1;
    public static final int EAS_SYNC_STATUS_BAD_SYNC_KEY = 3;
    public static final int EAS_SYNC_STATUS_PROTOCOL_ERROR = 4;
    public static final int EAS_SYNC_STATUS_SERVER_ERROR = 5;
    public static final int EAS_SYNC_STATUS_BAD_CLIENT_DATA = 6;
    public static final int EAS_SYNC_STATUS_CONFLICT = 7;
    public static final int EAS_SYNC_STATUS_OBJECT_NOT_FOUND = 8;
    public static final int EAS_SYNC_STATUS_CANNOT_COMPLETE = 9;
    public static final int EAS_SYNC_STATUS_FOLDER_SYNC_NEEDED = 12;
    public static final int EAS_SYNC_STATUS_INCOMPLETE_REQUEST = 13;
    public static final int EAS_SYNC_STATUS_BAD_HEARTBEAT_VALUE = 14;
    public static final int EAS_SYNC_STATUS_TOO_MANY_COLLECTIONS = 15;
    public static final int EAS_SYNC_STATUS_RETRY = 16;

    public static boolean shouldRetry(final int status) {
        return status == EAS_SYNC_STATUS_SERVER_ERROR || status == EAS_SYNC_STATUS_RETRY;
    }

    /**
     * Parse the status for a single message update.
     * @param endTag the tag we end with
     * @throws IOException
     */
    public void messageUpdateParser(int endTag) throws IOException {
        // We get serverId and status in the responses
        String serverId = null;
        int status = -1;
        while (nextTag(endTag) != END) {
            if (tag == Tags.SYNC_STATUS) {
                status = getValueInt();
            } else if (tag == Tags.SYNC_SERVER_ID) {
                serverId = getValue();
            } else {
                skipTag();
            }
        }
        if (serverId != null && status != -1) {
            mMessageUpdateStatus.put(serverId, status);
        }
    }

    @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) {
                messageUpdateParser(tag);
            } 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
                        mContentResolver.delete(EmailContent.Message.CONTENT_URI,
                                WHERE_SERVER_ID_AND_MAILBOX_KEY,
                                new String[] {sse.mItemId, mMailboxIdAsString});
                    }
                }
            }
        }
    }

    @Override
    protected void wipe() {
        LogUtils.i(TAG, "Wiping mailbox " + mMailbox);
        Mailbox.resyncMailbox(mContentResolver, new android.accounts.Account(mAccount.mEmailAddress,
                Eas.EXCHANGE_ACCOUNT_MANAGER_TYPE), mMailbox.mId);
    }

    @Override
    public boolean parse() throws IOException, CommandStatusException {
        final boolean result = super.parse();
        return result || fetchNeeded();
    }

    /**
     * Commit all changes. This results in a Binder IPC call which has constraint on the size of
     * the data, the docs say it currently 1MB. We set a limit to the size of the message we fetch
     * with {@link Eas#EAS12_TRUNCATION_SIZE} & {@link Eas#EAS12_TRUNCATION_SIZE} which are at 200k
     * or bellow. As long as these limits are bellow 500k, we should be able to apply a single
     * message (the transaction size is about double the message size because Java strings are 16
     * bit.
     * <b/>
     * We first try to apply the changes in normal chunk size {@link #MAX_OPS_PER_BATCH}. If we get
     * a {@link TransactionTooLargeException} we try again with but this time, we apply each change
     * immediately.
     */
    @Override
    public void commit() throws RemoteException, OperationApplicationException {
        try {
            commitImpl(MAX_OPS_PER_BATCH);
        } catch (TransactionTooLargeException e) {
            // Try again but apply batch after every message. The max message size defined in
            // Eas.EAS12_TRUNCATION_SIZE or Eas.EAS2_5_TRUNCATION_SIZE is small enough to fit
            // in a single Binder call.
            LogUtils.w(TAG, "Transaction too large, retrying in single mode", e);
            commitImpl(1);
        }
    }

    public void commitImpl(int maxOpsPerBatch)
            throws RemoteException, OperationApplicationException {
        // Use a batch operation to handle the changes
        ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();

        // Maximum size of message text per fetch
        int numFetched = fetchedEmails.size();
        LogUtils.d(TAG, "commitImpl: maxOpsPerBatch=%d numFetched=%d numNew=%d "
                + "numDeleted=%d numChanged=%d",
                maxOpsPerBatch,
                numFetched,
                newEmails.size(),
                deletedEmails.size(),
                changedEmails.size());
        for (EmailContent.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);
                    while (c.moveToNext()) {
                        // This shouldn't happen, but clean up if it does
                        Long dupId =
                                Long.parseLong(c.getString(EmailContent.ID_PROJECTION_COLUMN));
                        userLog("Delete duplicate with id: " + dupId);
                        deletedEmails.add(dupId);
                    }
                }
            } 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) {
                LogUtils.i(TAG, "Fetched body successfully for %s", id);
                final String[] bindArgument = new String[] {id};
                ops.add(ContentProviderOperation.newUpdate(EmailContent.Body.CONTENT_URI)
                        .withSelection(EmailContent.Body.SELECTION_BY_MESSAGE_KEY, bindArgument)
                        .withValue(EmailContent.Body.TEXT_CONTENT, msg.mText)
                        .build());
                ops.add(ContentProviderOperation.newUpdate(EmailContent.Message.CONTENT_URI)
                        .withSelection(EmailContent.RECORD_ID + "=?", bindArgument)
                        .withValue(EmailContent.Message.FLAG_LOADED,
                                EmailContent.Message.FLAG_LOADED_COMPLETE)
                        .build());
            }
            applyBatchIfNeeded(ops, maxOpsPerBatch, false);
        }

        for (EmailContent.Message msg: newEmails) {
            msg.addSaveOps(ops);
            applyBatchIfNeeded(ops, maxOpsPerBatch, false);
        }

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

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

        // 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());

        applyBatchIfNeeded(ops, maxOpsPerBatch, true);
        userLog(mMailbox.mDisplayName, " SyncKey saved as: ", mMailbox.mSyncKey);
    }

    // Check if there at least MAX_OPS_PER_BATCH ops in queue and flush if there are.
    // If force is true, flush regardless of size.
    private void applyBatchIfNeeded(ArrayList<ContentProviderOperation> ops, int maxOpsPerBatch,
            boolean force)
            throws RemoteException, OperationApplicationException {
        if (force ||  ops.size() >= maxOpsPerBatch) {
            // STOPSHIP Remove calculating size of data before ship
            if (LogUtils.isLoggable(TAG, Log.DEBUG)) {
                final Parcel parcel = Parcel.obtain();
                for (ContentProviderOperation op : ops) {
                    op.writeToParcel(parcel, 0);
                }
                Log.d(TAG, String.format("Committing %d ops total size=%d",
                        ops.size(), parcel.dataSize()));
                parcel.recycle();
            }
            mContentResolver.applyBatch(EmailContent.AUTHORITY, ops);
            ops.clear();
        }
    }
}