/*
 * 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.text.TextUtils;

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.ExchangeService;
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.Arrays;
import java.util.HashMap;
import java.util.List;

/**
 * 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";

    // These are defined by the EAS protocol
    public static final int USER_GENERIC_TYPE = 1;
    public static final int INBOX_TYPE = 2;
    public static final int DRAFTS_TYPE = 3;
    public static final int DELETED_TYPE = 4;
    public static final int SENT_TYPE = 5;
    public static final int OUTBOX_TYPE = 6;
    public static final int TASKS_TYPE = 7;
    public static final int CALENDAR_TYPE = 8;
    public static final int CONTACTS_TYPE = 9;
    public static final int NOTES_TYPE = 10;
    public static final int JOURNAL_TYPE = 11;
    public static final int USER_MAILBOX_TYPE = 12;

    // EAS types that we are willing to consider valid folders for EAS sync
    private static final List<Integer> VALID_EAS_FOLDER_TYPES = Arrays.asList(INBOX_TYPE,
            DRAFTS_TYPE, DELETED_TYPE, SENT_TYPE, OUTBOX_TYPE, USER_MAILBOX_TYPE, CALENDAR_TYPE,
            CONTACTS_TYPE, USER_GENERIC_TYPE);

    /** 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.DISPLAY_NAME, MailboxColumns.HIERARCHICAL_NAME,
                    MailboxColumns.FLAGS };
    private static final int FIXUP_PARENT_ID_COLUMN = 0;
    private static final int FIXUP_PARENT_DISPLAY_NAME_COLUMN = 1;
    private static final int FIXUP_PARENT_HIERARCHICAL_NAME_COLUMN = 2;
    private static final int FIXUP_PARENT_FLAGS_COLUMN = 3;

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

    /** 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;
    @VisibleForTesting
    boolean mInUnitTest = false;

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

    /** List of pending operations to send as a batch to the content provider. */
    private 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 ArrayList<String> mParentFixupsNeeded = new ArrayList<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;

    private boolean mOutboxCreated = false;

    private static final ContentValues UNINITIALIZED_PARENT_KEY = new ContentValues();

    {
        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)) {
                        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)) {
                        // Delete PIM data
                        ExchangeService.deleteAccountPIMData(mContext, mAccountId);
                        // 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});
                        // Reconstruct _main
                        res = true;
                        resetFolders = true;
                        // Reset the sync key and save (this should trigger the AccountObserver
                        // in ExchangeService, which will recreate the account mailbox, which
                        // will then start syncing folders, etc.)
                        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);
                    } 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.i(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_UNKNOWN + ")";

    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 easType The mailbox's type, in terms of the EAS values (NOT {@link Mailbox}'s type
     *                values).
     * @throws IOException
     */
    private void addMailboxOp(final String name, final String serverId,
            final String parentServerId, final int easType) throws IOException {
        final ContentValues cv = new ContentValues();
        cv.put(MailboxColumns.DISPLAY_NAME, name);
        cv.put(MailboxColumns.SERVER_ID, serverId);
        final String parentId;
        if (parentServerId.equals("0")) {
            parentId = NO_MAILBOX_STRING;
            cv.put(Mailbox.PARENT_KEY, Mailbox.NO_MAILBOX);
        } else {
            parentId = parentServerId;
            mParentFixupsNeeded.add(parentId);
        }
        cv.put(MailboxColumns.PARENT_SERVER_ID, parentId);
        cv.put(MailboxColumns.ACCOUNT_KEY, mAccountId);
        final int mailboxType;
        final boolean shouldSync;
        switch (easType) {
            case INBOX_TYPE:
                mailboxType = Mailbox.TYPE_INBOX;
                shouldSync = true;
                break;
            case CONTACTS_TYPE:
                mailboxType = Mailbox.TYPE_CONTACTS;
                shouldSync = true;
                break;
            case OUTBOX_TYPE:
                // TYPE_OUTBOX mailboxes are known by ExchangeService to sync whenever they
                // aren't empty.  The value of mSyncFrequency is ignored for this kind of
                // mailbox.
                mailboxType = Mailbox.TYPE_OUTBOX;
                shouldSync = false;
                mOutboxCreated = true;
                break;
            case SENT_TYPE:
                mailboxType = Mailbox.TYPE_SENT;
                shouldSync = false;
                break;
            case DRAFTS_TYPE:
                mailboxType = Mailbox.TYPE_DRAFTS;
                shouldSync = false;
                break;
            case DELETED_TYPE:
                mailboxType = Mailbox.TYPE_TRASH;
                shouldSync = false;
                break;
            case CALENDAR_TYPE:
                mailboxType = Mailbox.TYPE_CALENDAR;
                shouldSync = true;
                break;
            default:
                mailboxType = Mailbox.TYPE_MAIL;
                shouldSync = false;
        }
        cv.put(MailboxColumns.TYPE, 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());
    }

    /**
     * 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 (VALID_EAS_FOLDER_TYPES.contains(type)) {
            addMailboxOp(name, serverId, parentId, type);
        }
    }

    /**
     * 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.i(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;
        }
        // Execute the batch; throw IOExceptions if this fails, hoping the issue isn't repeatable
        // If it IS repeatable, there's no good result, since the folder list will be invalid
        try {
            mContentResolver.applyBatch(EmailContent.AUTHORITY, mOperations);
        } 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(2);

        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 String parentHierarchicalName;
            final int parentFlags;
            try {
                if (parentCursor.moveToFirst()) {
                    parentId = parentCursor.getLong(FIXUP_PARENT_ID_COLUMN);
                    final String hierarchicalName = parentCursor.getString(
                            FIXUP_PARENT_HIERARCHICAL_NAME_COLUMN);
                    if (hierarchicalName != null) {
                        parentHierarchicalName = hierarchicalName;
                    } else {
                        parentHierarchicalName = parentCursor.getString(
                                FIXUP_PARENT_DISPLAY_NAME_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);
                        final String childName =
                                childCursor.getString(FIXUP_CHILD_DISPLAY_NAME_COLUMN);
                        cv.put(MailboxColumns.HIERARCHICAL_NAME,
                                parentHierarchicalName + "/" + childName);
                        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, and we didn't get an Outbox, make one.
        if (mInitialSync && !mOutboxCreated) {
            addMailboxOp(Mailbox.getSystemMailboxName(mContext, Mailbox.TYPE_OUTBOX), "0", "0",
                    OUTBOX_TYPE);
        }

        // 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 {
    }

}
