/*
 * 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.Context;
import android.content.OperationApplicationException;
import android.database.Cursor;
import android.os.RemoteException;
import android.os.TransactionTooLargeException;
import android.text.TextUtils;
import android.util.SparseBooleanArray;
import android.util.SparseIntArray;

import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent;
import com.android.emailcommon.provider.EmailContent.AccountColumns;
import com.android.emailcommon.provider.EmailContent.MailboxColumns;
import com.android.emailcommon.provider.Mailbox;
import com.android.emailcommon.service.SyncWindow;
import com.android.emailcommon.utility.AttachmentUtilities;
import com.android.exchange.CommandStatusException;
import com.android.exchange.CommandStatusException.CommandStatus;
import com.android.exchange.Eas;
import com.android.exchange.eas.EasSyncContacts;
import com.android.exchange.service.EasCalendarSyncHandler;
import com.android.mail.utils.LogUtils;
import com.google.common.annotations.VisibleForTesting;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Set;

/**
 * Parse the result of a FolderSync command
 *
 * Handles the addition, deletion, and changes to folders in the user's Exchange account.
 **/

public class FolderSyncParser extends AbstractSyncParser {

    public static final String TAG = "FolderSyncParser";

    /**
     * Mapping from EAS type values to {@link Mailbox} types.
     * See http://msdn.microsoft.com/en-us/library/gg650877(v=exchg.80).aspx for the list of EAS
     * type values.
     * If an EAS type is not in the map, or is inserted with a value of {@link Mailbox#TYPE_NONE},
     * then we don't support that type and we should ignore it.
     * TODO: Maybe we should store the mailbox anyway, otherwise it'll be annoying to upgrade.
     */
    private static final SparseIntArray MAILBOX_TYPE_MAP;
    static {
        MAILBOX_TYPE_MAP = new SparseIntArray(11);
        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_USER_GENERIC,  Mailbox.TYPE_MAIL);
        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_INBOX,  Mailbox.TYPE_INBOX);
        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_DRAFTS,  Mailbox.TYPE_DRAFTS);
        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_DELETED,  Mailbox.TYPE_TRASH);
        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_SENT,  Mailbox.TYPE_SENT);
        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_OUTBOX,  Mailbox.TYPE_OUTBOX);
        //MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_TASKS,  Mailbox.TYPE_TASKS);
        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_CALENDAR,  Mailbox.TYPE_CALENDAR);
        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_CONTACTS,  Mailbox.TYPE_CONTACTS);
        //MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_NOTES, Mailbox.TYPE_NONE);
        //MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_JOURNAL, Mailbox.TYPE_NONE);
        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_USER_MAIL, Mailbox.TYPE_MAIL);
        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_USER_CALENDAR, Mailbox.TYPE_CALENDAR);
        MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_USER_CONTACTS, Mailbox.TYPE_CONTACTS);
        //MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_USER_TASKS, Mailbox.TYPE_TASKS);
        //MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_USER_JOURNAL, Mailbox.TYPE_NONE);
        //MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_USER_NOTES, Mailbox.TYPE_NONE);
        //MAILBOX_TYPE_MAP.put(Eas.MAILBOX_TYPE_UNKNOWN, Mailbox.TYPE_NONE);
        //MAILBOX_TYPE_MAP.put(MAILBOX_TYPE_RECIPIENT_INFORMATION_CACHE, Mailbox.TYPE_NONE);
    }

    /** Content selection for all mailboxes belonging to an account. */
    private static final String WHERE_ACCOUNT_KEY = MailboxColumns.ACCOUNT_KEY + "=?";

    /**
     * Content selection to find a specific mailbox by server id. Since server ids aren't unique
     * across all accounts, this must also check account id.
     */
    private static final String WHERE_SERVER_ID_AND_ACCOUNT = MailboxColumns.SERVER_ID + "=? and " +
        MailboxColumns.ACCOUNT_KEY + "=?";

    /**
     * Content selection to find a specific mailbox by display name and account.
     */
    private static final String WHERE_DISPLAY_NAME_AND_ACCOUNT = MailboxColumns.DISPLAY_NAME +
        "=? and " + MailboxColumns.ACCOUNT_KEY + "=?";

    /**
     * Content selection to find children by parent's server id. Since server ids aren't unique
     * across accounts, this must also use account id.
     */
    private static final String WHERE_PARENT_SERVER_ID_AND_ACCOUNT =
        MailboxColumns.PARENT_SERVER_ID +"=? and " + MailboxColumns.ACCOUNT_KEY + "=?";

    /** Projection used when fetching a Mailbox's ids. */
    private static final String[] MAILBOX_ID_COLUMNS_PROJECTION =
        new String[] {MailboxColumns.ID, MailboxColumns.SERVER_ID, MailboxColumns.PARENT_SERVER_ID};
    private static final int MAILBOX_ID_COLUMNS_ID = 0;
    private static final int MAILBOX_ID_COLUMNS_SERVER_ID = 1;
    private static final int MAILBOX_ID_COLUMNS_PARENT_SERVER_ID = 2;

    /** Projection used for changed parents during parent/child fixup. */
    private static final String[] FIXUP_PARENT_PROJECTION =
            { MailboxColumns.ID, MailboxColumns.FLAGS };
    private static final int FIXUP_PARENT_ID_COLUMN = 0;
    private static final int FIXUP_PARENT_FLAGS_COLUMN = 1;

    /** Projection used for changed children during parent/child fixup. */
    private static final String[] FIXUP_CHILD_PROJECTION =
            { MailboxColumns.ID };
    private static final int FIXUP_CHILD_ID_COLUMN = 0;

    /** Flags that are set or cleared when a mailbox's child status changes. */
    private static final int HAS_CHILDREN_FLAGS =
            Mailbox.FLAG_HAS_CHILDREN | Mailbox.FLAG_CHILDREN_VISIBLE;

    /** Mailbox.NO_MAILBOX, as a string (convenience since this is used in several places). */
    private static final String NO_MAILBOX_STRING = Long.toString(Mailbox.NO_MAILBOX);

    @VisibleForTesting
    long mAccountId;
    @VisibleForTesting
    String mAccountIdAsString;

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

    /** List of pending operations to send as a batch to the content provider. */
    private final ArrayList<ContentProviderOperation> mOperations =
            new ArrayList<ContentProviderOperation>();
    /** Indicates whether this sync is an initial FolderSync. */
    private boolean mInitialSync;
    /** List of folder server ids whose children changed with this sync. */
    private final Set<String> mParentFixupsNeeded = new LinkedHashSet<String>();
    /** Indicates whether the sync response provided a different sync key than we had. */
    private boolean mSyncKeyChanged = false;

    // If true, we only care about status (this is true when validating an account) and ignore
    // other data
    private final boolean mStatusOnly;

    /** Map of folder types that have been created during this sync. */
    private final SparseBooleanArray mCreatedFolderTypes =
            new SparseBooleanArray(Mailbox.REQUIRED_FOLDER_TYPES.length);

    private static final ContentValues UNINITIALIZED_PARENT_KEY = new ContentValues();

    static {
        UNINITIALIZED_PARENT_KEY.put(MailboxColumns.PARENT_KEY, Mailbox.PARENT_KEY_UNINITIALIZED);
    }

    public FolderSyncParser(final Context context, final ContentResolver resolver,
            final InputStream in, final Account account, final boolean statusOnly)
                    throws IOException {
        super(context, resolver, in, null, account);
        mAccountId = mAccount.mId;
        mAccountIdAsString = Long.toString(mAccountId);
        mStatusOnly = statusOnly;
    }

    public FolderSyncParser(InputStream in, AbstractSyncAdapter adapter) throws IOException {
        this(in, adapter, false);
    }

    public FolderSyncParser(InputStream in, AbstractSyncAdapter adapter, boolean statusOnly)
            throws IOException {
        super(in, adapter);
        mAccountId = mAccount.mId;
        mAccountIdAsString = Long.toString(mAccountId);
        mStatusOnly = statusOnly;
    }

    @Override
    public boolean parse() throws IOException, CommandStatusException {
        int status;
        boolean res = false;
        boolean resetFolders = false;
        mInitialSync = (mAccount.mSyncKey == null) || "0".equals(mAccount.mSyncKey);
        if (mInitialSync) {
            // We're resyncing all folders for this account, so nuke any existing ones.
            mContentResolver.delete(Mailbox.CONTENT_URI, WHERE_ACCOUNT_KEY,
                    new String[] {mAccountIdAsString});
        }
        if (nextTag(START_DOCUMENT) != Tags.FOLDER_FOLDER_SYNC)
            throw new EasParserException();
        while (nextTag(START_DOCUMENT) != END_DOCUMENT) {
            if (tag == Tags.FOLDER_STATUS) {
                status = getValueInt();
                // Do a sanity check on the account here; if we have any duplicated folders, we'll
                // act as though we have a bad folder sync key (wipe/reload mailboxes)
                // Note: The ContentValues isn't used, but no point creating a new one
                int dupes = 0;
                if (mAccountId > 0) {
                    dupes = mContentResolver.update(
                            ContentUris.withAppendedId(EmailContent.ACCOUNT_CHECK_URI, mAccountId),
                            UNINITIALIZED_PARENT_KEY, null, null);
                }
                if (dupes > 0) {
                    LogUtils.w(TAG, "Duplicate mailboxes found for account %d: %d", mAccountId,
                            dupes);
                    status = Eas.FOLDER_STATUS_INVALID_KEY;
                }
                if (status != Eas.FOLDER_STATUS_OK) {
                    // If the account hasn't been saved, this is a validation attempt, so we don't
                    // try reloading the folder list...
                    if (CommandStatus.isDeniedAccess(status) ||
                            CommandStatus.isNeedsProvisioning(status) ||
                            (mAccount.mId == Account.NOT_SAVED)) {
                        LogUtils.e(LogUtils.TAG, "FolderSync: Unknown status: " + status);
                        throw new CommandStatusException(status);
                    // Note that we need to catch both old-style (Eas.FOLDER_STATUS_INVALID_KEY)
                    // and EAS 14 style command status
                    } else if (status == Eas.FOLDER_STATUS_INVALID_KEY ||
                            CommandStatus.isBadSyncKey(status)) {
                        wipe();
                        // Reconstruct _main
                        res = true;
                        resetFolders = true;
                    } else {
                        // Other errors are at the server, so let's throw an error that will
                        // cause this sync to be retried at a later time
                        throw new EasParserException("Folder status error");
                    }
                }
            } else if (tag == Tags.FOLDER_SYNC_KEY) {
                final String newKey = getValue();
                if (newKey != null && !resetFolders) {
                    mSyncKeyChanged = !newKey.equals(mAccount.mSyncKey);
                    mAccount.mSyncKey = newKey;
                }
            } else if (tag == Tags.FOLDER_CHANGES) {
                if (mStatusOnly) return res;
                changesParser();
            } else
                skipTag();
        }
        if (!mStatusOnly) {
            commit();
        }
        return res;
    }

    /**
     * Get a cursor with folder ids for a specific folder.
     * @param serverId The server id for the folder we are interested in.
     * @return A cursor for the folder specified by serverId for this account.
     */
    private Cursor getServerIdCursor(final String serverId) {
        mBindArguments[0] = serverId;
        mBindArguments[1] = mAccountIdAsString;
        return mContentResolver.query(Mailbox.CONTENT_URI, MAILBOX_ID_COLUMNS_PROJECTION,
                WHERE_SERVER_ID_AND_ACCOUNT, mBindArguments, null);
    }

    /**
     * Add the appropriate {@link ContentProviderOperation} to {@link #mOperations} for a Delete
     * change in the FolderSync response.
     * @throws IOException
     */
    private void deleteParser() throws IOException {
        while (nextTag(Tags.FOLDER_DELETE) != END) {
            switch (tag) {
                case Tags.FOLDER_SERVER_ID:
                    final String serverId = getValue();
                    // Find the mailbox in this account with the given serverId
                    final Cursor c = getServerIdCursor(serverId);
                    try {
                        if (c.moveToFirst()) {
                            LogUtils.d(TAG, "Deleting %s", serverId);
                            final long mailboxId = c.getLong(MAILBOX_ID_COLUMNS_ID);
                            mOperations.add(ContentProviderOperation.newDelete(
                                    ContentUris.withAppendedId(Mailbox.CONTENT_URI,
                                            mailboxId)).build());
                            AttachmentUtilities.deleteAllMailboxAttachmentFiles(mContext,
                                    mAccountId, mailboxId);
                            final String parentId =
                                    c.getString(MAILBOX_ID_COLUMNS_PARENT_SERVER_ID);
                            if (!TextUtils.isEmpty(parentId)) {
                                mParentFixupsNeeded.add(parentId);
                            }
                        }
                    } finally {
                        c.close();
                    }
                    break;
                default:
                    skipTag();
            }
        }
    }

    private static class SyncOptions {
        private final int mInterval;
        private final int mLookback;

        private SyncOptions(int interval, int lookback) {
            mInterval = interval;
            mLookback = lookback;
        }
    }

    private static final String MAILBOX_STATE_SELECTION =
        MailboxColumns.ACCOUNT_KEY + "=? AND (" + MailboxColumns.SYNC_INTERVAL + "!=" +
            Account.CHECK_INTERVAL_NEVER + " OR " + Mailbox.SYNC_LOOKBACK + "!=" +
            SyncWindow.SYNC_WINDOW_ACCOUNT + ")";

    private static final String[] MAILBOX_STATE_PROJECTION = new String[] {
        MailboxColumns.SERVER_ID, MailboxColumns.SYNC_INTERVAL, MailboxColumns.SYNC_LOOKBACK};
    private static final int MAILBOX_STATE_SERVER_ID = 0;
    private static final int MAILBOX_STATE_INTERVAL = 1;
    private static final int MAILBOX_STATE_LOOKBACK = 2;
    @VisibleForTesting
    final HashMap<String, SyncOptions> mSyncOptionsMap = new HashMap<String, SyncOptions>();

    /**
     * For every mailbox in this account that has a non-default interval or lookback, save those
     * values.
     */
    @VisibleForTesting
    void saveMailboxSyncOptions() {
        // Shouldn't be necessary, but...
        mSyncOptionsMap.clear();
        Cursor c = mContentResolver.query(Mailbox.CONTENT_URI, MAILBOX_STATE_PROJECTION,
                MAILBOX_STATE_SELECTION, new String[] {mAccountIdAsString}, null);
        if (c != null) {
            try {
                while (c.moveToNext()) {
                    mSyncOptionsMap.put(c.getString(MAILBOX_STATE_SERVER_ID),
                            new SyncOptions(c.getInt(MAILBOX_STATE_INTERVAL),
                                    c.getInt(MAILBOX_STATE_LOOKBACK)));
                }
            } finally {
                c.close();
            }
        }
    }

    /**
     * For every set of saved mailbox sync options, try to find and restore those values
     */
    @VisibleForTesting
    void restoreMailboxSyncOptions() {
        try {
            ContentValues cv = new ContentValues();
            mBindArguments[1] = mAccountIdAsString;
            for (String serverId: mSyncOptionsMap.keySet()) {
                SyncOptions options = mSyncOptionsMap.get(serverId);
                cv.put(MailboxColumns.SYNC_INTERVAL, options.mInterval);
                cv.put(MailboxColumns.SYNC_LOOKBACK, options.mLookback);
                mBindArguments[0] = serverId;
                // If we match account and server id, set the sync options
                mContentResolver.update(Mailbox.CONTENT_URI, cv, WHERE_SERVER_ID_AND_ACCOUNT,
                        mBindArguments);
            }
        } finally {
            mSyncOptionsMap.clear();
        }
    }

    /**
     * Add a {@link ContentProviderOperation} to {@link #mOperations} to add a mailbox.
     * @param name The new mailbox's name.
     * @param serverId The new mailbox's server id.
     * @param parentServerId The server id of the new mailbox's parent ("0" if none).
     * @param mailboxType The mailbox's type, which is one of the values defined in {@link Mailbox}.
     * @param fromServer Whether this mailbox was synced from server (as opposed to local-only).
     * @throws IOException
     */
    private void addMailboxOp(final String name, final String serverId,
            final String parentServerId, final int mailboxType, final boolean fromServer)
            throws IOException {
        final ContentValues cv = new ContentValues(10);
        cv.put(MailboxColumns.DISPLAY_NAME, name);
        if (fromServer) {
            cv.put(MailboxColumns.SERVER_ID, serverId);
            final String parentId;
            if (parentServerId.equals("0")) {
                parentId = NO_MAILBOX_STRING;
                cv.put(MailboxColumns.PARENT_KEY, Mailbox.NO_MAILBOX);
            } else {
                parentId = parentServerId;
                mParentFixupsNeeded.add(parentId);
            }
            cv.put(MailboxColumns.PARENT_SERVER_ID, parentId);
        } else {
            cv.put(MailboxColumns.SERVER_ID, "");
            cv.put(MailboxColumns.PARENT_KEY, Mailbox.NO_MAILBOX);
            cv.put(MailboxColumns.PARENT_SERVER_ID, NO_MAILBOX_STRING);
            cv.put(MailboxColumns.TOTAL_COUNT, -1);
        }
        cv.put(MailboxColumns.ACCOUNT_KEY, mAccountId);
        cv.put(MailboxColumns.TYPE, mailboxType);

        final boolean shouldSync = fromServer && Mailbox.getDefaultSyncStateForType(mailboxType);
        cv.put(MailboxColumns.SYNC_INTERVAL, shouldSync ? 1 : 0);

        // Set basic flags
        int flags = 0;
        if (mailboxType <= Mailbox.TYPE_NOT_EMAIL) {
            flags |= Mailbox.FLAG_HOLDS_MAIL + Mailbox.FLAG_SUPPORTS_SETTINGS;
        }
        // Outbox, Drafts, and Sent don't allow mail to be moved to them
        if (mailboxType == Mailbox.TYPE_MAIL || mailboxType == Mailbox.TYPE_TRASH ||
                mailboxType == Mailbox.TYPE_JUNK || mailboxType == Mailbox.TYPE_INBOX) {
            flags |= Mailbox.FLAG_ACCEPTS_MOVED_MAIL;
        }
        cv.put(MailboxColumns.FLAGS, flags);

        // Make boxes like Contacts and Calendar invisible in the folder list
        cv.put(MailboxColumns.FLAG_VISIBLE, (mailboxType < Mailbox.TYPE_NOT_EMAIL));

        mOperations.add(
                ContentProviderOperation.newInsert(Mailbox.CONTENT_URI).withValues(cv).build());

        mCreatedFolderTypes.put(mailboxType, true);
    }

    /**
     * Add the appropriate {@link ContentProviderOperation} to {@link #mOperations} for an Add
     * change in the FolderSync response.
     * @throws IOException
     */
    private void addParser() throws IOException {
        String name = null;
        String serverId = null;
        String parentId = null;
        int type = 0;

        while (nextTag(Tags.FOLDER_ADD) != END) {
            switch (tag) {
                case Tags.FOLDER_DISPLAY_NAME: {
                    name = getValue();
                    break;
                }
                case Tags.FOLDER_TYPE: {
                    type = getValueInt();
                    break;
                }
                case Tags.FOLDER_PARENT_ID: {
                    parentId = getValue();
                    break;
                }
                case Tags.FOLDER_SERVER_ID: {
                    serverId = getValue();
                    break;
                }
                default:
                    skipTag();
            }
        }
        if (name != null && serverId != null && parentId != null) {
            final int mailboxType = MAILBOX_TYPE_MAP.get(type, Mailbox.TYPE_NONE);
            if (mailboxType != Mailbox.TYPE_NONE) {
                if (type == Eas.MAILBOX_TYPE_CALENDAR && !name.contains(mAccount.mEmailAddress)) {
                    name = mAccount.mEmailAddress;
                }
                addMailboxOp(name, serverId, parentId, mailboxType, true);
            }
        }
    }

    /**
     * Add the appropriate {@link ContentProviderOperation} to {@link #mOperations} for an Update
     * change in the FolderSync response.
     * @throws IOException
     */
    private void updateParser() throws IOException {
        String serverId = null;
        String displayName = null;
        String parentId = null;
        while (nextTag(Tags.FOLDER_UPDATE) != END) {
            switch (tag) {
                case Tags.FOLDER_SERVER_ID:
                    serverId = getValue();
                    break;
                case Tags.FOLDER_DISPLAY_NAME:
                    displayName = getValue();
                    break;
                case Tags.FOLDER_PARENT_ID:
                    parentId = getValue();
                    break;
                default:
                    skipTag();
                    break;
            }
        }
        // We'll make a change if one of parentId or displayName are specified
        // serverId is required, but let's be careful just the same
        if (serverId != null && (displayName != null || parentId != null)) {
            final Cursor c = getServerIdCursor(serverId);
            try {
                // If we find the mailbox (using serverId), make the change
                if (c.moveToFirst()) {
                    LogUtils.d(TAG, "Updating %s", serverId);
                    final ContentValues cv = new ContentValues();
                    // Store the new parent key.
                    cv.put(Mailbox.PARENT_SERVER_ID, parentId);
                    // Fix up old and new parents, as needed
                    if (!TextUtils.isEmpty(parentId)) {
                        mParentFixupsNeeded.add(parentId);
                    } else {
                        cv.put(Mailbox.PARENT_KEY, Mailbox.NO_MAILBOX);
                    }
                    final String oldParentId = c.getString(MAILBOX_ID_COLUMNS_PARENT_SERVER_ID);
                    if (!TextUtils.isEmpty(oldParentId)) {
                        mParentFixupsNeeded.add(oldParentId);
                    }
                    // Set display name if we've got one
                    if (displayName != null) {
                        cv.put(Mailbox.DISPLAY_NAME, displayName);
                    }
                    mOperations.add(ContentProviderOperation.newUpdate(
                            ContentUris.withAppendedId(Mailbox.CONTENT_URI,
                                    c.getLong(MAILBOX_ID_COLUMNS_ID))).withValues(cv).build());
                }
            } finally {
                c.close();
            }
        }
    }

    /**
     * Handle the Changes element of the FolderSync response. This is the container for Add, Delete,
     * and Update elements.
     * @throws IOException
     */
    private void changesParser() throws IOException {
        while (nextTag(Tags.FOLDER_CHANGES) != END) {
            if (tag == Tags.FOLDER_ADD) {
                addParser();
            } else if (tag == Tags.FOLDER_DELETE) {
                deleteParser();
            } else if (tag == Tags.FOLDER_UPDATE) {
                updateParser();
            } else if (tag == Tags.FOLDER_COUNT) {
                // TODO: Maybe we can make use of this count somehow.
                getValueInt();
            } else
                skipTag();
        }
    }

    /**
     * Commit the contents of {@link #mOperations} to the content provider.
     * @throws IOException
     */
    private void flushOperations() throws IOException {
        if (mOperations.isEmpty()) {
            return;
        }
        int transactionSize = mOperations.size();
        final ArrayList<ContentProviderOperation> subOps =
                new ArrayList<ContentProviderOperation>(transactionSize);
        while (!mOperations.isEmpty()) {
            subOps.clear();
            subOps.addAll(mOperations.subList(0, transactionSize));
            // Try to apply the ops. If the transaction is too large, split it in half and try again
            // If some other error happens then throw an IOException up the stack.
            try {
                mContentResolver.applyBatch(EmailContent.AUTHORITY, subOps);
                mOperations.removeAll(subOps);
            } catch (final TransactionTooLargeException e) {
                // If the transaction is too large, try splitting it.
                if (transactionSize == 1) {
                    LogUtils.e(TAG, "Single operation transaction too large");
                    throw new IOException("Single operation transaction too large");
                }
                LogUtils.d(TAG, "Transaction operation count %d too large, halving...",
                        transactionSize);
                transactionSize = transactionSize / 2;
                if (transactionSize < 1) {
                    transactionSize = 1;
                }
            } catch (final RemoteException e) {
                LogUtils.e(TAG, "RemoteException in commit");
                throw new IOException("RemoteException in commit");
            } catch (final OperationApplicationException e) {
                LogUtils.e(TAG, "OperationApplicationException in commit");
                throw new IOException("OperationApplicationException in commit");
            }
        }
        mOperations.clear();
    }

    /**
     * Fix folder data for any folders whose parent or children changed during this sync.
     * Unfortunately this cannot be done in the same pass as the actual sync: newly synced folders
     * lack ids until they're committed to the content provider, so we can't set the parentKey
     * for their children.
     * During parsing, we only track the parents who have changed. We need to do a query for
     * children anyway (to determine whether a parent still has any) so it's simpler to not bother
     * tracking which folders have had their parents changed.
     * TODO: Figure out if we can avoid the two-pass.
     * @throws IOException
     */
    private void doParentFixups() throws IOException {
        if (mParentFixupsNeeded.isEmpty()) {
            return;
        }

        // These objects will be used in every loop iteration, so create them here for efficiency
        // and just reset the values inside the loop as necessary.
        final String[] bindArguments = new String[2];
        bindArguments[1] = mAccountIdAsString;
        final ContentValues cv = new ContentValues(1);

        for (final String parentServerId : mParentFixupsNeeded) {
            // Get info about this parent.
            bindArguments[0] = parentServerId;
            final Cursor parentCursor = mContentResolver.query(Mailbox.CONTENT_URI,
                    FIXUP_PARENT_PROJECTION, WHERE_SERVER_ID_AND_ACCOUNT, bindArguments, null);
            if (parentCursor == null) {
                // TODO: Error handling.
                continue;
            }
            final long parentId;
            final int parentFlags;
            try {
                if (parentCursor.moveToFirst()) {
                    parentId = parentCursor.getLong(FIXUP_PARENT_ID_COLUMN);
                    parentFlags = parentCursor.getInt(FIXUP_PARENT_FLAGS_COLUMN);
                } else {
                    // TODO: Error handling.
                    continue;
                }
            } finally {
                parentCursor.close();
            }

            // Fix any children for this parent.
            final Cursor childCursor = mContentResolver.query(Mailbox.CONTENT_URI,
                    FIXUP_CHILD_PROJECTION, WHERE_PARENT_SERVER_ID_AND_ACCOUNT, bindArguments,
                    null);
            boolean hasChildren = false;
            if (childCursor != null) {
                try {
                    // Clear the results of the last iteration.
                    cv.clear();
                    // All children in this loop share the same parentId.
                    cv.put(MailboxColumns.PARENT_KEY, parentId);
                    while (childCursor.moveToNext()) {
                        final long childId = childCursor.getLong(FIXUP_CHILD_ID_COLUMN);
                        mOperations.add(ContentProviderOperation.newUpdate(
                                ContentUris.withAppendedId(Mailbox.CONTENT_URI, childId)).
                                withValues(cv).build());
                        hasChildren = true;
                    }
                } finally {
                    childCursor.close();
                }
            }

            // Fix the parent's flags based on whether it now has children.
            final int newFlags;

            if (hasChildren) {
                newFlags = parentFlags | HAS_CHILDREN_FLAGS;
            } else {
                newFlags = parentFlags & ~HAS_CHILDREN_FLAGS;
            }
            if (newFlags != parentFlags) {
                cv.clear();
                cv.put(MailboxColumns.FLAGS, newFlags);
                mOperations.add(ContentProviderOperation.newUpdate(ContentUris.withAppendedId(
                        Mailbox.CONTENT_URI, parentId)).withValues(cv).build());
            }
            flushOperations();
        }
    }

    @Override
    public void commandsParser() throws IOException {
    }

    @Override
    public void commit() throws IOException {
        // Set the account sync key.
        if (mSyncKeyChanged) {
            final ContentValues cv = new ContentValues(1);
            cv.put(AccountColumns.SYNC_KEY, mAccount.mSyncKey);
            mOperations.add(
                    ContentProviderOperation.newUpdate(mAccount.getUri()).withValues(cv).build());
        }

        // If this is the initial sync, make sure we have all the required folder types.
        if (mInitialSync) {
            for (final int requiredType : Mailbox.REQUIRED_FOLDER_TYPES) {
                if (!mCreatedFolderTypes.get(requiredType)) {
                    addMailboxOp(Mailbox.getSystemMailboxName(mContext, requiredType),
                            null, null, requiredType, false);
                }
            }
        }

        // Send all operations so far.
        flushOperations();

        // Now that new mailboxes are committed, let's do parent fixups.
        doParentFixups();

        // Look for sync issues and its children and delete them
        // I'm not aware of any other way to deal with this properly
        mBindArguments[0] = "Sync Issues";
        mBindArguments[1] = mAccountIdAsString;
        Cursor c = mContentResolver.query(Mailbox.CONTENT_URI,
                MAILBOX_ID_COLUMNS_PROJECTION, WHERE_DISPLAY_NAME_AND_ACCOUNT,
                mBindArguments, null);
        String parentServerId = null;
        long id = 0;
        try {
            if (c.moveToFirst()) {
                id = c.getLong(MAILBOX_ID_COLUMNS_ID);
                parentServerId = c.getString(MAILBOX_ID_COLUMNS_SERVER_ID);
            }
        } finally {
            c.close();
        }
        if (parentServerId != null) {
            mContentResolver.delete(ContentUris.withAppendedId(Mailbox.CONTENT_URI, id),
                    null, null);
            mBindArguments[0] = parentServerId;
            mContentResolver.delete(Mailbox.CONTENT_URI, WHERE_PARENT_SERVER_ID_AND_ACCOUNT,
                    mBindArguments);
        }

        // If we have saved options, restore them now
        if (mInitialSync) {
            restoreMailboxSyncOptions();
        }
    }

    @Override
    public void responsesParser() throws IOException {
    }

    @Override
    protected void wipe() {
        EasCalendarSyncHandler.wipeAccountFromContentProvider(mContext,
                mAccount.mEmailAddress);
        EasSyncContacts.wipeAccountFromContentProvider(mContext,
                mAccount.mEmailAddress);

        // Save away any mailbox sync information that is NOT default
        saveMailboxSyncOptions();
        // And only then, delete mailboxes
        mContentResolver.delete(Mailbox.CONTENT_URI, WHERE_ACCOUNT_KEY,
                new String[] {mAccountIdAsString});
        // Reset the sync key and save.
        mAccount.mSyncKey = "0";
        ContentValues cv = new ContentValues();
        cv.put(AccountColumns.SYNC_KEY, mAccount.mSyncKey);
        mContentResolver.update(ContentUris.withAppendedId(Account.CONTENT_URI,
                mAccount.mId), cv, null, null);
    }
}
