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.toHeader(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.toHeader(froms);
                    break;
                case Tags.EMAIL_CC:
                    msg.mCc = Address.toHeader(Address.parse(getValue()));
                    break;
                case Tags.EMAIL_REPLY_TO:
                    msg.mReplyTo = Address.toHeader(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();
        }
    }
}