/*******************************************************************************
 *      Copyright (C) 2012 Google Inc.
 *      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.mail.ui;

import android.animation.ValueAnimator;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.LoaderManager;
import android.app.SearchManager;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.content.Loader;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.database.Cursor;
import android.database.DataSetObservable;
import android.database.DataSetObserver;
import android.database.Observable;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Parcelable;
import android.os.SystemClock;
import android.speech.RecognizerIntent;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.ActionBarDrawerToggle;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ListView;
import android.widget.Toast;

import com.android.mail.ConversationListContext;
import com.android.mail.MailLogService;
import com.android.mail.R;
import com.android.mail.analytics.Analytics;
import com.android.mail.analytics.AnalyticsTimer;
import com.android.mail.browse.ConfirmDialogFragment;
import com.android.mail.browse.ConversationCursor;
import com.android.mail.browse.ConversationCursor.ConversationOperation;
import com.android.mail.browse.ConversationItemViewModel;
import com.android.mail.browse.ConversationMessage;
import com.android.mail.browse.ConversationPagerController;
import com.android.mail.browse.SelectedConversationsActionMenu;
import com.android.mail.browse.SyncErrorDialogFragment;
import com.android.mail.browse.UndoCallback;
import com.android.mail.compose.ComposeActivity;
import com.android.mail.content.CursorCreator;
import com.android.mail.content.ObjectCursor;
import com.android.mail.content.ObjectCursorLoader;
import com.android.mail.providers.Account;
import com.android.mail.providers.Conversation;
import com.android.mail.providers.ConversationInfo;
import com.android.mail.providers.Folder;
import com.android.mail.providers.FolderWatcher;
import com.android.mail.providers.MailAppProvider;
import com.android.mail.providers.Settings;
import com.android.mail.providers.UIProvider;
import com.android.mail.providers.UIProvider.AccountCapabilities;
import com.android.mail.providers.UIProvider.AccountCursorExtraKeys;
import com.android.mail.providers.UIProvider.AutoAdvance;
import com.android.mail.providers.UIProvider.ConversationColumns;
import com.android.mail.providers.UIProvider.ConversationOperations;
import com.android.mail.providers.UIProvider.FolderCapabilities;
import com.android.mail.providers.UIProvider.FolderType;
import com.android.mail.ui.ActionableToastBar.ActionClickedListener;
import com.android.mail.utils.ContentProviderTask;
import com.android.mail.utils.DrawIdler;
import com.android.mail.utils.LogTag;
import com.android.mail.utils.LogUtils;
import com.android.mail.utils.MailObservable;
import com.android.mail.utils.NotificationActionUtils;
import com.android.mail.utils.Utils;
import com.android.mail.utils.VeiledAddressMatcher;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.TimerTask;


/**
 * This is an abstract implementation of the Activity Controller. This class
 * knows how to respond to menu items, state changes, layout changes, etc. It
 * weaves together the views and listeners, dispatching actions to the
 * respective underlying classes.
 * <p>
 * Even though this class is abstract, it should provide default implementations
 * for most, if not all the methods in the ActivityController interface. This
 * makes the task of the subclasses easier: OnePaneActivityController and
 * TwoPaneActivityController can be concise when the common functionality is in
 * AbstractActivityController.
 * </p>
 * <p>
 * In the Gmail codebase, this was called BaseActivityController
 * </p>
 */
public abstract class AbstractActivityController implements ActivityController,
        EmptyFolderDialogFragment.EmptyFolderDialogFragmentListener, View.OnClickListener {
    // Keys for serialization of various information in Bundles.
    /** Tag for {@link #mAccount} */
    private static final String SAVED_ACCOUNT = "saved-account";
    /** Tag for {@link #mFolder} */
    private static final String SAVED_FOLDER = "saved-folder";
    /** Tag for {@link #mCurrentConversation} */
    private static final String SAVED_CONVERSATION = "saved-conversation";
    /** Tag for {@link #mCheckedSet} */
    private static final String SAVED_SELECTED_SET = "saved-selected-set";
    /** Tag for {@link ActionableToastBar#getOperation()} */
    private static final String SAVED_TOAST_BAR_OP = "saved-toast-bar-op";
    /** Tag for {@link #mFolderListFolder} */
    private static final String SAVED_HIERARCHICAL_FOLDER = "saved-hierarchical-folder";
    /** Tag for {@link ConversationListContext#searchQuery} */
    private static final String SAVED_QUERY = "saved-query";
    /** Tag for {@link #mDialogAction} */
    private static final String SAVED_ACTION = "saved-action";
    /** Tag for {@link #mDialogFromSelectedSet} */
    private static final String SAVED_ACTION_FROM_SELECTED = "saved-action-from-selected";
    /** Tag for {@link #mDetachedConvUri} */
    private static final String SAVED_DETACHED_CONV_URI = "saved-detached-conv-uri";
    /** Key to store {@link #mInbox}. */
    private static final String SAVED_INBOX_KEY = "m-inbox";
    /** Key to store {@link #mConversationListScrollPositions} */
    private static final String SAVED_CONVERSATION_LIST_SCROLL_POSITIONS =
            "saved-conversation-list-scroll-positions";

    /** Tag used when loading a wait fragment */
    protected static final String TAG_WAIT = "wait-fragment";
    /** Tag used when loading a conversation list fragment. */
    public static final String TAG_CONVERSATION_LIST = "tag-conversation-list";
    /** Tag used when loading a custom fragment. */
    protected static final String TAG_CUSTOM_FRAGMENT = "tag-custom-fragment";

    /** Key to store an account in a bundle */
    private final String BUNDLE_ACCOUNT_KEY = "account";
    /** Key to store a folder in a bundle */
    private final String BUNDLE_FOLDER_KEY = "folder";
    /**
     * Key to set a flag for the ConversationCursorLoader to ignore any
     * initial load limit that may be set by the Account. Instead,
     * perform a full load instead of the full-stage load.
     */
    private final String BUNDLE_IGNORE_INITIAL_CONVERSATION_LIMIT_KEY =
            "ignore-initial-conversation-limit";

    protected Account mAccount;
    protected Folder mFolder;
    protected Folder mInbox;
    /** True when {@link #mFolder} is first shown to the user. */
    private boolean mFolderChanged = false;
    protected ActionBarController mActionBarController;
    protected final MailActivity mActivity;
    protected final Context mContext;
    private final FragmentManager mFragmentManager;
    protected final RecentFolderList mRecentFolderList;
    protected ConversationListContext mConvListContext;
    protected Conversation mCurrentConversation;
    protected MaterialSearchViewController mSearchViewController;
    /**
     * The hash of {@link #mCurrentConversation} in detached mode. 0 if we are not in detached mode.
     */
    private Uri mDetachedConvUri;

    /** A map of {@link Folder} {@link Uri} to scroll position in the conversation list. */
    private final Bundle mConversationListScrollPositions = new Bundle();

    /** A {@link android.content.BroadcastReceiver} that suppresses new e-mail notifications. */
    private SuppressNotificationReceiver mNewEmailReceiver = null;

    /** Handler for all our local runnables. */
    protected Handler mHandler = new Handler();

    /**
     * The current mode of the application. All changes in mode are initiated by
     * the activity controller. View mode changes are propagated to classes that
     * attach themselves as listeners of view mode changes.
     */
    protected final ViewMode mViewMode;
    protected ContentResolver mResolver;
    protected boolean mHaveAccountList = false;
    private AsyncRefreshTask mAsyncRefreshTask;

    private boolean mDestroyed;

    /** True if running on tablet */
    private final boolean mIsTablet;

    /**
     * Are we in a point in the Activity/Fragment lifecycle where it's safe to execute fragment
     * transactions? (including back stack manipulation)
     * <p>
     * Per docs in {@link FragmentManager#beginTransaction()}, this flag starts out true, switches
     * to false after {@link Activity#onSaveInstanceState}, and becomes true again in both onStart
     * and onResume.
     */
    private boolean mSafeToModifyFragments = true;

    private final Set<Uri> mCurrentAccountUris = Sets.newHashSet();
    protected ConversationCursor mConversationListCursor;
    private final DataSetObservable mConversationListObservable = new MailObservable("List");

    /** Runnable that checks the logging level to enable/disable the logging service. */
    private Runnable mLogServiceChecker = null;
    /** List of all accounts currently known to the controller. This is never null. */
    private Account[] mAllAccounts = new Account[0];

    private FolderWatcher mFolderWatcher;

    private boolean mIgnoreInitialConversationLimit;

    /**
     * Interface for actions that are deferred until after a load completes. This is for handling
     * user actions which affect cursors (e.g. marking messages read or unread) that happen before
     * that cursor is loaded.
     */
    private interface LoadFinishedCallback {
        void onLoadFinished();
    }

    /** The deferred actions to execute when mConversationListCursor load completes. */
    private final ArrayList<LoadFinishedCallback> mConversationListLoadFinishedCallbacks =
            new ArrayList<LoadFinishedCallback>();

    private RefreshTimerTask mConversationListRefreshTask;

    /** Listeners that are interested in changes to the current account. */
    private final DataSetObservable mAccountObservers = new MailObservable("Account");
    /** Listeners that are interested in changes to the recent folders. */
    private final DataSetObservable mRecentFolderObservers = new MailObservable("RecentFolder");
    /** Listeners that are interested in changes to the list of all accounts. */
    private final DataSetObservable mAllAccountObservers = new MailObservable("AllAccounts");
    /** Listeners that are interested in changes to the current folder. */
    private final DataSetObservable mFolderObservable = new MailObservable("CurrentFolder");
    /** Listeners that are interested in changes to the Folder or Account selection */
    private final DataSetObservable mFolderOrAccountObservers =
            new MailObservable("FolderOrAccount");

    /**
     * Selected conversations, if any.
     */
    private final ConversationCheckedSet mCheckedSet = new ConversationCheckedSet();

    private final int mFolderItemUpdateDelayMs;

    /** Keeps track of selected and unselected conversations */
    final protected ConversationPositionTracker mTracker;

    /**
     * Action menu associated with the selected set.
     */
    SelectedConversationsActionMenu mCabActionMenu;

    /** The compose button floating over the conversation/search lists */
    protected View mFloatingComposeButton;
    protected ActionableToastBar mToastBar;
    protected ConversationPagerController mPagerController;

    // This is split out from the general loader dispatcher because its loader doesn't return a
    // basic Cursor
    /** Handles loader callbacks to create a convesation cursor. */
    private final ConversationListLoaderCallbacks mListCursorCallbacks =
            new ConversationListLoaderCallbacks();

    /** Object that listens to all LoaderCallbacks that result in {@link Folder} creation. */
    private final FolderLoads mFolderCallbacks = new FolderLoads();
    /** Object that listens to all LoaderCallbacks that result in {@link Account} creation. */
    private final AccountLoads mAccountCallbacks = new AccountLoads();

    /**
     * Matched addresses that must be shielded from users because they are temporary. Even though
     * this is instantiated from settings, this matcher is valid for all accounts, and is expected
     * to live past the life of an account.
     */
    private final VeiledAddressMatcher mVeiledMatcher;

    protected static final String LOG_TAG = LogTag.getLogTag();

    // Loader constants: Accounts
    /**
     * The list of accounts. This loader is started early in the application life-cycle since
     * the list of accounts is central to all other data the application needs: unread counts for
     * folders, critical UI settings like show/hide checkboxes, ...
     * The loader is started when the application is created: both in
     * {@link #onCreate(Bundle)} and in {@link #onActivityResult(int, int, Intent)}. It is never
     * destroyed since the cursor is needed through the life of the application. When the list of
     * accounts changes, we notify {@link #mAllAccountObservers}.
     */
    private static final int LOADER_ACCOUNT_CURSOR = 0;

    /**
     * The current account. This loader is started when we have an account. The mail application
     * <b>needs</b> a valid account to function. As soon as we set {@link #mAccount},
     * we start a loader to observe for changes on the current account.
     * The loader is always restarted when an account is set in {@link #setAccount(Account)}.
     * When the current account object changes, we notify {@link #mAccountObservers}.
     * A possible performance improvement would be to listen purely on
     * {@link #LOADER_ACCOUNT_CURSOR}. The current account is guaranteed to be in the list,
     * and would avoid two updates when a single setting on the current account changes.
     */
    private static final int LOADER_ACCOUNT_UPDATE_CURSOR = 1;

    // Loader constants: Conversations

    /** The conversation cursor over the current conversation list. This loader provides
     * a cursor over conversation entries from a folder to display a conversation
     * list.
     * This loader is started when the user switches folders (in {@link #updateFolder(Folder)},
     * or when the controller is told that a folder/account change is imminent
     * (in {@link #preloadConvList(Account, Folder)}. The loader is maintained for the life of
     * the current folder. When the user switches folders, the old loader is destroyed and a new
     * one is created.
     *
     * When the conversation list changes, we notify {@link #mConversationListObservable}.
     */
    private static final int LOADER_CONVERSATION_LIST = 10;

    // Loader constants: misc
    /**
     * The loader that determines whether the Warm welcome tour should be displayed for the user.
     */
    public static final int LOADER_WELCOME_TOUR = 20;

    /**
     * The load which loads accounts for the welcome tour.
     */
    public static final int LOADER_WELCOME_TOUR_ACCOUNTS = 21;

    // Loader constants: Folders

    /** The current folder. This loader watches for updates to the current folder in a manner
     * analogous to the {@link #LOADER_ACCOUNT_UPDATE_CURSOR}. Updates to the current folder
     * might be due to server-side changes (unread count), or local changes (sync window or sync
     * status change).
     * The change of current folder calls {@link #updateFolder(Folder)}.
     * This is responsible for restarting a loader using the URI of the provided folder. When the
     * loader returns, the current folder is updated and consumers, if any, are notified.
     * When the current folder changes, we notify {@link #mFolderObservable}
     */
    private static final int LOADER_FOLDER_CURSOR = 30;

    /**
     * The list of recent folders. Recent folders are shown in the DrawerFragment. The recent
     * folders are tied to the current account being viewed. When the account is changed,
     * we restart this loader to retrieve the recent accounts. Recents are pre-populated for
     * phones historically, when they were displayed in the spinner. On the tablet,
     * they showed in the {@link FolderListFragment} and were not-populated.  The code to
     * pre-populate the recents is somewhat convoluted: when the loader returns a short list of
     * recent folders, it issues an update on the Recent Folder URI. The underlying provider then
     * does the appropriate thing to populate recent folders, and notify of a change on the cursor.
     * Recent folders are needed for the life of the current account.
     * When the recent folders change, we notify {@link #mRecentFolderObservers}.
     */
    private static final int LOADER_RECENT_FOLDERS = 31;
    /**
     * The primary inbox for the current account. The mechanism to load the default inbox for the
     * current account is (sadly) different from loading other folders. The method
     * {@link #loadAccountInbox()} is called, and it restarts this loader. When the loader returns
     * a valid cursor, we create a folder, call {@link #onFolderChanged{Folder)} eventually
     * calling {@link #updateFolder(Folder)} which starts a loader {@link #LOADER_FOLDER_CURSOR}
     * over the current folder.
     * When we have a valid cursor, we destroy this loader, This convoluted flow is historical.
     */
    private static final int LOADER_ACCOUNT_INBOX = 32;

    /**
     * The fake folder of search results for a term. When we search for a term,
     * a new activity is created with {@link Intent#ACTION_SEARCH}. For this new activity,
     * we start a loader which returns conversations that match the user-provided query.
     * We destroy the loader when we obtain a valid cursor since subsequent searches will create
     * a new activity.
     */
    private static final int LOADER_SEARCH = 33;
    /**
     * The initial folder at app start. When the application is launched from an intent that
     * specifies the initial folder (notifications/widgets/shortcuts),
     * then we extract the folder URI from the intent, but we cannot trust the folder object. Since
     * shortcuts and widgets persist past application update, they might have incorrect
     * information encoded in them. So, to obtain a {@link Folder} object from a {@link Uri},
     * we need to start another loader. Upon obtaining a valid cursor, the loader is destroyed.
     * An additional complication arises if we have to view a specific conversation within this
     * folder. This is the case when launching the app from a single conversation notification
     * or tapping on a specific conversation in the widget. In these cases, the conversation is
     * saved in {@link #mConversationToShow} and is retrieved when the loader returns.
     */
    public static final int LOADER_FIRST_FOLDER = 34;

    /**
     * Guaranteed to be the last loader ID used by the activity. Loaders are owned by Activity or
     * fragments, and within an activity, loader IDs need to be unique. A hack to ensure that the
     * {@link FolderWatcher} can create its folder loaders without clashing with the IDs of those
     * of the {@link AbstractActivityController}. Currently, the {@link FolderWatcher} is the only
     * other class that uses this activity's LoaderManager. If another class needs activity-level
     * loaders, consider consolidating the loaders in a central location: a UI-less fragment
     * perhaps.
     */
    public static final int LAST_LOADER_ID = 35;

    /**
     * Guaranteed to be the last loader ID used by the Fragment. Loaders are owned by Activity or
     * fragments, and within an activity, loader IDs need to be unique. Currently,
     * SectionedInboxTeaserView is the only class that uses the
     * {@link ConversationListFragment}'s LoaderManager.
     */
    public static final int LAST_FRAGMENT_LOADER_ID = 1000;

    /** Code returned after an account has been added. */
    private static final int ADD_ACCOUNT_REQUEST_CODE = 1;
    /** Code returned when the user has to enter the new password on an existing account. */
    private static final int REAUTHENTICATE_REQUEST_CODE = 2;
    /** Code returned when the previous activity needs to navigate to a different folder
     *  or account */
    private static final int CHANGE_NAVIGATION_REQUEST_CODE = 3;

    /** Code returned from voice search intent */
    public static final int VOICE_SEARCH_REQUEST_CODE = 4;

    public static final String EXTRA_FOLDER = "extra-folder";
    public static final String EXTRA_ACCOUNT = "extra-account";

    /** The pending destructive action to be carried out before swapping the conversation cursor.*/
    private DestructiveAction mPendingDestruction;
    protected AsyncRefreshTask mFolderSyncTask;
    private Folder mFolderListFolder;
    private final int mShowUndoBarDelay;
    private boolean mRecentsDataUpdated;
    /** A wait fragment we added, if any. */
    private WaitFragment mWaitFragment;
    /** True if we have results from a search query */
    private boolean mHaveSearchResults = false;
    /** If a confirmation dialog is being show, the listener for the positive action. */
    private OnClickListener mDialogListener;
    /**
     * If a confirmation dialog is being show, the resource of the action: R.id.delete, etc.  This
     * is used to create a new {@link #mDialogListener} on orientation changes.
     */
    private int mDialogAction = -1;
    /**
     * If a confirmation dialog is being shown, this is true if the dialog acts on the selected set
     * and false if it acts on the currently selected conversation
     */
    private boolean mDialogFromSelectedSet;

    /** Which conversation to show, if started from widget/notification. */
    private Conversation mConversationToShow = null;

    /**
     * A temporary reference to the pending destructive action that was deferred due to an
     * auto-advance transition in progress.
     * <p>
     * In detail: when auto-advance triggers a mode change, we must wait until the transition
     * completes before executing the destructive action to ensure a smooth mode change transition.
     * This member variable houses the pending destructive action work to be run upon completion.
     */
    private Runnable mAutoAdvanceOp = null;

    protected DrawerLayout mDrawerContainer;
    protected View mDrawerPullout;
    protected ActionBarDrawerToggle mDrawerToggle;

    protected ListView mListViewForAnimating;
    protected boolean mHasNewAccountOrFolder;
    private boolean mConversationListLoadFinishedIgnored;
    private final MailDrawerListener mDrawerListener = new MailDrawerListener();
    private boolean mHideMenuItems;

    private final DrawIdler mDrawIdler = new DrawIdler();

    public static final String SYNC_ERROR_DIALOG_FRAGMENT_TAG = "SyncErrorDialogFragment";

    private final DataSetObserver mUndoNotificationObserver = new DataSetObserver() {
        @Override
        public void onChanged() {
            super.onChanged();

            if (mConversationListCursor != null) {
                mConversationListCursor.handleNotificationActions();
            }
        }
    };

    private final HomeButtonListener mHomeButtonListener = new HomeButtonListener();

    public AbstractActivityController(MailActivity activity, ViewMode viewMode) {
        mActivity = activity;
        mFragmentManager = mActivity.getFragmentManager();
        mViewMode = viewMode;
        mContext = activity.getApplicationContext();
        mRecentFolderList = new RecentFolderList(mContext);
        mTracker = new ConversationPositionTracker(this);
        // Allow the fragment to observe changes to its own selection set. No other object is
        // aware of the selected set.
        mCheckedSet.addObserver(this);

        final Resources r = mContext.getResources();
        mFolderItemUpdateDelayMs = r.getInteger(R.integer.folder_item_refresh_delay_ms);
        mShowUndoBarDelay = r.getInteger(R.integer.show_undo_bar_delay_ms);
        mVeiledMatcher = VeiledAddressMatcher.newInstance(activity.getResources());
        mIsTablet = Utils.useTabletUI(r);
        mConversationListLoadFinishedIgnored = false;
    }

    public Account getCurrentAccount() {
        return mAccount;
    }

    public ConversationListContext getCurrentListContext() {
        return mConvListContext;
    }

    @Override
    public final ConversationCursor getConversationListCursor() {
        return mConversationListCursor;
    }

    /**
     * Check if the fragment is attached to an activity and has a root view.
     * @param in fragment to be checked
     * @return true if the fragment is valid, false otherwise
     */
    private static boolean isValidFragment(Fragment in) {
        return !(in == null || in.getActivity() == null || in.getView() == null);
    }

    /**
     * Get the conversation list fragment for this activity. If the conversation list fragment is
     * not attached, this method returns null.
     *
     * Caution! This method returns the {@link ConversationListFragment} after the fragment has been
     * added, <b>and</b> after the {@link FragmentManager} has run through its queue to add the
     * fragment. There is a non-trivial amount of time after the fragment is instantiated and before
     * this call returns a non-null value, depending on the {@link FragmentManager}. If you
     * need the fragment immediately after adding it, consider making the fragment an observer of
     * the controller and perform the task immediately on {@link Fragment#onActivityCreated(Bundle)}
     */
    protected ConversationListFragment getConversationListFragment() {
        final Fragment fragment = mFragmentManager.findFragmentByTag(TAG_CONVERSATION_LIST);
        if (isValidFragment(fragment)) {
            return (ConversationListFragment) fragment;
        }
        return null;
    }

    /**
     * Returns the folder list fragment attached with this activity. If no such fragment is attached
     * this method returns null.
     *
     * Caution! This method returns the {@link FolderListFragment} after the fragment has been
     * added, <b>and</b> after the {@link FragmentManager} has run through its queue to add the
     * fragment. There is a non-trivial amount of time after the fragment is instantiated and before
     * this call returns a non-null value, depending on the {@link FragmentManager}. If you
     * need the fragment immediately after adding it, consider making the fragment an observer of
     * the controller and perform the task immediately on {@link Fragment#onActivityCreated(Bundle)}
     */
    protected FolderListFragment getFolderListFragment() {
        final String drawerPulloutTag = mActivity.getString(R.string.drawer_pullout_tag);
        final Fragment fragment = mFragmentManager.findFragmentByTag(drawerPulloutTag);
        if (isValidFragment(fragment)) {
            return (FolderListFragment) fragment;
        }
        return null;
    }

    /**
     * Initialize the action bar. This is not visible to OnePaneController and
     * TwoPaneController so they cannot override this behavior.
     */
    private void initializeActionBar() {
        final ActionBar actionBar = mActivity.getSupportActionBar();
        if (actionBar == null) {
            return;
        }

        mActionBarController = new ActionBarController(mContext);
        mActionBarController.initialize(mActivity, this, actionBar);
        actionBar.setShowHideAnimationEnabled(false);

        // init the action bar to allow the 'up' affordance.
        // any configurations that disallow 'up' should do that later.
        mActionBarController.setBackButton();
    }

    /**
     * Attach the action bar to the activity.
     */
    private void attachActionBar() {
        final ActionBar actionBar = mActivity.getSupportActionBar();
        if (actionBar != null) {
            // Show a title
            final int mask = ActionBar.DISPLAY_SHOW_TITLE | ActionBar.DISPLAY_SHOW_HOME;
            actionBar.setDisplayOptions(mask, mask);
            mActionBarController.setViewModeController(mViewMode);
        }
    }

    /**
     * Returns whether the conversation list fragment is visible or not.
     * Different layouts will have their own notion on the visibility of
     * fragments, so this method needs to be overriden.
     *
     */
    protected abstract boolean isConversationListVisible();

    /**
     * If required, starts wait mode for the current account.
     */
    final void perhapsEnterWaitMode() {
        // If the account is not initialized, then show the wait fragment, since nothing can be
        // shown.
        if (mAccount.isAccountInitializationRequired()) {
            showWaitForInitialization();
            return;
        }

        final boolean inWaitingMode = inWaitMode();
        final boolean isSyncRequired = mAccount.isAccountSyncRequired();
        if (isSyncRequired) {
            if (inWaitingMode) {
                // Update the WaitFragment's account object
                updateWaitMode();
            } else {
                // Transition to waiting mode
                showWaitForInitialization();
            }
        } else if (inWaitingMode) {
            // Dismiss waiting mode
            hideWaitForInitialization();
        }
    }

    @Override
    public void switchToDefaultInboxOrChangeAccount(Account account) {
        LogUtils.d(LOG_TAG, "AAC.switchToDefaultAccount(%s)", account);
        if (mViewMode.isSearchMode()) {
            // We are in an activity on top of the main navigation activity.
            // We need to return to it with a result code that indicates it should navigate to
            // a different folder.
            final Intent intent = new Intent();
            intent.putExtra(AbstractActivityController.EXTRA_ACCOUNT, account);
            mActivity.setResult(Activity.RESULT_OK, intent);
            mActivity.finish();
            return;
        }
        final boolean firstLoad = mAccount == null;
        final boolean switchToDefaultInbox = !firstLoad && account.uri.equals(mAccount.uri);
        // If the active account has been clicked in the drawer, go to default inbox
        if (switchToDefaultInbox) {
            loadAccountInbox();
            return;
        }
        changeAccount(account);
    }

    public void changeAccount(Account account) {
        LogUtils.d(LOG_TAG, "AAC.changeAccount(%s)", account);
        // Is the account or account settings different from the existing account?
        final boolean firstLoad = mAccount == null;
        final boolean accountChanged = firstLoad || !account.uri.equals(mAccount.uri);

        // If nothing has changed, return early without wasting any more time.
        if (!accountChanged && !account.settingsDiffer(mAccount)) {
            return;
        }
        // We also don't want to do anything if the new account is null
        if (account == null) {
            LogUtils.e(LOG_TAG, "AAC.changeAccount(null) called.");
            return;
        }
        final String emailAddress = account.getEmailAddress();
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                MailActivity.setNfcMessage(emailAddress);
            }
        });
        if (accountChanged) {
            commitDestructiveActions(false);
        }

        // Change the account here
        setAccount(account);
        // And carry out associated actions.
        cancelRefreshTask();
        if (accountChanged) {
            loadAccountInbox();
        }
        // Check if we need to force setting up an account before proceeding.
        if (mAccount != null && !Uri.EMPTY.equals(mAccount.settings.setupIntentUri)) {
            // Launch the intent!
            final Intent intent = new Intent(Intent.ACTION_EDIT);

            intent.setPackage(mContext.getPackageName());
            intent.setData(mAccount.settings.setupIntentUri);

            mActivity.startActivity(intent);
        }
    }

    /**
     * Adds a listener interested in change in the current account. If a class is storing a
     * reference to the current account, it should listen on changes, so it can receive updates to
     * settings. Must happen in the UI thread.
     */
    @Override
    public void registerAccountObserver(DataSetObserver obs) {
        mAccountObservers.registerObserver(obs);
    }

    /**
     * Removes a listener from receiving current account changes.
     * Must happen in the UI thread.
     */
    @Override
    public void unregisterAccountObserver(DataSetObserver obs) {
        mAccountObservers.unregisterObserver(obs);
    }

    @Override
    public void registerAllAccountObserver(DataSetObserver observer) {
        mAllAccountObservers.registerObserver(observer);
    }

    @Override
    public void unregisterAllAccountObserver(DataSetObserver observer) {
        mAllAccountObservers.unregisterObserver(observer);
    }

    @Override
    public Account[] getAllAccounts() {
        return mAllAccounts;
    }

    @Override
    public Account getAccount() {
        return mAccount;
    }

    @Override
    public void registerFolderOrAccountChangedObserver(final DataSetObserver observer) {
        mFolderOrAccountObservers.registerObserver(observer);
    }

    @Override
    public void unregisterFolderOrAccountChangedObserver(final DataSetObserver observer) {
        mFolderOrAccountObservers.unregisterObserver(observer);
    }

    /**
     * If the drawer is open, the function locks the drawer to the closed, thereby sliding in
     * the drawer to the left edge, disabling events, and refreshing it once it's either closed
     * or put in an idle state.
     */
    @Override
    public void closeDrawer(final boolean hasNewFolderOrAccount, Account nextAccount,
            Folder nextFolder) {
        if (!isDrawerEnabled()) {
            if (hasNewFolderOrAccount) {
                mFolderOrAccountObservers.notifyChanged();
            }
            return;
        }
        // If there are no new folders or accounts to switch to, just close the drawer
        if (!hasNewFolderOrAccount) {
            mDrawerContainer.closeDrawers();
            return;
        }
        // Otherwise, start preloading the conversation list for the new folder.
        if (nextFolder != null) {
            preloadConvList(nextAccount, nextFolder);
        }
        // Remember if the conversation list view is animating
        final ConversationListFragment conversationList = getConversationListFragment();
        if (conversationList != null) {
            mListViewForAnimating = conversationList.getListView();
        } else {
            // There is no conversation list to animate, so just set it to null
            mListViewForAnimating = null;
        }

        if (mDrawerContainer.isDrawerOpen(mDrawerPullout)) {
            // Lets the drawer listener update the drawer contents and notify the FolderListFragment
            mHasNewAccountOrFolder = true;
            mDrawerContainer.setDrawerLockMode(DrawerLayout.LOCK_MODE_LOCKED_CLOSED);
        } else {
            // Drawer is already closed, notify observers that is the case.
            if (hasNewFolderOrAccount) {
                mFolderOrAccountObservers.notifyChanged();
            }
        }
    }

    /**
     * Load the conversation list early for the given folder. This happens when some UI element
     * (usually the drawer) instructs the controller that an account change or folder change is
     * imminent. While the UI element is animating, the controller can preload the conversation
     * list for the default inbox of the account provided here or to the folder provided here.
     *
     * @param nextAccount The account which the app will switch to shortly, possibly null.
     * @param nextFolder The folder which the app will switch to shortly, possibly null.
     */
    protected void preloadConvList(Account nextAccount, Folder nextFolder) {
        // Fire off the conversation list loader for this account already with a fake
        // listener.
        final Bundle args = new Bundle(2);
        if (nextAccount != null) {
            args.putParcelable(BUNDLE_ACCOUNT_KEY, nextAccount);
        } else {
            args.putParcelable(BUNDLE_ACCOUNT_KEY, mAccount);
        }
        if (nextFolder != null) {
            args.putParcelable(BUNDLE_FOLDER_KEY, nextFolder);
        } else {
            LogUtils.e(LOG_TAG, new Error(), "AAC.preloadConvList(): Got an empty folder");
        }
        mFolder = null;
        final LoaderManager lm = mActivity.getLoaderManager();
        lm.destroyLoader(LOADER_CONVERSATION_LIST);
        lm.initLoader(LOADER_CONVERSATION_LIST, args, mListCursorCallbacks);
    }

    /**
     * Initiates the async request to create a fake search folder, which returns conversations that
     * match the query term provided by the user. Returns immediately.
     * @param intent Intent that the app was started with. This intent contains the search query.
     */
    private void fetchSearchFolder(Intent intent) {
        final Bundle args = new Bundle(1);
        args.putString(ConversationListContext.EXTRA_SEARCH_QUERY, intent
                .getStringExtra(ConversationListContext.EXTRA_SEARCH_QUERY));
        mActivity.getLoaderManager().restartLoader(LOADER_SEARCH, args, mFolderCallbacks);
    }

    protected void onFolderChanged(Folder folder, final boolean force) {
        if (isDrawerEnabled()) {
            /** If the folder doesn't exist, or its parent URI is empty,
             * this is not a child folder */
            final boolean isTopLevel = Folder.isRoot(folder);
            final int mode = mViewMode.getMode();
            mDrawerToggle.setDrawerIndicatorEnabled(
                    getShouldShowDrawerIndicator(mode, isTopLevel));
            mDrawerContainer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);

            mDrawerContainer.closeDrawers();
        }

        if (mFolder == null || !mFolder.equals(folder)) {
            // We are actually changing the folder, so exit cab mode
            exitCabMode();
        }

        final String query;
        if (folder != null && folder.isType(FolderType.SEARCH)) {
            query = mConvListContext.searchQuery;
        } else {
            query = null;
        }

        changeFolder(folder, query, force);
    }

    /**
     * Sets the folder state without changing view mode and without creating a list fragment, if
     * possible.
     * @param folder the folder whose list of conversations are to be shown
     * @param query the query string for a list of conversations matching a search
     */
    private void setListContext(Folder folder, String query) {
        updateFolder(folder);
        if (query != null) {
            mConvListContext = ConversationListContext.forSearchQuery(mAccount, mFolder, query);
        } else {
            mConvListContext = ConversationListContext.forFolder(mAccount, mFolder);
        }
        cancelRefreshTask();
    }

    /**
     * Changes the folder to the value provided here. This causes the view mode to change.
     * @param folder the folder to change to
     * @param query if non-null, this represents the search string that the folder represents.
     * @param force <code>true</code> to force a folder change, <code>false</code> to disallow
     *          changing to the current folder
     */
    private void changeFolder(Folder folder, String query, final boolean force) {
        if (!Objects.equal(mFolder, folder)) {
            commitDestructiveActions(false);
        }
        if (folder != null && (!folder.equals(mFolder) || force)
                || (mViewMode.getMode() != ViewMode.CONVERSATION_LIST)) {
            setListContext(folder, query);
            showConversationList(mConvListContext);
            // Touch the current folder: it is different, and it has been accessed.
            mRecentFolderList.touchFolder(mFolder, mAccount);
        }
        resetActionBarIcon();
    }

    @Override
    public void onFolderSelected(Folder folder) {
        onFolderChanged(folder, false /* force */);
    }

    /**
     * Adds a listener interested in change in the recent folders. If a class is storing a
     * reference to the recent folders, it should listen on changes, so it can receive updates.
     * Must happen in the UI thread.
     */
    @Override
    public void registerRecentFolderObserver(DataSetObserver obs) {
        mRecentFolderObservers.registerObserver(obs);
    }

    /**
     * Removes a listener from receiving recent folder changes.
     * Must happen in the UI thread.
     */
    @Override
    public void unregisterRecentFolderObserver(DataSetObserver obs) {
        mRecentFolderObservers.unregisterObserver(obs);
    }

    @Override
    public RecentFolderList getRecentFolders() {
        return mRecentFolderList;
    }

    /**
     * Load the default inbox associated with the current account.
     */
    protected void loadAccountInbox() {
        boolean handled = false;
        if (mFolderWatcher != null) {
            final Folder inbox = mFolderWatcher.getDefaultInbox(mAccount);
            if (inbox != null) {
                onFolderChanged(inbox, false /* force */);
                handled = true;
            }
        }
        if (!handled) {
            LogUtils.d(LOG_TAG, "Starting a LOADER_ACCOUNT_INBOX for %s", mAccount);
            restartOptionalLoader(LOADER_ACCOUNT_INBOX, mFolderCallbacks, Bundle.EMPTY);
        }
        final int mode = mViewMode.getMode();
        if (mode == ViewMode.UNKNOWN || mode == ViewMode.WAITING_FOR_ACCOUNT_INITIALIZATION) {
            mViewMode.enterConversationListMode();
        }
    }

    @Override
    public void setFolderWatcher(FolderWatcher watcher) {
        mFolderWatcher = watcher;
    }

    /**
     * Marks the {@link #mFolderChanged} value if the newFolder is different from the existing
     * {@link #mFolder}. This should be called immediately <b>before</b> assigning newFolder to
     * mFolder.
     * @param newFolder the new folder we are switching to.
     */
    private void setHasFolderChanged(final Folder newFolder) {
        // We should never try to assign a null folder. But in the rare event that we do, we should
        // only set the bit when we have a valid folder, and null is not valid.
        if (newFolder == null) {
            return;
        }
        // If the previous folder was null, or if the two folders represent different data, then we
        // consider that the folder has changed.
        if (mFolder == null || !newFolder.equals(mFolder)) {
            mFolderChanged = true;
        }
    }

    /**
     * Sets the current folder if it is different from the object provided here. This method does
     * NOT notify the folder observers that a change has happened. Observers are notified when we
     * get an updated folder from the loaders, which will happen as a consequence of this method
     * (since this method starts/restarts the loaders).
     * @param folder The folder to assign
     */
    private void updateFolder(Folder folder) {
        if (folder == null || !folder.isInitialized()) {
            LogUtils.e(LOG_TAG, new Error(), "AAC.setFolder(%s): Bad input", folder);
            return;
        }
        if (folder.equals(mFolder)) {
            LogUtils.d(LOG_TAG, "AAC.setFolder(%s): Input matches mFolder", folder);
            return;
        }
        final boolean wasNull = mFolder == null;
        LogUtils.d(LOG_TAG, "AbstractActivityController.setFolder(%s)", folder.name);
        final LoaderManager lm = mActivity.getLoaderManager();
        // updateFolder is called from AAC.onLoadFinished() on folder changes.  We need to
        // ensure that the folder is different from the previous folder before marking the
        // folder changed.
        setHasFolderChanged(folder);
        mFolder = folder;

        // We do not need to notify folder observers yet. Instead we start the loaders and
        // when the load finishes, we will get an updated folder. Then, we notify the
        // folderObservers in onLoadFinished.
        mActionBarController.setFolder(mFolder);

        // Only when we switch from one folder to another do we want to restart the
        // folder and conversation list loaders (to trigger onCreateLoader).
        // The first time this runs when the activity is [re-]initialized, we want to re-use the
        // previous loader's instance and data upon configuration change (e.g. rotation).
        // If there was not already an instance of the loader, init it.
        if (lm.getLoader(LOADER_FOLDER_CURSOR) == null) {
            lm.initLoader(LOADER_FOLDER_CURSOR, Bundle.EMPTY, mFolderCallbacks);
        } else {
            lm.restartLoader(LOADER_FOLDER_CURSOR, Bundle.EMPTY, mFolderCallbacks);
        }
        if (!wasNull && lm.getLoader(LOADER_CONVERSATION_LIST) != null) {
            // If there was an existing folder AND we have changed
            // folders, we want to restart the loader to get the information
            // for the newly selected folder
            lm.destroyLoader(LOADER_CONVERSATION_LIST);
        }
        final Bundle args = new Bundle(2);
        args.putParcelable(BUNDLE_ACCOUNT_KEY, mAccount);
        args.putParcelable(BUNDLE_FOLDER_KEY, mFolder);
        args.putBoolean(BUNDLE_IGNORE_INITIAL_CONVERSATION_LIMIT_KEY,
                mIgnoreInitialConversationLimit);
        mIgnoreInitialConversationLimit = false;
        lm.initLoader(LOADER_CONVERSATION_LIST, args, mListCursorCallbacks);
    }

    @Override
    public Folder getFolder() {
        return mFolder;
    }

    @Override
    public Folder getHierarchyFolder() {
        return mFolderListFolder;
    }

    /**
     * Set the folder currently selected in the folder selection hierarchy fragments.
     */
    protected void setHierarchyFolder(Folder folder) {
        mFolderListFolder = folder;
    }

    /**
     * The mail activity calls other activities for two specific reasons:
     * <ul>
     *     <li>To add an account. And receives the result {@link #ADD_ACCOUNT_REQUEST_CODE}</li>
     *     <li>To update the password on a current account. The result {@link
     *     #REAUTHENTICATE_REQUEST_CODE} is received.</li>
     * </ul>
     * @param requestCode
     * @param resultCode
     * @param data
     */
    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        switch (requestCode) {
            case ADD_ACCOUNT_REQUEST_CODE:
                // We were waiting for the user to create an account
                if (resultCode == Activity.RESULT_OK) {
                    // restart the loader to get the updated list of accounts
                    mActivity.getLoaderManager().initLoader(LOADER_ACCOUNT_CURSOR, Bundle.EMPTY,
                            mAccountCallbacks);
                } else {
                    // The user failed to create an account, just exit the app
                    mActivity.finish();
                }
                break;
            case REAUTHENTICATE_REQUEST_CODE:
                if (resultCode == Activity.RESULT_OK) {
                    // The user successfully authenticated, attempt to refresh the list
                    final Uri refreshUri = mFolder != null ? mFolder.refreshUri : null;
                    if (refreshUri != null) {
                        startAsyncRefreshTask(refreshUri);
                    }
                }
                break;
            case CHANGE_NAVIGATION_REQUEST_CODE:
                if (ViewMode.isSearchMode(mViewMode.getMode())) {
                    mActivity.setResult(resultCode, data);
                    mActivity.finish();
                } else if (resultCode == Activity.RESULT_OK && data != null) {
                    // We have have received a result that indicates we need to navigate to a
                    // different folder or account. This happens if someone navigates using the
                    // drawer on the search results activity.
                    final Folder folder = data.getParcelableExtra(EXTRA_FOLDER);
                    final Account account = data.getParcelableExtra(EXTRA_ACCOUNT);
                    if (folder != null) {
                        onFolderSelected(folder);
                        mViewMode.enterConversationListMode();
                    } else if (account != null) {
                        switchToDefaultInboxOrChangeAccount(account);
                        mViewMode.enterConversationListMode();
                    }
                }
                break;
            case VOICE_SEARCH_REQUEST_CODE:
                if (resultCode == Activity.RESULT_OK) {
                    final ArrayList<String> matches = data.getStringArrayListExtra(
                            RecognizerIntent.EXTRA_RESULTS);
                    if (!matches.isEmpty()) {
                        // not sure how dependable the API is, but it's all we have.
                        // take the top choice.
                        mSearchViewController.onSearchPerformed(matches.get(0));
                    }
                }
                break;
        }
    }

    /**
     * Inform the conversation cursor that there has been a visibility change.
     * @param visible true if the conversation list is visible, false otherwise.
     */
    protected synchronized void informCursorVisiblity(boolean visible) {
        if (mConversationListCursor != null) {
            Utils.setConversationCursorVisibility(mConversationListCursor, visible, mFolderChanged);
            // We have informed the cursor. Subsequent visibility changes should not tell it that
            // the folder has changed.
            mFolderChanged = false;
        }
    }

    @Override
    public void onConversationListVisibilityChanged(boolean visible) {
        mFloatingComposeButton.setVisibility(
                !ViewMode.isSearchMode(mViewMode.getMode()) && visible ? View.VISIBLE : View.GONE);

        informCursorVisiblity(visible);
        commitAutoAdvanceOperation();

        // Notify special views
        final ConversationListFragment convListFragment = getConversationListFragment();
        if (convListFragment != null && convListFragment.getAnimatedAdapter() != null) {
            convListFragment.getAnimatedAdapter().onConversationListVisibilityChanged(visible);
        }
    }

    /**
     * Called when a conversation is visible. Child classes must call the super class implementation
     * before performing local computation.
     */
    @Override
    public void onConversationVisibilityChanged(boolean visible) {
        commitAutoAdvanceOperation();
    }

    /**
     * Commits any pending destructive action that was earlier deferred by an auto-advance
     * mode-change transition.
     */
    private void commitAutoAdvanceOperation() {
        if (mAutoAdvanceOp != null) {
            mAutoAdvanceOp.run();
            mAutoAdvanceOp = null;
        }
    }

    /**
     * Initialize development time logging. This can potentially log a lot of PII, and we don't want
     * to turn it on for shipped versions.
     */
    private void initializeDevLoggingService() {
        if (!MailLogService.DEBUG_ENABLED) {
            return;
        }
        // Check every 5 minutes.
        final int WAIT_TIME = 5 * 60 * 1000;
        // Start a runnable that periodically checks the log level and starts/stops the service.
        mLogServiceChecker = new Runnable() {
            /** True if currently logging. */
            private boolean mCurrentlyLogging = false;

            /**
             * If the logging level has been changed since the previous run, start or stop the
             * service.
             */
            private void startOrStopService() {
                // If the log level is already high, start the service.
                final Intent i = new Intent(mContext, MailLogService.class);
                final boolean loggingEnabled = MailLogService.isLoggingLevelHighEnough();
                if (mCurrentlyLogging == loggingEnabled) {
                    // No change since previous run, just return;
                    return;
                }
                if (loggingEnabled) {
                    LogUtils.e(LOG_TAG, "Starting MailLogService");
                    mContext.startService(i);
                } else {
                    LogUtils.e(LOG_TAG, "Stopping MailLogService");
                    mContext.stopService(i);
                }
                mCurrentlyLogging = loggingEnabled;
            }

            @Override
            public void run() {
                startOrStopService();
                mHandler.postDelayed(this, WAIT_TIME);
            }
        };
        // Start the runnable right away.
        mHandler.post(mLogServiceChecker);
    }

    /**
     * The application can be started from the following entry points:
     * <ul>
     *     <li>Launcher: you tap on the Gmail icon in the launcher. This is what most users think of
     *         as “Starting the app”.</li>
     *     <li>Shortcut: Users can make a shortcut to take them directly to a label.</li>
     *     <li>Widget: Shows the contents of a synced label, and allows:
     *     <ul>
     *         <li>Viewing the list (tapping on the title)</li>
     *         <li>Composing a new message (tapping on the new message icon in the title. This
     *         launches the {@link ComposeActivity}.
     *         </li>
     *         <li>Viewing a single message (tapping on a list element)</li>
     *     </ul>
     *
     *     </li>
     *     <li>Tapping on a notification:
     *     <ul>
     *         <li>Shows message list if more than one message</li>
     *         <li>Shows the conversation if the notification is for a single message</li>
     *     </ul>
     *     </li>
     *     <li>...and most importantly, the activity life cycle can tear down the application and
     *     restart it:
     *     <ul>
     *         <li>Rotate the application: it is destroyed and recreated.</li>
     *         <li>Navigate away, and return from recent applications.</li>
     *     </ul>
     *     </li>
     *     <li>Add a new account: fires off an intent to add an account,
     *     and returns in {@link #onActivityResult(int, int, android.content.Intent)} .</li>
     *     <li>Re-authenticate your account: again returns in onActivityResult().</li>
     *     <li>Composing can happen from many entry points: third party applications fire off an
     *     intent to compose email, and launch directly into the {@link ComposeActivity}
     *     .</li>
     * </ul>
     * {@inheritDoc}
     */
    @Override
    public boolean onCreate(Bundle savedState) {
        initializeActionBar();
        initializeDevLoggingService();
        // Allow shortcut keys to function for the ActionBar and menus.
        mActivity.setDefaultKeyMode(Activity.DEFAULT_KEYS_SHORTCUT);
        mResolver = mActivity.getContentResolver();
        mNewEmailReceiver = new SuppressNotificationReceiver();
        mRecentFolderList.initialize(mActivity);
        mVeiledMatcher.initialize(this);

        mFloatingComposeButton = mActivity.findViewById(R.id.compose_button);
        mFloatingComposeButton.setOnClickListener(this);

        if (isDrawerEnabled()) {
            mDrawerToggle = new ActionBarDrawerToggle(mActivity, mDrawerContainer,
                    R.string.drawer_open, R.string.drawer_close);
            mDrawerContainer.setDrawerListener(mDrawerListener);
            mDrawerContainer.setDrawerShadow(
                    mContext.getResources().getDrawable(R.drawable.drawer_shadow), Gravity.START);

            mDrawerToggle.setDrawerIndicatorEnabled(isDrawerEnabled());
        } else {
            final ActionBar ab = mActivity.getSupportActionBar();
            ab.setHomeAsUpIndicator(R.drawable.ic_drawer);
            ab.setHomeActionContentDescription(R.string.drawer_open);
            ab.setDisplayHomeAsUpEnabled(true);
        }

        // All the individual UI components listen for ViewMode changes. This
        // simplifies the amount of logic in the AbstractActivityController, but increases the
        // possibility of timing-related bugs.
        mViewMode.addListener(this);
        mPagerController = new ConversationPagerController(mActivity, this);
        mToastBar = findActionableToastBar(mActivity);
        attachActionBar();

        mDrawIdler.setRootView(mActivity.getWindow().getDecorView());

        final Intent intent = mActivity.getIntent();

        mSearchViewController = new MaterialSearchViewController(mActivity, this, intent,
                savedState);
        addConversationListLayoutListener(mSearchViewController);

        // Immediately handle a clean launch with intent, and any state restoration
        // that does not rely on restored fragments or loader data
        // any state restoration that relies on those can be done later in
        // onRestoreInstanceState, once fragments are up and loader data is re-delivered
        if (savedState != null) {
            if (savedState.containsKey(SAVED_ACCOUNT)) {
                setAccount((Account) savedState.getParcelable(SAVED_ACCOUNT));
            }
            if (savedState.containsKey(SAVED_FOLDER)) {
                final Folder folder = savedState.getParcelable(SAVED_FOLDER);
                final String query = savedState.getString(SAVED_QUERY, null);
                setListContext(folder, query);
            }
            if (savedState.containsKey(SAVED_ACTION)) {
                mDialogAction = savedState.getInt(SAVED_ACTION);
            }
            mDialogFromSelectedSet = savedState.getBoolean(SAVED_ACTION_FROM_SELECTED, false);
            mViewMode.handleRestore(savedState);
        } else if (intent != null) {
            handleIntent(intent);
        }
        // Create the accounts loader; this loads the account switch spinner.
        mActivity.getLoaderManager().initLoader(LOADER_ACCOUNT_CURSOR, Bundle.EMPTY,
                mAccountCallbacks);
        return true;
    }

    /**
     * @param activity the activity that has been inflated
     * @return the Actionable Toast Bar defined within the activity
     */
    protected ActionableToastBar findActionableToastBar(MailActivity activity) {
        return (ActionableToastBar) activity.findViewById(R.id.toast_bar);
    }

    @Override
    public void onPostCreate(Bundle savedState) {
        if (!isDrawerEnabled()) {
            return;
        }
        // Sync the toggle state after onRestoreInstanceState has occurred.
        mDrawerToggle.syncState();

        mHideMenuItems = isDrawerEnabled() && mDrawerContainer.isDrawerOpen(mDrawerPullout);
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        if (isDrawerEnabled()) {
            mDrawerToggle.onConfigurationChanged(newConfig);
        }
    }

    /**
     * This controller listens for clicks on items in the floating action bar.
     *
     * @param view the item that was clicked in the floating action bar
     */
    @Override
    public void onClick(View view) {
        final int viewId = view.getId();
        if (viewId == R.id.compose_button) {
            ComposeActivity.compose(mActivity.getActivityContext(), getAccount());
        } else if (viewId == android.R.id.home) {
            // TODO: b/16627877
            handleUpPress();
        }
    }

    /**
     * If drawer is open/visible (even partially), close it.
     */
    protected void closeDrawerIfOpen() {
        if (!isDrawerEnabled()) {
            return;
        }
        if(mDrawerContainer.isDrawerOpen(mDrawerPullout)) {
            mDrawerContainer.closeDrawers();
        }
    }

    @Override
    public void onStart() {
        mSafeToModifyFragments = true;

        NotificationActionUtils.registerUndoNotificationObserver(mUndoNotificationObserver);

        if (mViewMode.getMode() != ViewMode.UNKNOWN) {
            Analytics.getInstance().sendView("MainActivity" + mViewMode.toString());
        }
    }

    @Override
    public void onRestart() {
        final DialogFragment fragment = (DialogFragment)
                mFragmentManager.findFragmentByTag(SYNC_ERROR_DIALOG_FRAGMENT_TAG);
        if (fragment != null) {
            fragment.dismiss();
        }
        // When the user places the app in the background by pressing "home",
        // dismiss the toast bar. However, since there is no way to determine if
        // home was pressed, just dismiss any existing toast bar when restarting
        // the app.
        if (mToastBar != null) {
            mToastBar.hide(false, false /* actionClicked */);
        }
    }

    @Override
    public Dialog onCreateDialog(int id, Bundle bundle) {
        return null;
    }

    @Override
    public final boolean onCreateOptionsMenu(Menu menu) {
        if (mViewMode.isAdMode()) {
            return false;
        }
        final MenuInflater inflater = mActivity.getMenuInflater();
        inflater.inflate(mActionBarController.getOptionsMenuId(), menu);
        mActionBarController.onCreateOptionsMenu(menu);
        return true;
    }

    @Override
    public final boolean onKeyDown(int keyCode, KeyEvent event) {
        return false;
    }

    public abstract boolean doesActionChangeConversationListVisibility(int action);

    /**
     * Helper function that determines if we should associate an undo callback with
     * the current menu action item
     * @param actionId the id of the action
     * @return the appropriate callback handler, or null if not applicable
     */
    private UndoCallback getUndoCallbackForDestructiveActionsWithAutoAdvance(
            int actionId, final Conversation conv) {
        // We associated the undoCallback if the user is going to perform an action on the current
        // conversation, causing the current conversation to be removed from view and replacing it
        // with another (via Auto Advance). The undoCallback will bring the removed conversation
        // back into the view if the action is undone.
        final Collection<Conversation> convCol = Conversation.listOf(conv);
        final boolean isApplicableForReshow = mAccount != null &&
                mAccount.settings != null &&
                mTracker != null &&
                // ensure that we will show another conversation due to Auto Advance
                mTracker.getNextConversation(
                        mAccount.settings.getAutoAdvanceSetting(), convCol) != null &&
                // ensure that we are performing the action from conversation view
                isCurrentConversationInView(convCol) &&
                // check for the appropriate destructive actions
                doesActionRemoveCurrentConversationFromView(actionId);
        return (isApplicableForReshow) ?
            new UndoCallback() {
                @Override
                public void performUndoCallback() {
                    showConversation(conv);
                }
            } : null;
    }

    /**
     * Check if the provided action will remove the active conversation from view
     * @param actionId the applied action
     * @return true if it will remove the conversation from view, false otherwise
     */
    private boolean doesActionRemoveCurrentConversationFromView(int actionId) {
        return actionId == R.id.archive ||
                actionId == R.id.delete ||
                actionId == R.id.discard_outbox ||
                actionId == R.id.remove_folder ||
                actionId == R.id.report_spam ||
                actionId == R.id.report_phishing ||
                actionId == R.id.move_to;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {

        /*
         * The action bar home/up action should open or close the drawer.
         * mDrawerToggle will take care of this.
         */
        if (isDrawerEnabled() && mDrawerToggle.onOptionsItemSelected(item)) {
            Analytics.getInstance().sendEvent(Analytics.EVENT_CATEGORY_MENU_ITEM, "drawer_toggle",
                    null, 0);
            return true;
        }

        Analytics.getInstance().sendMenuItemEvent(Analytics.EVENT_CATEGORY_MENU_ITEM,
                item.getItemId(), "action_bar/" + mViewMode.getModeString(), 0);

        final int id = item.getItemId();
        LogUtils.d(LOG_TAG, "AbstractController.onOptionsItemSelected(%d) called.", id);
        boolean handled = true;
        /** This is NOT a batch action. */
        final boolean isBatch = false;
        final Collection<Conversation> target = Conversation.listOf(mCurrentConversation);
        final Settings settings = (mAccount == null) ? null : mAccount.settings;
        // The user is choosing a new action; commit whatever they had been
        // doing before. Don't animate if we are launching a new screen.
        commitDestructiveActions(!doesActionChangeConversationListVisibility(id));
        final UndoCallback undoCallback = getUndoCallbackForDestructiveActionsWithAutoAdvance(
                id, mCurrentConversation);

        if (id == R.id.archive) {
            final boolean showDialog = (settings != null && settings.confirmArchive);
            confirmAndDelete(id, target, showDialog, R.plurals.confirm_archive_conversation, undoCallback);
        } else if (id == R.id.remove_folder) {
            delete(R.id.remove_folder, target,
                    getDeferredRemoveFolder(target, mFolder, true, isBatch, true, undoCallback),
                    isBatch);
        } else if (id == R.id.delete) {
            final boolean showDialog = (settings != null && settings.confirmDelete);
            confirmAndDelete(id, target, showDialog, R.plurals.confirm_delete_conversation, undoCallback);
        } else if (id == R.id.discard_drafts) {
            // drafts are lost forever, so always confirm
            confirmAndDelete(id, target, true /* showDialog */,
                    R.plurals.confirm_discard_drafts_conversation, undoCallback);
        } else if (id == R.id.discard_outbox) {
            // discard in outbox means we discard the failed message and save them in drafts
            delete(id, target, getDeferredAction(id, target, isBatch, undoCallback), isBatch);
        } else if (id == R.id.mark_important) {
            updateConversation(Conversation.listOf(mCurrentConversation),
                    ConversationColumns.PRIORITY, UIProvider.ConversationPriority.HIGH);
        } else if (id == R.id.mark_not_important) {
            if (mFolder != null && mFolder.isImportantOnly()) {
                delete(R.id.mark_not_important, target,
                        getDeferredAction(R.id.mark_not_important, target, isBatch, undoCallback),
                        isBatch);
            } else {
                updateConversation(Conversation.listOf(mCurrentConversation),
                        ConversationColumns.PRIORITY, UIProvider.ConversationPriority.LOW);
            }
        } else if (id == R.id.mute) {
            delete(R.id.mute, target, getDeferredAction(R.id.mute, target, isBatch, undoCallback),
                    isBatch);
        } else if (id == R.id.report_spam) {
            delete(R.id.report_spam, target,
                    getDeferredAction(R.id.report_spam, target, isBatch, undoCallback), isBatch);
        } else if (id == R.id.mark_not_spam) {
            // Currently, since spam messages are only shown in list with
            // other spam messages,
            // marking a message not as spam is a destructive action
            delete(R.id.mark_not_spam, target,
                    getDeferredAction(R.id.mark_not_spam, target, isBatch, undoCallback), isBatch);
        } else if (id == R.id.report_phishing) {
            delete(R.id.report_phishing, target,
                    getDeferredAction(R.id.report_phishing, target, isBatch, undoCallback), isBatch);
        } else if (id == android.R.id.home) {
            handleUpPress();
        } else if (id == R.id.compose) {
            ComposeActivity.compose(mActivity.getActivityContext(), mAccount);
        } else if (id == R.id.refresh) {
            requestFolderRefresh();
        } else if (id == R.id.settings) {
            Utils.showSettings(mActivity.getActivityContext(), mAccount);
        } else if (id == R.id.help_info_menu_item) {
            mActivity.showHelp(mAccount, mViewMode.getMode());
        } else if (id == R.id.move_to || id == R.id.change_folders) {
            final FolderSelectionDialog dialog = FolderSelectionDialog.getInstance(mAccount,
                    Conversation.listOf(mCurrentConversation), isBatch, mFolder,
                    id == R.id.move_to);
            if (dialog != null) {
                dialog.show(mActivity.getFragmentManager(), null);
            }
        } else if (id == R.id.move_to_inbox) {
            new AsyncTask<Void, Void, Folder>() {
                @Override
                protected Folder doInBackground(final Void... params) {
                    // Get the "move to" inbox
                    return Utils.getFolder(mContext, mAccount.settings.moveToInbox,
                            true /* allowHidden */);
                }

                @Override
                protected void onPostExecute(final Folder moveToInbox) {
                    final List<FolderOperation> ops = Lists.newArrayListWithCapacity(1);
                    // Add inbox
                    ops.add(new FolderOperation(moveToInbox, true));
                    assignFolder(ops, Conversation.listOf(mCurrentConversation), true,
                            true /* showUndo */, false /* isMoveTo */);
                }
            }.execute((Void[]) null);
        } else if (id == R.id.empty_trash) {
            showEmptyDialog();
        } else if (id == R.id.empty_spam) {
            showEmptyDialog();
        } else if (id == R.id.search) {
            mSearchViewController.showSearchActionBar(
                    MaterialSearchViewController.SEARCH_VIEW_STATE_VISIBLE);
        } else {
            handled = false;
        }
        return handled;
    }

    /**
     * Opens an {@link EmptyFolderDialogFragment} for the current folder.
     */
    private void showEmptyDialog() {
        if (mFolder != null) {
            final EmptyFolderDialogFragment fragment =
                    EmptyFolderDialogFragment.newInstance(mFolder.totalCount, mFolder.type);
            fragment.setListener(this);
            fragment.show(mActivity.getFragmentManager(), EmptyFolderDialogFragment.FRAGMENT_TAG);
        }
    }

    @Override
    public void onFolderEmptied() {
        emptyFolder();
    }

    /**
     * Performs the work of emptying the currently visible folder.
     */
    private void emptyFolder() {
        if (mConversationListCursor != null) {
            mConversationListCursor.emptyFolder();
        }
    }

    private void attachEmptyFolderDialogFragmentListener() {
        final EmptyFolderDialogFragment fragment =
                (EmptyFolderDialogFragment) mActivity.getFragmentManager()
                        .findFragmentByTag(EmptyFolderDialogFragment.FRAGMENT_TAG);

        if (fragment != null) {
            fragment.setListener(this);
        }
    }

    /**
     * Toggles the drawer pullout. If it was open (Fully extended), the
     * drawer will be closed. Otherwise, the drawer will be opened. This should
     * only be called when used with a toggle item. Other cases should be handled
     * explicitly with just closeDrawers() or openDrawer(View drawerView);
     */
    protected void toggleDrawerState() {
        if (!isDrawerEnabled()) {
            return;
        }
        if(mDrawerContainer.isDrawerOpen(mDrawerPullout)) {
            mDrawerContainer.closeDrawers();
        } else {
            mDrawerContainer.openDrawer(mDrawerPullout);
        }
    }

    @Override
    public final boolean onBackPressed() {
        if (isDrawerEnabled() && mDrawerContainer.isDrawerVisible(mDrawerPullout)) {
            mDrawerContainer.closeDrawers();
            return true;
        } else if (mSearchViewController.handleBackPress()) {
            return true;
        // If we're in CAB mode, let the activity handle onBackPressed.
        // It will handle closing CAB mode for us.
        } else if (mCabActionMenu != null && mCabActionMenu.isActivated()) {
            return false;
        }

        return handleBackPress();
    }

    protected abstract boolean handleBackPress();

    protected abstract boolean handleUpPress();

    @Override
    public void updateConversation(Collection<Conversation> target, ContentValues values) {
        mConversationListCursor.updateValues(target, values);
        refreshConversationList();
    }

    @Override
    public void updateConversation(Collection <Conversation> target, String columnName,
            boolean value) {
        mConversationListCursor.updateBoolean(target, columnName, value);
        refreshConversationList();
    }

    @Override
    public void updateConversation(Collection <Conversation> target, String columnName,
            int value) {
        mConversationListCursor.updateInt(target, columnName, value);
        refreshConversationList();
    }

    @Override
    public void updateConversation(Collection <Conversation> target, String columnName,
            String value) {
        mConversationListCursor.updateString(target, columnName, value);
        refreshConversationList();
    }

    @Override
    public void markConversationMessagesUnread(final Conversation conv,
            final Set<Uri> unreadMessageUris, final byte[] originalConversationInfo) {
        // The only caller of this method is the conversation view, from where marking unread should
        // *always* take you back to list mode.
        showConversation(null);

        // locally mark conversation unread (the provider is supposed to propagate message unread
        // to conversation unread)
        conv.read = false;
        if (mConversationListCursor == null) {
            LogUtils.d(LOG_TAG, "markConversationMessagesUnread(id=%d), deferring", conv.id);

            mConversationListLoadFinishedCallbacks.add(new LoadFinishedCallback() {
                @Override
                public void onLoadFinished() {
                    doMarkConversationMessagesUnread(conv, unreadMessageUris,
                            originalConversationInfo);
                }
            });
        } else {
            LogUtils.d(LOG_TAG, "markConversationMessagesUnread(id=%d), performing", conv.id);
            doMarkConversationMessagesUnread(conv, unreadMessageUris, originalConversationInfo);
        }
    }

    private void doMarkConversationMessagesUnread(Conversation conv, Set<Uri> unreadMessageUris,
            byte[] originalConversationInfo) {
        // Only do a granular 'mark unread' if a subset of messages are unread
        final int unreadCount = (unreadMessageUris == null) ? 0 : unreadMessageUris.size();
        final int numMessages = conv.getNumMessages();
        final boolean subsetIsUnread = (numMessages > 1 && unreadCount > 0
                && unreadCount < numMessages);

        LogUtils.d(LOG_TAG, "markConversationMessagesUnread(conv=%s)"
                + ", numMessages=%d, unreadCount=%d, subsetIsUnread=%b",
                conv, numMessages, unreadCount, subsetIsUnread);
        if (!subsetIsUnread) {
            // Conversations are neither marked read, nor viewed, and we don't want to show
            // the next conversation.
            LogUtils.d(LOG_TAG, ". . doing full mark unread");
            markConversationsRead(Collections.singletonList(conv), false, false, false);
        } else {
            if (LogUtils.isLoggable(LOG_TAG, LogUtils.DEBUG)) {
                final ConversationInfo info = ConversationInfo.fromBlob(originalConversationInfo);
                LogUtils.d(LOG_TAG, ". . doing subset mark unread, originalConversationInfo = %s",
                        info);
            }
            mConversationListCursor.setConversationColumn(conv.uri, ConversationColumns.READ, 0);

            // Locally update conversation's conversationInfo to revert to original version
            if (originalConversationInfo != null) {
                mConversationListCursor.setConversationColumn(conv.uri,
                        ConversationColumns.CONVERSATION_INFO, originalConversationInfo);
            }

            // applyBatch with each CPO as an UPDATE op on each affected message uri
            final ArrayList<ContentProviderOperation> ops = Lists.newArrayList();
            String authority = null;
            for (Uri messageUri : unreadMessageUris) {
                if (authority == null) {
                    authority = messageUri.getAuthority();
                }
                ops.add(ContentProviderOperation.newUpdate(messageUri)
                        .withValue(UIProvider.MessageColumns.READ, 0)
                        .build());
                LogUtils.d(LOG_TAG, ". . Adding op: read=0, uri=%s", messageUri);
            }
            LogUtils.d(LOG_TAG, ". . operations = %s", ops);
            new ContentProviderTask() {
                @Override
                protected void onPostExecute(Result result) {
                    if (result.exception != null) {
                        LogUtils.e(LOG_TAG, result.exception, "ContentProviderTask() ERROR.");
                    } else {
                        LogUtils.d(LOG_TAG, "ContentProviderTask(): success %s",
                                Arrays.toString(result.results));
                    }
                }
            }.run(mResolver, authority, ops);
        }
    }

    @Override
    public void markConversationsRead(final Collection<Conversation> targets, final boolean read,
            final boolean viewed) {
        LogUtils.d(LOG_TAG, "markConversationsRead(targets=%s)", targets.toArray());

        if (mConversationListCursor == null) {
            if (LogUtils.isLoggable(LOG_TAG, LogUtils.DEBUG)) {
                LogUtils.d(LOG_TAG, "markConversationsRead(targets=%s), deferring",
                        targets.toArray());
            }
            mConversationListLoadFinishedCallbacks.add(new LoadFinishedCallback() {
                @Override
                public void onLoadFinished() {
                    markConversationsRead(targets, read, viewed, true);
                }
            });
        } else {
            // We want to show the next conversation if we are marking unread.
            markConversationsRead(targets, read, viewed, true);
        }
    }

    private void markConversationsRead(final Collection<Conversation> targets, final boolean read,
            final boolean markViewed, final boolean showNext) {
        LogUtils.d(LOG_TAG, "performing markConversationsRead");
        // Auto-advance if requested and the current conversation is being marked unread
        if (showNext && !read) {
            final Runnable operation = new Runnable() {
                @Override
                public void run() {
                    markConversationsRead(targets, read, markViewed, showNext);
                }
            };

            if (!showNextConversation(targets, operation)) {
                // This method will be called again if the user selects an autoadvance option
                return;
            }
        }

        final int size = targets.size();
        final List<ConversationOperation> opList = new ArrayList<ConversationOperation>(size);
        for (final Conversation target : targets) {
            final ContentValues value = new ContentValues(4);
            value.put(ConversationColumns.READ, read);

            // We never want to mark unseen here, but we do want to mark it seen
            if (read || markViewed) {
                value.put(ConversationColumns.SEEN, Boolean.TRUE);
            }

            // The mark read/unread/viewed operations do not show an undo bar
            value.put(ConversationOperations.Parameters.SUPPRESS_UNDO, true);
            if (markViewed) {
                value.put(ConversationColumns.VIEWED, true);
            }
            final ConversationInfo info = target.conversationInfo;
            final boolean changed = info.markRead(read);
            if (changed) {
                value.put(ConversationColumns.CONVERSATION_INFO, info.toBlob());
            }
            opList.add(mConversationListCursor.getOperationForConversation(
                    target, ConversationOperation.UPDATE, value));
            // Update the local conversation objects so they immediately change state.
            target.read = read;
            if (markViewed) {
                target.markViewed();
            }
        }
        mConversationListCursor.updateBulkValues(opList);
    }

    /**
     * Auto-advance to a different conversation if the currently visible conversation in
     * conversation mode is affected (deleted, marked unread, etc.).
     *
     * <p>Does nothing if outside of conversation mode.</p>
     *
     * @param target the set of conversations being deleted/marked unread
     */
    @Override
    public void showNextConversation(final Collection<Conversation> target) {
        showNextConversation(target, null);
    }

    /**
     * Helper function to determine if the provided set of conversations is in view
     * @param target set of conversations that we are interested in
     * @return true if they are in view, false otherwise
     */
    private boolean isCurrentConversationInView(final Collection<Conversation> target) {
        final int viewMode = mViewMode.getMode();
        return (viewMode == ViewMode.CONVERSATION
                || viewMode == ViewMode.SEARCH_RESULTS_CONVERSATION)
                && Conversation.contains(target, mCurrentConversation);
    }

    /**
     * Auto-advance to a different conversation if the currently visible conversation in
     * conversation mode is affected (deleted, marked unread, etc.).
     *
     * <p>Does nothing if outside of conversation mode.</p>
     * <p>
     * Clients may pass an operation to execute on the target that this method will run after
     * auto-advance is complete. The operation, if provided, may run immediately, or it may run
     * later, or not at all. Reasons it may run later include:
     * <ul>
     * <li>the auto-advance setting is uninitialized and we need to wait for the user to set it</li>
     * <li>auto-advance in this configuration requires a mode change, and we need to wait for the
     * mode change transition to finish</li>
     * </ul>
     * <p>If the current conversation is not in the target collection, this method will do nothing,
     * and will not execute the operation.
     *
     * @param target the set of conversations being deleted/marked unread
     * @param operation (optional) the operation to execute after advancing
     * @return <code>false</code> if this method handled or will execute the operation,
     * <code>true</code> otherwise.
     */
    private boolean showNextConversation(final Collection<Conversation> target,
            final Runnable operation) {
        if (isCurrentConversationInView(target)) {
            final int autoAdvanceSetting = mAccount.settings.getAutoAdvanceSetting();

            // If we don't have one set, but we're here, just take the default
            final int autoAdvance = (autoAdvanceSetting == AutoAdvance.UNSET) ?
                    AutoAdvance.DEFAULT : autoAdvanceSetting;

            final Conversation next = mTracker.getNextConversation(autoAdvance, target);
            LogUtils.d(LOG_TAG, "showNextConversation: showing %s next.", next);
            // Set mAutoAdvanceOp *before* showConversation() to ensure that it runs when the
            // transition doesn't run (i.e. it "completes" immediately).
            mAutoAdvanceOp = operation;
            showConversation(next);
            return (mAutoAdvanceOp == null);
        }

        return true;
    }

    @Override
    public void starMessage(ConversationMessage msg, boolean starred) {
        if (msg.starred == starred) {
            return;
        }

        msg.starred = starred;

        // locally propagate the change to the owning conversation
        // (figure the provider will properly propagate the change when it commits it)
        //
        // when unstarring, only propagate the change if this was the only message starred
        final boolean conversationStarred = starred || msg.isConversationStarred();
        final Conversation conv = msg.getConversation();
        if (conversationStarred != conv.starred) {
            conv.starred = conversationStarred;
            mConversationListCursor.setConversationColumn(conv.uri,
                    ConversationColumns.STARRED, conversationStarred);
        }

        final ContentValues values = new ContentValues(1);
        values.put(UIProvider.MessageColumns.STARRED, starred ? 1 : 0);

        new ContentProviderTask.UpdateTask() {
            @Override
            protected void onPostExecute(Result result) {
                // TODO: handle errors?
            }
        }.run(mResolver, msg.uri, values, null /* selection*/, null /* selectionArgs */);
    }

    @Override
    public void requestFolderRefresh() {
        if (mFolder == null) {
            return;
        }
        final ConversationListFragment convList = getConversationListFragment();
        if (convList == null) {
            // This could happen if this account is in initial sync (user
            // is seeing the "your mail will appear shortly" message)
            return;
        }

        // TODO: remove me after experiment b/17508768
        final String id = android.provider.Settings.Secure.getString(
                mActivity.getContentResolver(), android.provider.Settings.Secure.ANDROID_ID);
        if (!TextUtils.isEmpty(id)) {
            final long longId = Long.parseLong(
                    Character.toString(id.charAt(id.length() - 1)), 16 /* hex */);
            Analytics.getInstance().sendEvent("battery_experiment", "refresh",
                    longId % 2 == 0 ? "even" : "odd", 1);
        }

        convList.showSyncStatusBar();

        if (mAsyncRefreshTask != null) {
            mAsyncRefreshTask.cancel(true);
        }
        mAsyncRefreshTask = new AsyncRefreshTask(mContext, mFolder.refreshUri);
        mAsyncRefreshTask.execute();
    }

    /**
     * Confirm (based on user's settings) and delete a conversation from the conversation list and
     * from the database.
     * @param actionId the ID of the menu item that caused the delete: R.id.delete, R.id.archive...
     * @param target the conversations to act upon
     * @param showDialog true if a confirmation dialog is to be shown, false otherwise.
     * @param confirmResource the resource ID of the string that is shown in the confirmation dialog
     */
    private void confirmAndDelete(int actionId, final Collection<Conversation> target,
            boolean showDialog, int confirmResource, UndoCallback undoCallback) {
        final boolean isBatch = false;
        if (showDialog) {
            makeDialogListener(actionId, isBatch, undoCallback);
            final CharSequence message = Utils.formatPlural(mContext, confirmResource,
                    target.size());
            final ConfirmDialogFragment c = ConfirmDialogFragment.newInstance(message);
            c.displayDialog(mActivity.getFragmentManager());
        } else {
            delete(0, target, getDeferredAction(actionId, target, isBatch, undoCallback), isBatch);
        }
    }

    @Override
    public void delete(final int actionId, final Collection<Conversation> target,
                       final DestructiveAction action, final boolean isBatch) {
        // Order of events is critical! The Conversation View Fragment must be
        // notified of the next conversation with showConversation(next) *before* the
        // conversation list
        // fragment has a chance to delete the conversation, animating it away.

        // Update the conversation fragment if the current conversation is
        // deleted.
        final Runnable operation = new Runnable() {
            @Override
            public void run() {
                delete(actionId, target, action, isBatch);
            }
        };

        showNextConversation(target, operation);

        // If the conversation is in the selected set, remove it from the set.
        // Batch selections are cleared in the end of the action, so not done for batch actions.
        if (!isBatch) {
            for (final Conversation conv : target) {
                if (mCheckedSet.contains(conv)) {
                    mCheckedSet.toggle(conv);
                }
            }
        }
        // The conversation list deletes and performs the action if it exists.
        final ConversationListFragment convListFragment = getConversationListFragment();
        if (convListFragment != null) {
            LogUtils.i(LOG_TAG, "AAC.requestDelete: ListFragment is handling delete.");
            convListFragment.requestDelete(actionId, target, action);
            return;
        }
        // No visible UI element handled it on our behalf. Perform the action
        // ourself.
        LogUtils.i(LOG_TAG, "ACC.requestDelete: performing remove action ourselves");
        action.performAction();
    }

    /**
     * Requests that the action be performed and the UI state is updated to reflect the new change.
     * @param action the action to be performed, specified as a menu id: R.id.archive, ...
     */
    private void requestUpdate(final DestructiveAction action) {
        action.performAction();
        refreshConversationList();
    }

    @Override
    public void onPrepareDialog(int id, Dialog dialog, Bundle bundle) {
        // TODO(viki): Auto-generated method stub
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        return mActionBarController.onPrepareOptionsMenu(menu);
    }

    @Override
    public void onPause() {
        mHaveAccountList = false;
        enableNotifications();
    }

    @Override
    public void onResume() {
        // Register the receiver that will prevent the status receiver from
        // displaying its notification icon as long as we're running.
        // The SupressNotificationReceiver will block the broadcast if we're looking at the folder
        // that the notification was received for.
        disableNotifications();

        mSafeToModifyFragments = true;

        attachEmptyFolderDialogFragmentListener();

        // Invalidating the options menu so that when we make changes in settings,
        // the changes will always be updated in the action bar/options menu/
        mActivity.invalidateOptionsMenu();
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        mViewMode.handleSaveInstanceState(outState);
        if (mAccount != null) {
            outState.putParcelable(SAVED_ACCOUNT, mAccount);
        }
        if (mFolder != null) {
            outState.putParcelable(SAVED_FOLDER, mFolder);
        }
        // If this is a search activity, let's store the search query term as well.
        if (ConversationListContext.isSearchResult(mConvListContext)) {
            outState.putString(SAVED_QUERY, mConvListContext.searchQuery);
        }
        if (mCurrentConversation != null && mViewMode.isConversationMode()) {
            outState.putParcelable(SAVED_CONVERSATION, mCurrentConversation);
        }
        if (!mCheckedSet.isEmpty()) {
            outState.putParcelable(SAVED_SELECTED_SET, mCheckedSet);
        }
        if (mToastBar.getVisibility() == View.VISIBLE) {
            outState.putParcelable(SAVED_TOAST_BAR_OP, mToastBar.getOperation());
        }
        final ConversationListFragment convListFragment = getConversationListFragment();
        if (convListFragment != null) {
            convListFragment.getAnimatedAdapter().onSaveInstanceState(outState);
        }
        // If there is a dialog being shown, save the state so we can create a listener for it.
        if (mDialogAction != -1) {
            outState.putInt(SAVED_ACTION, mDialogAction);
            outState.putBoolean(SAVED_ACTION_FROM_SELECTED, mDialogFromSelectedSet);
        }
        if (mDetachedConvUri != null) {
            outState.putParcelable(SAVED_DETACHED_CONV_URI, mDetachedConvUri);
        }

        outState.putParcelable(SAVED_HIERARCHICAL_FOLDER, mFolderListFolder);
        mSafeToModifyFragments = false;

        outState.putParcelable(SAVED_INBOX_KEY, mInbox);

        outState.putBundle(SAVED_CONVERSATION_LIST_SCROLL_POSITIONS,
                mConversationListScrollPositions);

        mSearchViewController.saveState(outState);
    }

    /**
     * @see #mSafeToModifyFragments
     */
    protected boolean safeToModifyFragments() {
        return mSafeToModifyFragments;
    }

    @Override
    public void executeSearch(String query) {
        AnalyticsTimer.getInstance().trackStart(AnalyticsTimer.SEARCH_TO_LIST);
        Intent intent = new Intent();
        intent.setAction(Intent.ACTION_SEARCH);
        intent.putExtra(ConversationListContext.EXTRA_SEARCH_QUERY, query);
        intent.putExtra(Utils.EXTRA_ACCOUNT, mAccount);
        intent.setComponent(mActivity.getComponentName());
        mSearchViewController.showSearchActionBar(
                MaterialSearchViewController.SEARCH_VIEW_STATE_GONE);
        // Call startActivityForResult here so we can tell if we have navigated to a different folder
        // or account from search results.
        mActivity.startActivityForResult(intent, CHANGE_NAVIGATION_REQUEST_CODE);
    }

    @Override
    public void onStop() {
        NotificationActionUtils.unregisterUndoNotificationObserver(mUndoNotificationObserver);
    }

    @Override
    public void onDestroy() {
        // stop listening to the cursor on e.g. configuration changes
        if (mConversationListCursor != null) {
            mConversationListCursor.removeListener(this);
        }
        mDrawIdler.setListener(null);
        mDrawIdler.setRootView(null);
        // unregister the ViewPager's observer on the conversation cursor
        mPagerController.onDestroy();
        mActionBarController.onDestroy();
        mRecentFolderList.destroy();
        mDestroyed = true;
        mHandler.removeCallbacks(mLogServiceChecker);
        mLogServiceChecker = null;
        mSearchViewController.onDestroy();
    }

    /**
     * Set the Action Bar icon according to the mode. The Action Bar icon can contain a back button
     * or not. The individual controller is responsible for changing the icon based on the mode.
     */
    protected abstract void resetActionBarIcon();

    /**
     * {@inheritDoc} Subclasses must override this to listen to mode changes
     * from the ViewMode. Subclasses <b>must</b> call the parent's
     * onViewModeChanged since the parent will handle common state changes.
     */
    @Override
    public void onViewModeChanged(int newMode) {
        // When we step away from the conversation mode, we don't have a current conversation
        // anymore. Let's blank it out so clients calling getCurrentConversation are not misled.
        if (!ViewMode.isConversationMode(newMode)) {
            setCurrentConversation(null);
        }

        // If the viewmode is not set, preserve existing icon.
        if (newMode != ViewMode.UNKNOWN) {
            resetActionBarIcon();
        }

        if (isDrawerEnabled()) {
            /** If the folder doesn't exist, or its parent URI is empty,
             * this is not a child folder */
            final boolean isTopLevel = Folder.isRoot(mFolder);
            mDrawerToggle.setDrawerIndicatorEnabled(
                    getShouldShowDrawerIndicator(newMode, isTopLevel));
            mDrawerContainer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
            closeDrawerIfOpen();
        }
    }

    /**
     * Returns true if the drawer icon is shown
     * @param viewMode the current view mode
     * @param isTopLevel true if the current folder is not a child
     * @return whether the drawer indicator is shown
     */
    private boolean getShouldShowDrawerIndicator(final int viewMode,
            final boolean isTopLevel) {
        // If search list/conv mode: disable indicator
        // Indicator is enabled either in conversation list or folder list mode.
        return isDrawerEnabled() && !ViewMode.isSearchMode(viewMode)
            && (viewMode == ViewMode.CONVERSATION_LIST  && isTopLevel);
    }

    public void disablePagerUpdates() {
        mPagerController.stopListening();
    }

    public boolean isDestroyed() {
        return mDestroyed;
    }

    @Override
    public void commitDestructiveActions(boolean animate) {
        ConversationListFragment fragment = getConversationListFragment();
        if (fragment != null) {
            fragment.commitDestructiveActions(animate);
        }
    }

    @Override
    public void onWindowFocusChanged(boolean hasFocus) {
        final ConversationListFragment convList = getConversationListFragment();
        // hasFocus already ensures that the window is in focus, so we don't need to call
        // AAC.isFragmentVisible(convList) here.
        if (hasFocus && convList != null && convList.isVisible()) {
            // The conversation list is visible.
            informCursorVisiblity(true);
        }
    }

    /**
     * Set the account, and carry out all the account-related changes that rely on this.
     * @param account new account to set to.
     */
    private void setAccount(Account account) {
        if (account == null) {
            LogUtils.w(LOG_TAG, new Error(),
                    "AAC ignoring null (presumably invalid) account restoration");
            return;
        }
        LogUtils.d(LOG_TAG, "AbstractActivityController.setAccount(): account = %s", account.uri);
        mAccount = account;

        Analytics.getInstance().setEmail(account.getEmailAddress(), account.getType());

        // Only change AAC state here. Do *not* modify any other object's state. The object
        // should listen on account changes.
        restartOptionalLoader(LOADER_RECENT_FOLDERS, mFolderCallbacks, Bundle.EMPTY);
        mActivity.invalidateOptionsMenu();
        disableNotificationsOnAccountChange(mAccount);
        restartOptionalLoader(LOADER_ACCOUNT_UPDATE_CURSOR, mAccountCallbacks, Bundle.EMPTY);
        // The Mail instance can be null during test runs.
        final MailAppProvider instance = MailAppProvider.getInstance();
        if (instance != null) {
            instance.setLastViewedAccount(mAccount.uri.toString());
        }
        if (account.settings == null) {
            LogUtils.w(LOG_TAG, new Error(), "AAC ignoring account with null settings.");
            return;
        }
        mAccountObservers.notifyChanged();
        perhapsEnterWaitMode();
    }

    /**
     * Restore the state from the previous bundle. Subclasses should call this
     * method from the parent class, since it performs important UI
     * initialization.
     *
     * @param savedState previous state
     */
    @Override
    public void onRestoreInstanceState(Bundle savedState) {
        mDetachedConvUri = savedState.getParcelable(SAVED_DETACHED_CONV_URI);
        if (savedState.containsKey(SAVED_CONVERSATION)) {
            // Open the conversation.
            final Conversation conversation = savedState.getParcelable(SAVED_CONVERSATION);
            if (conversation != null && conversation.position < 0) {
                // Set the position to 0 on this conversation, as we don't know where it is
                // in the list
                conversation.position = 0;
            }
            showConversation(conversation);
        }

        if (savedState.containsKey(SAVED_TOAST_BAR_OP)) {
            ToastBarOperation op = savedState.getParcelable(SAVED_TOAST_BAR_OP);
            if (op != null) {
                if (op.getType() == ToastBarOperation.UNDO) {
                    onUndoAvailable(op);
                } else if (op.getType() == ToastBarOperation.ERROR) {
                    onError(mFolder, true);
                }
            }
        }
        mFolderListFolder = savedState.getParcelable(SAVED_HIERARCHICAL_FOLDER);
        final ConversationListFragment convListFragment = getConversationListFragment();
        if (convListFragment != null) {
            convListFragment.getAnimatedAdapter().onRestoreInstanceState(savedState);
        }
        /*
         * Restore the state of selected conversations. This needs to be done after the correct mode
         * is set and the action bar is fully initialized. If not, several key pieces of state
         * information will be missing, and the split views may not be initialized correctly.
         */
        restoreSelectedConversations(savedState);
        // Order is important!!!
        // The dialog listener needs to happen *after* the selected set is restored.

        // If there has been an orientation change, and we need to recreate the listener for the
        // confirm dialog fragment (delete/archive/...), then do it here.
        if (mDialogAction != -1) {
            makeDialogListener(mDialogAction, mDialogFromSelectedSet,
                    getUndoCallbackForDestructiveActionsWithAutoAdvance(
                            mDialogAction, mCurrentConversation));
        }

        mInbox = savedState.getParcelable(SAVED_INBOX_KEY);

        mConversationListScrollPositions.clear();
        mConversationListScrollPositions.putAll(
                savedState.getBundle(SAVED_CONVERSATION_LIST_SCROLL_POSITIONS));
    }

    /**
     * Handle an intent to open the app. This method is called only when there is no saved state,
     * so we need to set state that wasn't set before. It is correct to change the viewmode here
     * since it has not been previously set.
     *
     * This method is called for a subset of the reasons mentioned in
     * {@link #onCreate(android.os.Bundle)}. Notably, this is called when launching the app from
     * notifications, widgets, and shortcuts.
     * @param intent intent passed to the activity.
     */
    private void handleIntent(Intent intent) {
        LogUtils.d(LOG_TAG, "IN AAC.handleIntent. action=%s", intent.getAction());
        if (Intent.ACTION_VIEW.equals(intent.getAction())) {
            if (intent.hasExtra(Utils.EXTRA_ACCOUNT)) {
                setAccount(Account.newInstance(intent.getStringExtra(Utils.EXTRA_ACCOUNT)));
            }
            if (mAccount == null) {
                return;
            }
            final boolean isConversationMode = intent.hasExtra(Utils.EXTRA_CONVERSATION);

            if (intent.getBooleanExtra(Utils.EXTRA_FROM_NOTIFICATION, false)) {
                Analytics.getInstance().setEmail(mAccount.getEmailAddress(), mAccount.getType());
                Analytics.getInstance().sendEvent("notification_click",
                        isConversationMode ? "conversation" : "conversation_list", null, 0);
            }

            if (isConversationMode && mViewMode.getMode() == ViewMode.UNKNOWN) {
                mViewMode.enterConversationMode();
            } else {
                mViewMode.enterConversationListMode();
            }
            // Put the folder and conversation, and ask the loader to create this folder.
            final Bundle args = new Bundle();

            final Uri folderUri;
            if (intent.hasExtra(Utils.EXTRA_FOLDER_URI)) {
                folderUri = intent.getParcelableExtra(Utils.EXTRA_FOLDER_URI);
            } else if (intent.hasExtra(Utils.EXTRA_FOLDER)) {
                final Folder folder =
                        Folder.fromString(intent.getStringExtra(Utils.EXTRA_FOLDER));
                folderUri = folder.folderUri.fullUri;
            } else {
                final Bundle extras = intent.getExtras();
                LogUtils.d(LOG_TAG, "Couldn't find a folder URI in the extras: %s",
                        extras == null ? "null" : extras.toString());
                folderUri = mAccount.settings.defaultInbox;
            }

            // Check if we should load all conversations instead of using
            // the default behavior which loads an initial subset.
            mIgnoreInitialConversationLimit =
                    intent.getBooleanExtra(Utils.EXTRA_IGNORE_INITIAL_CONVERSATION_LIMIT, false);

            args.putParcelable(Utils.EXTRA_FOLDER_URI, folderUri);
            args.putParcelable(Utils.EXTRA_CONVERSATION,
                    intent.getParcelableExtra(Utils.EXTRA_CONVERSATION));
            restartOptionalLoader(LOADER_FIRST_FOLDER, mFolderCallbacks, args);
        } else if (Intent.ACTION_SEARCH.equals(intent.getAction())) {
            if (intent.hasExtra(Utils.EXTRA_ACCOUNT)) {
                mHaveSearchResults = false;
                // Save this search query for future suggestions
                final String query = intent.getStringExtra(SearchManager.QUERY);
                mSearchViewController.saveRecentQuery(query);
                setAccount((Account) intent.getParcelableExtra(Utils.EXTRA_ACCOUNT));
                fetchSearchFolder(intent);
                if (shouldEnterSearchConvMode()) {
                    mViewMode.enterSearchResultsConversationMode();
                } else {
                    mViewMode.enterSearchResultsListMode();
                }
            } else {
                LogUtils.e(LOG_TAG, "Missing account extra from search intent.  Finishing");
                mActivity.finish();
            }
        }
        if (mAccount != null) {
            restartOptionalLoader(LOADER_ACCOUNT_UPDATE_CURSOR, mAccountCallbacks, Bundle.EMPTY);
        }
    }

    /**
     * Returns true if we should enter conversation mode with search.
     */
    protected final boolean shouldEnterSearchConvMode() {
        return mHaveSearchResults && Utils.showTwoPaneSearchResults(mActivity.getActivityContext());
    }

    /**
     * Copy any selected conversations stored in the saved bundle into our selection set,
     * triggering {@link ConversationSetObserver} callbacks as our selection set changes.
     *
     */
    private void restoreSelectedConversations(Bundle savedState) {
        if (savedState == null) {
            mCheckedSet.clear();
            return;
        }
        final ConversationCheckedSet selectedSet = savedState.getParcelable(SAVED_SELECTED_SET);
        if (selectedSet == null || selectedSet.isEmpty()) {
            mCheckedSet.clear();
            return;
        }

        // putAll will take care of calling our registered onSetPopulated method
        mCheckedSet.putAll(selectedSet);
    }

    /**
     * Show the conversation provided in the arguments. It is safe to pass a null conversation
     * object, which is a signal to back out of conversation view mode.
     * Child classes must call super.showConversation() <b>before</b> their own implementations.
     * @param conversation the conversation to be shown, or null if we want to back out to list
     *                     mode.
     * onLoadFinished(Loader, Cursor) on any callback.
     */
    protected void showConversation(Conversation conversation) {
        showConversation(conversation, false /* peek */);
    }

    protected void showConversation(Conversation conversation, boolean peek) {
        if (conversation != null) {
            Utils.sConvLoadTimer.start();
        }

        MailLogService.log("AbstractActivityController", "showConversation(%s)", conversation);
        // Set the current conversation just in case it wasn't already set.
        setCurrentConversation(conversation);
    }

    /**
     * Show the wait for account initialization mode.
     * Children can override this method, but they must call super.showWaitForInitialization().
     */
    protected void showWaitForInitialization() {
        mViewMode.enterWaitingForInitializationMode();
        mWaitFragment = WaitFragment.newInstance(mAccount, true /* expectingMessages */);
    }

    private void updateWaitMode() {
        final FragmentManager manager = mActivity.getFragmentManager();
        final WaitFragment waitFragment =
                (WaitFragment)manager.findFragmentByTag(TAG_WAIT);
        if (waitFragment != null) {
            waitFragment.updateAccount(mAccount);
        }
    }

    /**
     * Remove the "Waiting for Initialization" fragment. Child classes are free to override this
     * method, though they must call the parent implementation <b>after</b> they do anything.
     */
    protected void hideWaitForInitialization() {
        mWaitFragment = null;
    }

    /**
     * Use the instance variable and the wait fragment's tag to get the wait fragment.  This is
     * far superior to using the value of mWaitFragment, which might be invalid or might refer
     * to a fragment after it has been destroyed.
     * @return a wait fragment that is already attached to the activity, if one exists
     */
    protected final WaitFragment getWaitFragment() {
        final FragmentManager manager = mActivity.getFragmentManager();
        final WaitFragment waitFrag = (WaitFragment) manager.findFragmentByTag(TAG_WAIT);
        if (waitFrag != null) {
            // The Fragment Manager knows better, so use its instance.
            mWaitFragment = waitFrag;
        }
        return mWaitFragment;
    }

    /**
     * Returns true if we are waiting for the account to sync, and cannot show any folders or
     * conversation for the current account yet.
     */
    private boolean inWaitMode() {
        final WaitFragment waitFragment = getWaitFragment();
        if (waitFragment != null) {
            final Account fragmentAccount = waitFragment.getAccount();
            return fragmentAccount != null && fragmentAccount.uri.equals(mAccount.uri) &&
                    mViewMode.getMode() == ViewMode.WAITING_FOR_ACCOUNT_INITIALIZATION;
        }
        return false;
    }

    /**
     * Show the conversation List with the list context provided here. On certain layouts, this
     * might show more than just the conversation list. For instance, on tablets this might show
     * the conversations along with the conversation list.
     * @param listContext context providing information on what conversation list to display.
     */
    protected abstract void showConversationList(ConversationListContext listContext);

    @Override
    public void onConversationSelected(Conversation conversation, boolean inLoaderCallbacks) {
        final ConversationListFragment convListFragment = getConversationListFragment();
        if (convListFragment != null && convListFragment.getAnimatedAdapter() != null) {
            convListFragment.getAnimatedAdapter().onConversationSelected();
        }
        // Only animate destructive actions if we are going to be showing the
        // conversation list when we show the next conversation.
        commitDestructiveActions(mIsTablet);
        showConversation(conversation);
    }

    @Override
    public final void onCabModeEntered() {
        final ConversationListFragment convListFragment = getConversationListFragment();
        if (convListFragment != null && convListFragment.getAnimatedAdapter() != null) {
            convListFragment.getAnimatedAdapter().onCabModeEntered();
        }
    }

    @Override
    public final void onCabModeExited() {
        final ConversationListFragment convListFragment = getConversationListFragment();
        if (convListFragment != null && convListFragment.getAnimatedAdapter() != null) {
            convListFragment.getAnimatedAdapter().onCabModeExited();
        }
    }

    @Override
    public Conversation getCurrentConversation() {
        return mCurrentConversation;
    }

    /**
     * Set the current conversation. This is the conversation on which all actions are performed.
     * Do not modify mCurrentConversation except through this method, which makes it easy to
     * perform common actions associated with changing the current conversation.
     * @param conversation new conversation to view. Passing null indicates that we are backing
     *                     out to conversation list mode.
     */
    @Override
    public void setCurrentConversation(Conversation conversation) {
        // The controller should come out of detached mode if a new conversation is viewed, or if
        // we are going back to conversation list mode.
        if (mDetachedConvUri != null && (conversation == null
                || !mDetachedConvUri.equals(conversation.uri))) {
            clearDetachedMode();
        }

        // Must happen *before* setting mCurrentConversation because this sets
        // conversation.position if a cursor is available.
        mTracker.initialize(conversation);
        mCurrentConversation = conversation;

        if (mCurrentConversation != null) {
            mActionBarController.setCurrentConversation(mCurrentConversation);
            mActivity.invalidateOptionsMenu();
        }
    }

    /**
     * {@link LoaderManager} currently has a bug in
     * {@link LoaderManager#restartLoader(int, Bundle, android.app.LoaderManager.LoaderCallbacks)}
     * where, if a previous onCreateLoader returned a null loader, this method will NPE. Work around
     * this bug by destroying any loaders that may have been created as null (essentially because
     * they are optional loads, and may not apply to a particular account).
     * <p>
     * A simple null check before restarting a loader will not work, because that would not
     * give the controller a chance to invalidate UI corresponding the prior loader result.
     *
     * @param id loader ID to safely restart
     * @param handler the LoaderCallback which will handle this loader ID.
     * @param args arguments, if any, to be passed to the loader. Use {@link Bundle#EMPTY} if no
     *             arguments need to be specified.
     */
    private void restartOptionalLoader(int id, LoaderManager.LoaderCallbacks handler, Bundle args) {
        final LoaderManager lm = mActivity.getLoaderManager();
        lm.destroyLoader(id);
        lm.restartLoader(id, args, handler);
    }

    @Override
    public void registerConversationListObserver(DataSetObserver observer) {
        mConversationListObservable.registerObserver(observer);
    }

    @Override
    public void unregisterConversationListObserver(DataSetObserver observer) {
        try {
            mConversationListObservable.unregisterObserver(observer);
        } catch (IllegalStateException e) {
            // Log instead of crash
            LogUtils.e(LOG_TAG, e, "unregisterConversationListObserver called for an observer that "
                    + "hasn't been registered");
        }
    }

    @Override
    public void registerFolderObserver(DataSetObserver observer) {
        mFolderObservable.registerObserver(observer);
    }

    @Override
    public void unregisterFolderObserver(DataSetObserver observer) {
        try {
            mFolderObservable.unregisterObserver(observer);
        } catch (IllegalStateException e) {
            // Log instead of crash
            LogUtils.e(LOG_TAG, e, "unregisterFolderObserver called for an observer that "
                    + "hasn't been registered");
        }
    }

    @Override
    public void registerConversationLoadedObserver(DataSetObserver observer) {
        mPagerController.registerConversationLoadedObserver(observer);
    }

    @Override
    public void unregisterConversationLoadedObserver(DataSetObserver observer) {
        try {
            mPagerController.unregisterConversationLoadedObserver(observer);
        } catch (IllegalStateException e) {
            // Log instead of crash
            LogUtils.e(LOG_TAG, e, "unregisterConversationLoadedObserver called for an observer "
                    + "that hasn't been registered");
        }
    }

    /**
     * Returns true if the number of accounts is different, or if the current account has
     * changed. This method is meant to filter frequent changes to the list of
     * accounts, and only return true if the new list is substantially different from the existing
     * list. Returning true is safe here, it leads to more work in creating the
     * same account list again.
     * @param accountCursor the cursor which points to all the accounts.
     * @return true if the number of accounts is changed or current account missing from the list.
     */
    private boolean accountsUpdated(ObjectCursor<Account> accountCursor) {
        // Check to see if the current account hasn't been set, or the account cursor is empty
        if (mAccount == null || !accountCursor.moveToFirst()) {
            return true;
        }

        // Check to see if the number of accounts are different, from the number we saw on the last
        // updated
        if (mCurrentAccountUris.size() != accountCursor.getCount()) {
            return true;
        }

        // Check to see if the account list is different or if the current account is not found in
        // the cursor.
        boolean foundCurrentAccount = false;
        do {
            final Account account = accountCursor.getModel();
            if (!foundCurrentAccount && mAccount.uri.equals(account.uri)) {
                if (mAccount.settingsDiffer(account)) {
                    // Settings changed, and we don't need to look any further.
                    return true;
                }
                foundCurrentAccount = true;
            }
            // Is there a new account that we do not know about?
            if (!mCurrentAccountUris.contains(account.uri)) {
                return true;
            }
        } while (accountCursor.moveToNext());

        // As long as we found the current account, the list hasn't been updated
        return !foundCurrentAccount;
    }

    /**
     * Updates accounts for the app. If the current account is missing, the first
     * account in the list is set to the current account (we <em>have</em> to choose something).
     *
     * @param accounts cursor into the AccountCache
     * @return true if the update was successful, false otherwise
     */
    private boolean updateAccounts(ObjectCursor<Account> accounts) {
        if (accounts == null || !accounts.moveToFirst()) {
            return false;
        }

        final Account[] allAccounts = Account.getAllAccounts(accounts);
        // A match for the current account's URI in the list of accounts.
        Account currentFromList = null;

        // Save the uris for the accounts and find the current account in the updated cursor.
        mCurrentAccountUris.clear();
        for (final Account account : allAccounts) {
            LogUtils.d(LOG_TAG, "updateAccounts(%s)", account);
            mCurrentAccountUris.add(account.uri);
            if (mAccount != null && account.uri.equals(mAccount.uri)) {
                currentFromList = account;
            }
        }

        // 1. current account is already set and is in allAccounts:
        //    1a. It has changed -> load the updated account.
        //    1b. It is unchanged -> no-op
        // 2. current account is set and is not in allAccounts -> pick first (acct was deleted?)
        // 3. saved preference has an account -> pick that one
        // 4. otherwise just pick first

        boolean accountChanged = false;
        /// Assume case 4, initialize to first account, and see if we can find anything better.
        Account newAccount = allAccounts[0];
        if (currentFromList != null) {
            // Case 1: Current account exists but has changed
            if (!currentFromList.equals(mAccount)) {
                newAccount = currentFromList;
                accountChanged = true;
            }
            // Case 1b: else, current account is unchanged: nothing to do.
        } else {
            // Case 2: Current account is not in allAccounts, the account needs to change.
            accountChanged = true;
            if (mAccount == null) {
                // Case 3: Check for last viewed account, and check if it exists in the list.
                final String lastAccountUri = MailAppProvider.getInstance().getLastViewedAccount();
                if (lastAccountUri != null) {
                    for (final Account account : allAccounts) {
                        if (lastAccountUri.equals(account.uri.toString())) {
                            newAccount = account;
                            break;
                        }
                    }
                }
            }
        }
        if (accountChanged) {
            changeAccount(newAccount);
        }

        // Whether we have updated the current account or not, we need to update the list of
        // accounts in the ActionBar.
        mAllAccounts = allAccounts;
        mAllAccountObservers.notifyChanged();
        return (allAccounts.length > 0);
    }

    private void disableNotifications() {
        mNewEmailReceiver.activate(mContext, this);
    }

    private void enableNotifications() {
        mNewEmailReceiver.deactivate();
    }

    private void disableNotificationsOnAccountChange(Account account) {
        // If the new mail suppression receiver is activated for a different account, we want to
        // activate it for the new account.
        if (mNewEmailReceiver.activated() &&
                !mNewEmailReceiver.notificationsDisabledForAccount(account)) {
            // Deactivate the current receiver, otherwise multiple receivers may be registered.
            mNewEmailReceiver.deactivate();
            mNewEmailReceiver.activate(mContext, this);
        }
    }

    /**
     * Destructive actions on Conversations. This class should only be created by controllers, and
     * clients should only require {@link DestructiveAction}s, not specific implementations of the.
     * Only the controllers should know what kind of destructive actions are being created.
     */
    public class ConversationAction implements DestructiveAction {
        /**
         * The action to be performed. This is specified as the resource ID of the menu item
         * corresponding to this action: R.id.delete, R.id.report_spam, etc.
         */
        private final int mAction;
        /** The action will act upon these conversations */
        private final Collection<Conversation> mTarget;
        /** Whether this destructive action has already been performed */
        private boolean mCompleted;
        /** Whether this is an action on the currently selected set. */
        private final boolean mIsSelectedSet;

        private UndoCallback mCallback;

        /**
         * Create a listener object.
         * @param action action is one of four constants: R.id.y_button (archive),
         * R.id.delete , R.id.mute, and R.id.report_spam.
         * @param target Conversation that we want to apply the action to.
         * @param isBatch whether the conversations are in the currently selected batch set.
         */
        public ConversationAction(int action, Collection<Conversation> target, boolean isBatch) {
            mAction = action;
            mTarget = ImmutableList.copyOf(target);
            mIsSelectedSet = isBatch;
        }

        @Override
        public void setUndoCallback(UndoCallback undoCallback) {
            mCallback = undoCallback;
        }

        /**
         * The action common to child classes. This performs the action specified in the constructor
         * on the conversations given here.
         */
        @Override
        public void performAction() {
            if (isPerformed()) {
                return;
            }
            boolean undoEnabled = mAccount.supportsCapability(AccountCapabilities.UNDO);

            // Are we destroying the currently shown conversation? Show the next one.
            if (LogUtils.isLoggable(LOG_TAG, LogUtils.DEBUG)){
                LogUtils.d(LOG_TAG, "ConversationAction.performAction():"
                        + "\nmTarget=%s\nCurrent=%s",
                        Conversation.toString(mTarget), mCurrentConversation);
            }

            if (mConversationListCursor == null) {
                LogUtils.e(LOG_TAG, "null ConversationCursor in ConversationAction.performAction():"
                        + "\nmTarget=%s\nCurrent=%s",
                        Conversation.toString(mTarget), mCurrentConversation);
                return;
            }

            if (mAction == R.id.archive) {
                LogUtils.d(LOG_TAG, "Archiving");
                mConversationListCursor.archive(mTarget, mCallback);
            } else if (mAction == R.id.delete) {
                LogUtils.d(LOG_TAG, "Deleting");
                mConversationListCursor.delete(mTarget, mCallback);
                if (mFolder.supportsCapability(FolderCapabilities.DELETE_ACTION_FINAL)) {
                    undoEnabled = false;
                }
            } else if (mAction == R.id.mute) {
                LogUtils.d(LOG_TAG, "Muting");
                if (mFolder.supportsCapability(FolderCapabilities.DESTRUCTIVE_MUTE)) {
                    for (Conversation c : mTarget) {
                        c.localDeleteOnUpdate = true;
                    }
                }
                mConversationListCursor.mute(mTarget, mCallback);
            } else if (mAction == R.id.report_spam) {
                LogUtils.d(LOG_TAG, "Reporting spam");
                mConversationListCursor.reportSpam(mTarget, mCallback);
            } else if (mAction == R.id.mark_not_spam) {
                LogUtils.d(LOG_TAG, "Marking not spam");
                mConversationListCursor.reportNotSpam(mTarget, mCallback);
            } else if (mAction == R.id.report_phishing) {
                LogUtils.d(LOG_TAG, "Reporting phishing");
                mConversationListCursor.reportPhishing(mTarget, mCallback);
            } else if (mAction == R.id.remove_star) {
                LogUtils.d(LOG_TAG, "Removing star");
                // Star removal is destructive in the Starred folder.
                mConversationListCursor.updateBoolean(mTarget, ConversationColumns.STARRED,
                        false);
            } else if (mAction == R.id.mark_not_important) {
                LogUtils.d(LOG_TAG, "Marking not-important");
                // Marking not important is destructive in a mailbox
                // containing only important messages
                if (mFolder != null && mFolder.isImportantOnly()) {
                    for (Conversation conv : mTarget) {
                        conv.localDeleteOnUpdate = true;
                    }
                }
                mConversationListCursor.updateInt(mTarget, ConversationColumns.PRIORITY,
                        UIProvider.ConversationPriority.LOW);
            } else if (mAction == R.id.discard_drafts) {
                LogUtils.d(LOG_TAG, "Discarding draft messages");
                // Discarding draft messages is destructive in a "draft" mailbox
                if (mFolder != null && mFolder.isDraft()) {
                    for (Conversation conv : mTarget) {
                        conv.localDeleteOnUpdate = true;
                    }
                }
                mConversationListCursor.discardDrafts(mTarget);
                // We don't support undoing discarding drafts
                undoEnabled = false;
            } else if (mAction == R.id.discard_outbox) {
                LogUtils.d(LOG_TAG, "Discarding failed messages in Outbox");
                mConversationListCursor.moveFailedIntoDrafts(mTarget);
                undoEnabled = false;
            }
            if (undoEnabled && mTarget.size() > 0) {
                mHandler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        onUndoAvailable(new ToastBarOperation(mTarget.size(), mAction,
                                ToastBarOperation.UNDO, mIsSelectedSet, mFolder));
                    }
                }, mShowUndoBarDelay);
            }
            refreshConversationList();
            if (mIsSelectedSet) {
                mCheckedSet.clear();
            }
        }

        /**
         * Returns true if this action has been performed, false otherwise.
         *
         */
        private synchronized boolean isPerformed() {
            if (mCompleted) {
                return true;
            }
            mCompleted = true;
            return false;
        }
    }

    // Called from the FolderSelectionDialog after a user is done selecting folders to assign the
    // conversations to.
    @Override
    public final void assignFolder(Collection<FolderOperation> folderOps,
            Collection<Conversation> target, boolean batch, boolean showUndo,
            final boolean isMoveTo) {
        // Actions are destructive only when the current folder can be un-assigned from and
        // when the list of folders contains the current folder.
        final boolean isDestructive = mFolder
                .supportsCapability(FolderCapabilities.ALLOWS_REMOVE_CONVERSATION)
                && FolderOperation.isDestructive(folderOps, mFolder);
        LogUtils.d(LOG_TAG, "onFolderChangesCommit: isDestructive = %b", isDestructive);
        if (isDestructive) {
            for (final Conversation c : target) {
                c.localDeleteOnUpdate = true;
            }
        }
        final DestructiveAction folderChange;
        final UndoCallback undoCallback = isMoveTo ?
                getUndoCallbackForDestructiveActionsWithAutoAdvance(R.id.move_to,
                        mCurrentConversation)
                : null;
        // Update the UI elements depending no their visibility and availability
        // TODO(viki): Consolidate this into a single method requestDelete.
        if (isDestructive) {
            /*
             * If this is a MOVE operation, we want the action folder to be the destination folder.
             * Otherwise, we want it to be the current folder.
             *
             * A set of folder operations is a move if there are exactly two operations: an add and
             * a remove.
             */
            final Folder actionFolder;
            if (folderOps.size() != 2) {
                actionFolder = mFolder;
            } else {
                Folder addedFolder = null;
                boolean hasRemove = false;
                for (final FolderOperation folderOperation : folderOps) {
                    if (folderOperation.mAdd) {
                        addedFolder = folderOperation.mFolder;
                    } else {
                        hasRemove = true;
                    }
                }

                if (hasRemove && addedFolder != null) {
                    actionFolder = addedFolder;
                } else {
                    actionFolder = mFolder;
                }
            }

            folderChange = getDeferredFolderChange(target, folderOps, isDestructive,
                    batch, showUndo, isMoveTo, actionFolder, undoCallback);
            delete(0, target, folderChange, batch);
        } else {
            folderChange = getFolderChange(target, folderOps, isDestructive,
                    batch, showUndo, false /* isMoveTo */, mFolder, undoCallback);
            requestUpdate(folderChange);
        }
    }

    @Override
    public final void onRefreshRequired() {
        if (isAnimating()) {
            final ConversationListFragment f = getConversationListFragment();
            LogUtils.w(ConversationCursor.LOG_TAG,
                    "onRefreshRequired: delay until animating done. cursor=%s adapter=%s",
                    mConversationListCursor, (f != null) ? f.getAnimatedAdapter() : null);
            return;
        }
        // Refresh the query in the background
        if (mConversationListCursor.isRefreshRequired()) {
            mConversationListCursor.refresh();
        }
    }

    @Override
    public boolean isAnimating() {
        boolean isAnimating = false;
        ConversationListFragment convListFragment = getConversationListFragment();
        if (convListFragment != null) {
            isAnimating = convListFragment.isAnimating();
        }
        return isAnimating;
    }

    /**
     * Called when the {@link ConversationCursor} is changed or has new data in it.
     * <p>
     * {@inheritDoc}
     */
    @Override
    public final void onRefreshReady() {
        LogUtils.d(LOG_TAG, "Received refresh ready callback for folder %s",
                mFolder != null ? mFolder.id : "-1");

        if (mDestroyed) {
            LogUtils.i(LOG_TAG, "ignoring onRefreshReady on destroyed AAC");
            return;
        }

        if (!isAnimating()) {
            // Swap cursors
            mConversationListCursor.sync();
        } else {
            // (CLF guaranteed to be non-null due to check in isAnimating)
            LogUtils.w(LOG_TAG,
                    "AAC.onRefreshReady suppressing sync() due to animation. cursor=%s aa=%s",
                    mConversationListCursor, getConversationListFragment().getAnimatedAdapter());
        }
        mTracker.onCursorUpdated();
        perhapsShowFirstSearchResult();
    }

    @Override
    public final void onDataSetChanged() {
        updateConversationListFragment();
        mConversationListObservable.notifyChanged();
        mCheckedSet.validateAgainstCursor(mConversationListCursor);
    }

    /**
     * If the Conversation List Fragment is visible, updates the fragment.
     */
    private void updateConversationListFragment() {
        final ConversationListFragment convList = getConversationListFragment();
        if (convList != null) {
            refreshConversationList();
            if (isFragmentVisible(convList)) {
                informCursorVisiblity(true);
            }
        }
    }

    /**
     * This class handles throttled refresh of the conversation list
     */
    static class RefreshTimerTask extends TimerTask {
        final Handler mHandler;
        final AbstractActivityController mController;

        RefreshTimerTask(AbstractActivityController controller, Handler handler) {
            mHandler = handler;
            mController = controller;
        }

        @Override
        public void run() {
            mHandler.post(new Runnable() {
                @Override
                public void run() {
                    LogUtils.d(LOG_TAG, "Delay done... calling onRefreshRequired");
                    mController.onRefreshRequired();
                }});
        }
    }

    /**
     * Cancel the refresh task, if it's running
     */
    private void cancelRefreshTask () {
        if (mConversationListRefreshTask != null) {
            mConversationListRefreshTask.cancel();
            mConversationListRefreshTask = null;
        }
    }

    @Override
    public void onAnimationEnd(AnimatedAdapter animatedAdapter) {
        if (animatedAdapter != null) {
            LogUtils.i(LOG_TAG, "AAC.onAnimationEnd. cursor=%s adapter=%s", mConversationListCursor,
                    animatedAdapter);
        }
        if (mConversationListCursor == null) {
            LogUtils.e(LOG_TAG, "null ConversationCursor in onAnimationEnd");
            return;
        }
        if (mConversationListCursor.isRefreshReady()) {
            LogUtils.i(ConversationCursor.LOG_TAG, "Stopped animating: try sync");
            onRefreshReady();
        }

        if (mConversationListCursor.isRefreshRequired()) {
            LogUtils.i(ConversationCursor.LOG_TAG, "Stopped animating: refresh");
            mConversationListCursor.refresh();
        }
        if (mRecentsDataUpdated) {
            mRecentsDataUpdated = false;
            mRecentFolderObservers.notifyChanged();
        }
    }

    @Override
    public void onSetEmpty() {
        // There are no selected conversations. Ensure that the listener and its associated actions
        // are blanked out.
        setListener(null, -1);
    }

    @Override
    public void onSetPopulated(ConversationCheckedSet set) {
        mCabActionMenu = new SelectedConversationsActionMenu(mActivity, set, mFolder);
        if (mViewMode.isListMode() || (mIsTablet && mViewMode.isConversationMode())) {
            enableCabMode();
        }
    }

    @Override
    public void onSetChanged(ConversationCheckedSet set) {
        // Do nothing. We don't care about changes to the set.
    }

    @Override
    public ConversationCheckedSet getCheckedSet() {
        return mCheckedSet;
    }

    /**
     * Disable the Contextual Action Bar (CAB). The selected set is not changed.
     */
    protected void disableCabMode() {
        // Commit any previous destructive actions when entering/ exiting CAB mode.
        commitDestructiveActions(true);
        if (mCabActionMenu != null) {
            mCabActionMenu.deactivate();
        }
    }

    /**
     * Re-enable the CAB menu if required. The selection set is not changed.
     */
    protected void enableCabMode() {
        if (mCabActionMenu != null &&
                !(isDrawerEnabled() && mDrawerContainer.isDrawerOpen(mDrawerPullout))) {
            mCabActionMenu.activate();
        }
    }

    /**
     * Re-enable CAB mode only if we have an active selection
     */
    protected void maybeEnableCabMode() {
        if (!mCheckedSet.isEmpty()) {
            if (mCabActionMenu != null) {
                mCabActionMenu.activate();
            }
        }
    }

    /**
     * Unselect conversations and exit CAB mode.
     */
    protected final void exitCabMode() {
        mCheckedSet.clear();
    }

    @Override
    public void startSearch() {
        if (mAccount == null) {
            // We cannot search if there is no account. Drop the request to the floor.
            LogUtils.d(LOG_TAG, "AbstractActivityController.startSearch(): null account");
            return;
        }
        if (mAccount.supportsSearch()) {
            mSearchViewController.showSearchActionBar(
                    MaterialSearchViewController.SEARCH_VIEW_STATE_VISIBLE);
        } else {
            Toast.makeText(mActivity.getActivityContext(), mActivity.getActivityContext()
                    .getString(R.string.search_unsupported), Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (mToastBar != null && !mToastBar.isEventInToastBar(event)) {
                // if the toast bar is still animating, ignore this attempt to hide it
                if (mToastBar.isAnimating()) {
                    return;
                }

                // if the toast bar has not been seen long enough, ignore this attempt to hide it
                if (mToastBar.cannotBeHidden()) {
                    return;
                }

                // hide the toast bar
                mToastBar.hide(true /* animated */, false /* actionClicked */);
            }
        }
    }

    @Override
    public void onConversationSeen() {
        mPagerController.onConversationSeen();
    }

    @Override
    public boolean isInitialConversationLoading() {
        return mPagerController.isInitialConversationLoading();
    }

    /**
     * Check if the fragment given here is visible. Checking {@link Fragment#isVisible()} is
     * insufficient because that doesn't check if the window is currently in focus or not.
     */
    private boolean isFragmentVisible(Fragment in) {
        return in != null && in.isVisible() && mActivity.hasWindowFocus();
    }

    /**
     * This class handles callbacks that create a {@link ConversationCursor}.
     */
    private class ConversationListLoaderCallbacks implements
        LoaderManager.LoaderCallbacks<ConversationCursor> {

        @Override
        public Loader<ConversationCursor> onCreateLoader(int id, Bundle args) {
            final Account account = args.getParcelable(BUNDLE_ACCOUNT_KEY);
            final Folder folder = args.getParcelable(BUNDLE_FOLDER_KEY);
            final boolean ignoreInitialConversationLimit =
                    args.getBoolean(BUNDLE_IGNORE_INITIAL_CONVERSATION_LIMIT_KEY, false);
            if (account == null || folder == null) {
                return null;
            }
            return new ConversationCursorLoader(mActivity, account,
                    folder.conversationListUri, folder.getTypeDescription(),
                    ignoreInitialConversationLimit);
        }

        @Override
        public void onLoadFinished(Loader<ConversationCursor> loader, ConversationCursor data) {
            LogUtils.d(LOG_TAG,
                    "IN AAC.ConversationCursor.onLoadFinished, data=%s loader=%s this=%s",
                    data, loader, this);
            if (isDestroyed()) {
                return;
            }
            if (isDrawerEnabled() && mDrawerListener.getDrawerState() != DrawerLayout.STATE_IDLE) {
                LogUtils.d(LOG_TAG, "ConversationListLoaderCallbacks.onLoadFinished: ignoring.");
                mConversationListLoadFinishedIgnored = true;
                return;
            }
            // Clear our all pending destructive actions before swapping the conversation cursor
            destroyPending(null);
            mConversationListCursor = data;
            mConversationListCursor.addListener(AbstractActivityController.this);
            mDrawIdler.setListener(mConversationListCursor);
            mTracker.onCursorUpdated();
            mConversationListObservable.notifyChanged();
            // Handle actions that were deferred until after the conversation list was loaded.
            for (LoadFinishedCallback callback : mConversationListLoadFinishedCallbacks) {
                callback.onLoadFinished();
            }
            mConversationListLoadFinishedCallbacks.clear();

            final ConversationListFragment convList = getConversationListFragment();
            if (isFragmentVisible(convList)) {
                // The conversation list is already listening to list changes and gets notified
                // in the mConversationListObservable.notifyChanged() line above. We only need to
                // check and inform the cursor of the change in visibility here.
                informCursorVisiblity(true);
            }
            perhapsShowFirstSearchResult();
        }

        @Override
        public void onLoaderReset(Loader<ConversationCursor> loader) {
            LogUtils.d(LOG_TAG,
                    "IN AAC.ConversationCursor.onLoaderReset, data=%s loader=%s this=%s",
                    mConversationListCursor, loader, this);

            if (mConversationListCursor != null) {
                // Unregister the listener
                mConversationListCursor.removeListener(AbstractActivityController.this);
                mDrawIdler.setListener(null);
                mConversationListCursor = null;

                // Inform anyone who is interested about the change
                mTracker.onCursorUpdated();
                mConversationListObservable.notifyChanged();
            }
        }
    }

    /**
     * Class to perform {@link LoaderManager.LoaderCallbacks} for creating {@link Folder} objects.
     */
    private class FolderLoads implements LoaderManager.LoaderCallbacks<ObjectCursor<Folder>> {
        @Override
        public Loader<ObjectCursor<Folder>> onCreateLoader(int id, Bundle args) {
            final String[] everything = UIProvider.FOLDERS_PROJECTION;
            switch (id) {
                case LOADER_FOLDER_CURSOR:
                    LogUtils.d(LOG_TAG, "LOADER_FOLDER_CURSOR created");
                    final ObjectCursorLoader<Folder> loader = new
                            ObjectCursorLoader<Folder>(
                            mContext, mFolder.folderUri.fullUri, everything, Folder.FACTORY);
                    loader.setUpdateThrottle(mFolderItemUpdateDelayMs);
                    return loader;
                case LOADER_RECENT_FOLDERS:
                    LogUtils.d(LOG_TAG, "LOADER_RECENT_FOLDERS created");
                    if (mAccount != null && mAccount.recentFolderListUri != null
                            && !mAccount.recentFolderListUri.equals(Uri.EMPTY)) {
                        return new ObjectCursorLoader<Folder>(mContext,
                                mAccount.recentFolderListUri, everything, Folder.FACTORY);
                    }
                    break;
                case LOADER_ACCOUNT_INBOX:
                    LogUtils.d(LOG_TAG, "LOADER_ACCOUNT_INBOX created");
                    final Uri defaultInbox = Settings.getDefaultInboxUri(mAccount.settings);
                    final Uri inboxUri = defaultInbox.equals(Uri.EMPTY) ?
                            mAccount.folderListUri : defaultInbox;
                    LogUtils.d(LOG_TAG, "Loading the default inbox: %s", inboxUri);
                    if (inboxUri != null) {
                        return new ObjectCursorLoader<Folder>(mContext, inboxUri,
                                everything, Folder.FACTORY);
                    }
                    break;
                case LOADER_SEARCH:
                    LogUtils.d(LOG_TAG, "LOADER_SEARCH created");
                    return Folder.forSearchResults(mAccount,
                            args.getString(ConversationListContext.EXTRA_SEARCH_QUERY),
                            // We can just use current time as a unique identifier for this search
                            Long.toString(SystemClock.uptimeMillis()),
                            mActivity.getActivityContext());
                case LOADER_FIRST_FOLDER:
                    LogUtils.d(LOG_TAG, "LOADER_FIRST_FOLDER created");
                    final Uri folderUri = args.getParcelable(Utils.EXTRA_FOLDER_URI);
                    mConversationToShow = args.getParcelable(Utils.EXTRA_CONVERSATION);
                    if (mConversationToShow != null && mConversationToShow.position < 0){
                        mConversationToShow.position = 0;
                    }
                    return new ObjectCursorLoader<Folder>(mContext, folderUri,
                            everything, Folder.FACTORY);
                default:
                    LogUtils.wtf(LOG_TAG, "FolderLoads.onCreateLoader(%d) for invalid id", id);
                    return null;
            }
            return null;
        }

        @Override
        public void onLoadFinished(Loader<ObjectCursor<Folder>> loader, ObjectCursor<Folder> data) {
            if (data == null) {
                LogUtils.e(LOG_TAG, "Received null cursor from loader id: %d", loader.getId());
            }
            if (isDestroyed()) {
                return;
            }
            switch (loader.getId()) {
                case LOADER_FOLDER_CURSOR:
                    if (data != null && data.moveToFirst()) {
                        final Folder folder = data.getModel();
                        setHasFolderChanged(folder);
                        mFolder = folder;
                        mFolderObservable.notifyChanged();
                    } else {
                        LogUtils.d(LOG_TAG, "Unable to get the folder %s",
                                mFolder != null ? mFolder.name : "");
                    }
                    break;
                case LOADER_RECENT_FOLDERS:
                    // Few recent folders and we are running on a phone? Populate the default
                    // recents. The number of default recent folders is at least 2: every provider
                    // has at least two folders, and the recent folder count never decreases.
                    // Having a single recent folder is an erroneous case, and we can gracefully
                    // recover by populating default recents. The default recents will not stomp on
                    // the existing value: it will be shown in addition to the default folders:
                    // the max number of recent folders is more than 1+num(defaultRecents).
                    if (data != null && data.getCount() <= 1 && !mIsTablet) {
                        final class PopulateDefault extends AsyncTask<Uri, Void, Void> {
                            @Override
                            protected Void doInBackground(Uri... uri) {
                                // Asking for an update on the URI and ignore the result.
                                final ContentResolver resolver = mContext.getContentResolver();
                                resolver.update(uri[0], null, null, null);
                                return null;
                            }
                        }
                        final Uri uri = mAccount.defaultRecentFolderListUri;
                        LogUtils.v(LOG_TAG, "Default recents at %s", uri);
                        new PopulateDefault().execute(uri);
                        break;
                    }
                    LogUtils.v(LOG_TAG, "Reading recent folders from the cursor.");
                    mRecentFolderList.loadFromUiProvider(data);
                    if (isAnimating()) {
                        mRecentsDataUpdated = true;
                    } else {
                        mRecentFolderObservers.notifyChanged();
                    }
                    break;
                case LOADER_ACCOUNT_INBOX:
                    if (data != null && !data.isClosed() && data.moveToFirst()) {
                        final Folder inbox = data.getModel();
                        onFolderChanged(inbox, false /* force */);
                        // Just want to get the inbox, don't care about updates to it
                        // as this will be tracked by the folder change listener.
                        mActivity.getLoaderManager().destroyLoader(LOADER_ACCOUNT_INBOX);
                    } else {
                        LogUtils.d(LOG_TAG, "Unable to get the account inbox for account %s",
                                mAccount != null ? mAccount.getEmailAddress() : "");
                    }
                    break;
                case LOADER_SEARCH:
                    if (data != null && data.getCount() > 0) {
                        data.moveToFirst();
                        final Folder search = data.getModel();
                        updateFolder(search);
                        mConvListContext = ConversationListContext.forSearchQuery(mAccount, mFolder,
                                mActivity.getIntent()
                                        .getStringExtra(UIProvider.SearchQueryParameters.QUERY));
                        showConversationList(mConvListContext);
                        mActivity.invalidateOptionsMenu();
                        mHaveSearchResults = search.totalCount > 0;
                        mActivity.getLoaderManager().destroyLoader(LOADER_SEARCH);
                    } else {
                        LogUtils.e(LOG_TAG, "Null/empty cursor returned by LOADER_SEARCH loader");
                    }
                    break;
                case LOADER_FIRST_FOLDER:
                    if (data == null || data.getCount() <=0 || !data.moveToFirst()) {
                        return;
                    }
                    final Folder folder = data.getModel();
                    boolean handled = false;
                    if (folder != null) {
                        onFolderChanged(folder, false /* force */);
                        handled = true;
                    }
                    if (mConversationToShow != null) {
                        // Open the conversation.
                        showConversation(mConversationToShow);
                        handled = true;
                    }
                    if (!handled) {
                        // We have an account, but nothing else: load the default inbox.
                        loadAccountInbox();
                    }
                    mConversationToShow = null;
                    // And don't run this anymore.
                    mActivity.getLoaderManager().destroyLoader(LOADER_FIRST_FOLDER);
                    break;
            }
        }

        @Override
        public void onLoaderReset(Loader<ObjectCursor<Folder>> loader) {
        }
    }

    /**
     * Class to perform {@link LoaderManager.LoaderCallbacks} for creating {@link Account} objects.
     */
    private class AccountLoads implements LoaderManager.LoaderCallbacks<ObjectCursor<Account>> {
        final String[] mProjection = UIProvider.ACCOUNTS_PROJECTION;
        final CursorCreator<Account> mFactory = Account.FACTORY;

        @Override
        public Loader<ObjectCursor<Account>> onCreateLoader(int id, Bundle args) {
            switch (id) {
                case LOADER_ACCOUNT_CURSOR:
                    LogUtils.d(LOG_TAG,  "LOADER_ACCOUNT_CURSOR created");
                    return new ObjectCursorLoader<Account>(mContext,
                            MailAppProvider.getAccountsUri(), mProjection, mFactory);
                case LOADER_ACCOUNT_UPDATE_CURSOR:
                    LogUtils.d(LOG_TAG,  "LOADER_ACCOUNT_UPDATE_CURSOR created");
                    return new ObjectCursorLoader<Account>(mContext, mAccount.uri, mProjection,
                            mFactory);
                default:
                    LogUtils.wtf(LOG_TAG, "Got an id  (%d) that I cannot create!", id);
                    break;
            }
            return null;
        }

        @Override
        public void onLoadFinished(Loader<ObjectCursor<Account>> loader,
                ObjectCursor<Account> data) {
            if (data == null) {
                LogUtils.e(LOG_TAG, "Received null cursor from loader id: %d", loader.getId());
            }
            if (isDestroyed()) {
                return;
            }
            switch (loader.getId()) {
                case LOADER_ACCOUNT_CURSOR:
                    // We have received an update on the list of accounts.
                    if (data == null) {
                        // Nothing useful to do if we have no valid data.
                        break;
                    }
                    final long count = data.getCount();
                    if (count == 0) {
                        // If an empty cursor is returned, the MailAppProvider is indicating that
                        // no accounts have been specified.  We want to navigate to the
                        // "add account" activity that will handle the intent returned by the
                        // MailAppProvider

                        // If the MailAppProvider believes that all accounts have been loaded,
                        // and the account list is still empty, we want to prompt the user to add
                        // an account.
                        final Bundle extras = data.getExtras();
                        final boolean accountsLoaded =
                                extras.getInt(AccountCursorExtraKeys.ACCOUNTS_LOADED) != 0;

                        if (accountsLoaded) {
                            final Intent noAccountIntent = MailAppProvider.getNoAccountIntent
                                    (mContext);
                            if (noAccountIntent != null) {
                                mActivity.startActivityForResult(noAccountIntent,
                                        ADD_ACCOUNT_REQUEST_CODE);
                            }
                        }
                    } else {
                        final boolean accountListUpdated = accountsUpdated(data);
                        if (!mHaveAccountList || accountListUpdated) {
                            mHaveAccountList = updateAccounts(data);
                        }
                        Analytics.getInstance().setCustomDimension(Analytics.CD_INDEX_ACCOUNT_COUNT,
                                Long.toString(count));
                    }
                    break;
                case LOADER_ACCOUNT_UPDATE_CURSOR:
                    // We have received an update for current account.
                    if (data != null && data.moveToFirst()) {
                        final Account updatedAccount = data.getModel();
                        // Make sure that this is an update for the current account
                        if (updatedAccount.uri.equals(mAccount.uri)) {
                            final Settings previousSettings = mAccount.settings;

                            // Update the controller's reference to the current account
                            mAccount = updatedAccount;
                            LogUtils.d(LOG_TAG, "AbstractActivityController.onLoadFinished(): "
                                    + "mAccount = %s", mAccount.uri);

                            // Only notify about a settings change if something differs
                            if (!Objects.equal(mAccount.settings, previousSettings)) {
                                mAccountObservers.notifyChanged();
                            }
                            perhapsEnterWaitMode();
                        } else {
                            LogUtils.e(LOG_TAG, "Got update for account: %s with current account:"
                                    + " %s", updatedAccount.uri, mAccount.uri);
                            // We need to restart the loader, so the correct account information
                            // will be returned.
                            restartOptionalLoader(LOADER_ACCOUNT_UPDATE_CURSOR, this, Bundle.EMPTY);
                        }
                    }
                    break;
            }
        }

        @Override
        public void onLoaderReset(Loader<ObjectCursor<Account>> loader) {
            // Do nothing. In onLoadFinished() we copy the relevant data from the cursor.
        }
    }

    /**
     * Updates controller state based on search results and shows first conversation if required.
     */
    private void perhapsShowFirstSearchResult() {
        if (mCurrentConversation == null) {
            // Shown for search results in two-pane mode only.
            mHaveSearchResults = Intent.ACTION_SEARCH.equals(mActivity.getIntent().getAction())
                    && mConversationListCursor.getCount() > 0;
            if (!shouldShowFirstConversation()) {
                return;
            }
            mConversationListCursor.moveToPosition(0);
            final Conversation conv = new Conversation(mConversationListCursor);
            conv.position = 0;
            onConversationSelected(conv, true /* checkSafeToModifyFragments */);
        }
    }

    /**
     * Destroy the pending {@link DestructiveAction} till now and assign the given action as the
     * next destructive action..
     * @param nextAction the next destructive action to be performed. This can be null.
     */
    private void destroyPending(DestructiveAction nextAction) {
        // If there is a pending action, perform that first.
        if (mPendingDestruction != null) {
            mPendingDestruction.performAction();
        }
        mPendingDestruction = nextAction;
    }

    /**
     * Register a destructive action with the controller. This performs the previous destructive
     * action as a side effect. This method is final because we don't want the child classes to
     * embellish this method any more.
     * @param action the action to register.
     */
    private void registerDestructiveAction(DestructiveAction action) {
        // TODO(viki): This is not a good idea. The best solution is for clients to request a
        // destructive action from the controller and for the controller to own the action. This is
        // a half-way solution while refactoring DestructiveAction.
        destroyPending(action);
    }

    @Override
    public final DestructiveAction getBatchAction(int action, UndoCallback undoCallback) {
        final DestructiveAction da = new ConversationAction(action, mCheckedSet.values(), true);
        da.setUndoCallback(undoCallback);
        registerDestructiveAction(da);
        return da;
    }

    @Override
    public final DestructiveAction getDeferredBatchAction(int action, UndoCallback undoCallback) {
        return getDeferredAction(action, mCheckedSet.values(), true, undoCallback);
    }

    /**
     * Get a destructive action for a menu action. This is a temporary method,
     * to control the profusion of {@link DestructiveAction} classes that are
     * created. Please do not copy this paradigm.
     * @param action the resource ID of the menu action: R.id.delete, for
     *            example
     * @param target the conversations to act upon.
     * @return a {@link DestructiveAction} that performs the specified action.
     */
    private DestructiveAction getDeferredAction(int action, Collection<Conversation> target,
            boolean batch, UndoCallback callback) {
        ConversationAction cAction = new ConversationAction(action, target, batch);
        cAction.setUndoCallback(callback);
        return cAction;
    }

    /**
     * Class to change the folders that are assigned to a set of conversations. This is destructive
     * because the user can remove the current folder from the conversation, in which case it has
     * to be animated away from the current folder.
     */
    private class FolderDestruction implements DestructiveAction {
        private final Collection<Conversation> mTarget;
        private final ArrayList<FolderOperation> mFolderOps = new ArrayList<FolderOperation>();
        private final boolean mIsDestructive;
        /** Whether this destructive action has already been performed */
        private boolean mCompleted;
        private final boolean mIsSelectedSet;
        private final boolean mShowUndo;
        private final int mAction;
        private final Folder mActionFolder;

        private UndoCallback mUndoCallback;

        /**
         * Create a new folder destruction object to act on the given conversations.
         * @param target conversations to act upon.
         * @param actionFolder the {@link Folder} being acted upon, used for displaying the undo bar
         */
        private FolderDestruction(final Collection<Conversation> target,
                final Collection<FolderOperation> folders, boolean isDestructive, boolean isBatch,
                boolean showUndo, int action, final Folder actionFolder) {
            mTarget = ImmutableList.copyOf(target);
            mFolderOps.addAll(folders);
            mIsDestructive = isDestructive;
            mIsSelectedSet = isBatch;
            mShowUndo = showUndo;
            mAction = action;
            mActionFolder = actionFolder;
        }

        @Override
        public void setUndoCallback(UndoCallback undoCallback) {
            mUndoCallback = undoCallback;
        }

        @Override
        public void performAction() {
            if (isPerformed()) {
                return;
            }
            if (mIsDestructive && mShowUndo && mTarget.size() > 0) {
                ToastBarOperation undoOp = new ToastBarOperation(mTarget.size(), mAction,
                        ToastBarOperation.UNDO, mIsSelectedSet, mActionFolder);
                onUndoAvailable(undoOp);
            }
            // For each conversation, for each operation, add/ remove the
            // appropriate folders.
            ArrayList<ConversationOperation> ops = new ArrayList<ConversationOperation>();
            ArrayList<Uri> folderUris;
            ArrayList<Boolean> adds;
            for (Conversation target : mTarget) {
                HashMap<Uri, Folder> targetFolders = Folder.hashMapForFolders(target
                        .getRawFolders());
                folderUris = new ArrayList<Uri>();
                adds = new ArrayList<Boolean>();
                if (mIsDestructive) {
                    target.localDeleteOnUpdate = true;
                }
                for (FolderOperation op : mFolderOps) {
                    folderUris.add(op.mFolder.folderUri.fullUri);
                    adds.add(op.mAdd ? Boolean.TRUE : Boolean.FALSE);
                    if (op.mAdd) {
                        targetFolders.put(op.mFolder.folderUri.fullUri, op.mFolder);
                    } else {
                        targetFolders.remove(op.mFolder.folderUri.fullUri);
                    }
                }
                ops.add(mConversationListCursor.getConversationFolderOperation(target,
                        folderUris, adds, targetFolders.values(), mUndoCallback));
            }
            if (mConversationListCursor != null) {
                mConversationListCursor.updateBulkValues(ops);
            }
            refreshConversationList();
            if (mIsSelectedSet) {
                mCheckedSet.clear();
            }
        }

        /**
         * Returns true if this action has been performed, false otherwise.
         *
         */
        private synchronized boolean isPerformed() {
            if (mCompleted) {
                return true;
            }
            mCompleted = true;
            return false;
        }
    }

    public final DestructiveAction getFolderChange(Collection<Conversation> target,
            Collection<FolderOperation> folders, boolean isDestructive, boolean isBatch,
            boolean showUndo, final boolean isMoveTo, final Folder actionFolder,
            UndoCallback undoCallback) {
        final DestructiveAction da = getDeferredFolderChange(target, folders, isDestructive,
                isBatch, showUndo, isMoveTo, actionFolder, undoCallback);
        registerDestructiveAction(da);
        return da;
    }

    public final DestructiveAction getDeferredFolderChange(Collection<Conversation> target,
            Collection<FolderOperation> folders, boolean isDestructive, boolean isBatch,
            boolean showUndo, final boolean isMoveTo, final Folder actionFolder,
            UndoCallback undoCallback) {
        final DestructiveAction fd = new FolderDestruction(target, folders, isDestructive, isBatch,
                showUndo, isMoveTo ? R.id.move_folder : R.id.change_folders, actionFolder);
        fd.setUndoCallback(undoCallback);
        return fd;
    }

    @Override
    public final DestructiveAction getDeferredRemoveFolder(Collection<Conversation> target,
            Folder toRemove, boolean isDestructive, boolean isBatch,
            boolean showUndo, UndoCallback undoCallback) {
        Collection<FolderOperation> folderOps = new ArrayList<FolderOperation>();
        folderOps.add(new FolderOperation(toRemove, false));
        final DestructiveAction da = new FolderDestruction(target, folderOps, isDestructive, isBatch,
                showUndo, R.id.remove_folder, mFolder);
        da.setUndoCallback(undoCallback);
        return da;
    }

    @Override
    public final void refreshConversationList() {
        final ConversationListFragment convList = getConversationListFragment();
        if (convList == null) {
            return;
        }
        convList.requestListRefresh();
    }

    protected final ActionClickedListener getUndoClickedListener(
            final AnimatedAdapter listAdapter) {
        return new ActionClickedListener() {
            @Override
            public void onActionClicked(Context context) {
                if (mAccount.undoUri != null) {
                    // NOTE: We might want undo to return the messages affected, in which case
                    // the resulting cursor might be interesting...
                    // TODO: Use UIProvider.SEQUENCE_QUERY_PARAMETER to indicate the set of
                    // commands to undo
                    if (mConversationListCursor != null) {
                        mConversationListCursor.undo(
                                mActivity.getActivityContext(), mAccount.undoUri);
                    }
                    if (listAdapter != null) {
                        listAdapter.setUndo(true);
                    }
                }
            }
        };
    }

    /**
     * Shows an error toast in the bottom when a folder was not fetched successfully.
     * @param folder the folder which could not be fetched.
     * @param replaceVisibleToast if true, this should replace any currently visible toast.
     */
    protected final void showErrorToast(final Folder folder, boolean replaceVisibleToast) {

        final ActionClickedListener listener;
        final int actionTextResourceId;
        final int lastSyncResult = folder.lastSyncResult;
        switch (lastSyncResult & 0x0f) {
            case UIProvider.LastSyncResult.CONNECTION_ERROR:
                // The sync request that caused this failure.
                final int syncRequest = lastSyncResult >> 4;
                // Show: User explicitly pressed the refresh button and there is no connection
                // Show: The first time the user enters the app and there is no connection
                //       TODO(viki): Implement this.
                // Reference: http://b/7202801
                final boolean showToast = (syncRequest & UIProvider.SyncStatus.USER_REFRESH) != 0;
                // Don't show: Already in the app; user switches to a synced label
                // Don't show: In a live label and a background sync fails
                final boolean avoidToast = !showToast && (folder.syncWindow > 0
                        || (syncRequest & UIProvider.SyncStatus.BACKGROUND_SYNC) != 0);
                if (avoidToast) {
                    return;
                }
                listener = getRetryClickedListener(folder);
                actionTextResourceId = R.string.retry;
                break;
            case UIProvider.LastSyncResult.AUTH_ERROR:
                listener = getSignInClickedListener();
                actionTextResourceId = R.string.signin;
                break;
            case UIProvider.LastSyncResult.SECURITY_ERROR:
                return; // Currently we do nothing for security errors.
            case UIProvider.LastSyncResult.STORAGE_ERROR:
                listener = getStorageErrorClickedListener();
                actionTextResourceId = R.string.info;
                break;
            case UIProvider.LastSyncResult.INTERNAL_ERROR:
                listener = getInternalErrorClickedListener();
                actionTextResourceId = R.string.report;
                break;
            default:
                return;
        }
        mToastBar.show(listener,
                Utils.getSyncStatusText(mActivity.getActivityContext(), lastSyncResult),
                actionTextResourceId,
                replaceVisibleToast,
                true /* autohide */,
                new ToastBarOperation(1, 0, ToastBarOperation.ERROR, false, folder));
    }

    private ActionClickedListener getRetryClickedListener(final Folder folder) {
        return new ActionClickedListener() {
            @Override
            public void onActionClicked(Context context) {
                final Uri uri = folder.refreshUri;

                if (uri != null) {
                    startAsyncRefreshTask(uri);
                }
            }
        };
    }

    private ActionClickedListener getSignInClickedListener() {
        return new ActionClickedListener() {
            @Override
            public void onActionClicked(Context context) {
                promptUserForAuthentication(mAccount);
            }
        };
    }

    private ActionClickedListener getStorageErrorClickedListener() {
        return new ActionClickedListener() {
            @Override
            public void onActionClicked(Context context) {
                showStorageErrorDialog();
            }
        };
    }

    private void showStorageErrorDialog() {
        DialogFragment fragment = (DialogFragment)
                mFragmentManager.findFragmentByTag(SYNC_ERROR_DIALOG_FRAGMENT_TAG);
        if (fragment == null) {
            fragment = SyncErrorDialogFragment.newInstance();
        }
        fragment.show(mFragmentManager, SYNC_ERROR_DIALOG_FRAGMENT_TAG);
    }

    private ActionClickedListener getInternalErrorClickedListener() {
        return new ActionClickedListener() {
            @Override
            public void onActionClicked(Context context) {
                Utils.sendFeedback(mActivity, mAccount, true /* reportingProblem */);
            }
        };
    }

    @Override
    public void onFooterViewErrorActionClick(Folder folder, int errorStatus) {
        Uri uri = null;
        switch (errorStatus) {
            case UIProvider.LastSyncResult.CONNECTION_ERROR:
                if (folder != null && folder.refreshUri != null) {
                    uri = folder.refreshUri;
                }
                break;
            case UIProvider.LastSyncResult.AUTH_ERROR:
                promptUserForAuthentication(mAccount);
                return;
            case UIProvider.LastSyncResult.SECURITY_ERROR:
                return; // Currently we do nothing for security errors.
            case UIProvider.LastSyncResult.STORAGE_ERROR:
                showStorageErrorDialog();
                return;
            case UIProvider.LastSyncResult.INTERNAL_ERROR:
                Utils.sendFeedback(mActivity, mAccount, true /* reportingProblem */);
                return;
            default:
                return;
        }

        if (uri != null) {
            startAsyncRefreshTask(uri);
        }
    }

    @Override
    public void onFooterViewLoadMoreClick(Folder folder) {
        if (folder != null && folder.loadMoreUri != null) {
            startAsyncRefreshTask(folder.loadMoreUri);
        }
    }

    private void startAsyncRefreshTask(Uri uri) {
        if (mFolderSyncTask != null) {
            mFolderSyncTask.cancel(true);
        }
        mFolderSyncTask = new AsyncRefreshTask(mActivity.getActivityContext(), uri);
        mFolderSyncTask.execute();
    }

    private void promptUserForAuthentication(Account account) {
        if (account != null && !Utils.isEmpty(account.reauthenticationIntentUri)) {
            final Intent authenticationIntent =
                    new Intent(Intent.ACTION_VIEW, account.reauthenticationIntentUri);
            mActivity.startActivityForResult(authenticationIntent, REAUTHENTICATE_REQUEST_CODE);
        }
    }

    @Override
    public void onAccessibilityStateChanged() {
        // Clear the cache of objects.
        ConversationItemViewModel.onAccessibilityUpdated();
        // Re-render the list if it exists.
        final ConversationListFragment frag = getConversationListFragment();
        if (frag != null) {
            AnimatedAdapter adapter = frag.getAnimatedAdapter();
            if (adapter != null) {
                adapter.notifyDataSetInvalidated();
            }
        }
    }

    @Override
    public void makeDialogListener (final int action, final boolean isBatch,
            UndoCallback undoCallback) {
        final Collection<Conversation> target;
        if (isBatch) {
            target = mCheckedSet.values();
        } else {
            LogUtils.d(LOG_TAG, "Will act upon %s", mCurrentConversation);
            target = Conversation.listOf(mCurrentConversation);
        }
        final DestructiveAction destructiveAction = getDeferredAction(action, target, isBatch,
                undoCallback);
        mDialogAction = action;
        mDialogFromSelectedSet = isBatch;
        mDialogListener = new AlertDialog.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int which) {
                delete(action, target, destructiveAction, isBatch);
                // Afterwards, let's remove references to the listener and the action.
                setListener(null, -1);
            }
        };
    }

    @Override
    public AlertDialog.OnClickListener getListener() {
        return mDialogListener;
    }

    /**
     * Sets the listener for the positive action on a confirmation dialog.  Since only a single
     * confirmation dialog can be shown, this overwrites the previous listener.  It is safe to
     * unset the listener; in which case action should be set to -1.
     * @param listener the listener that will perform the task for this dialog's positive action.
     * @param action the action that created this dialog.
     */
    private void setListener(AlertDialog.OnClickListener listener, final int action){
        mDialogListener = listener;
        mDialogAction = action;
    }

    @Override
    public VeiledAddressMatcher getVeiledAddressMatcher() {
        return mVeiledMatcher;
    }

    @Override
    public void setDetachedMode() {
        // Tell the conversation list not to select anything.
        final ConversationListFragment frag = getConversationListFragment();
        if (frag != null) {
            frag.setChoiceNone();
        } else if (mIsTablet) {
            // How did we ever land here? Detached mode, and no CLF on tablet???
            LogUtils.e(LOG_TAG, "AAC.setDetachedMode(): CLF = null!");
        }
        mDetachedConvUri = mCurrentConversation.uri;
    }

    private void clearDetachedMode() {
        // Tell the conversation list to go back to its usual selection behavior.
        final ConversationListFragment frag = getConversationListFragment();
        if (frag != null) {
            frag.revertChoiceMode();
        } else if (mIsTablet) {
            // How did we ever land here? Detached mode, and no CLF on tablet???
            LogUtils.e(LOG_TAG, "AAC.clearDetachedMode(): CLF = null on tablet!");
        }
        mDetachedConvUri = null;
    }

    @Override
    public boolean shouldPreventListSwipesEntirely() {
        return false;
    }

    @Override
    public DrawerController getDrawerController() {
        return mDrawerListener;
    }

    private class MailDrawerListener extends Observable<DrawerLayout.DrawerListener>
            implements DrawerLayout.DrawerListener, DrawerController {
        private int mDrawerState;
        private float mOldSlideOffset;

        public MailDrawerListener() {
            mDrawerState = DrawerLayout.STATE_IDLE;
            mOldSlideOffset = 0.f;
        }

        @Override
        public boolean isDrawerEnabled() {
            return AbstractActivityController.this.isDrawerEnabled();
        }

        @Override
        public void registerDrawerListener(DrawerLayout.DrawerListener l) {
            registerObserver(l);
        }

        @Override
        public void unregisterDrawerListener(DrawerLayout.DrawerListener l) {
            unregisterObserver(l);
        }

        @Override
        public boolean isDrawerOpen() {
            return isDrawerEnabled() && mDrawerContainer.isDrawerOpen(mDrawerPullout);
        }

        @Override
        public boolean isDrawerVisible() {
            return isDrawerEnabled() && mDrawerContainer.isDrawerVisible(mDrawerPullout);
        }

        @Override
        public void toggleDrawerState() {
            AbstractActivityController.this.toggleDrawerState();
        }

        @Override
        public void onDrawerOpened(View drawerView) {
            mDrawerToggle.onDrawerOpened(drawerView);

            for (DrawerLayout.DrawerListener l : mObservers) {
                l.onDrawerOpened(drawerView);
            }
        }

        @Override
        public void onDrawerClosed(View drawerView) {
            mDrawerToggle.onDrawerClosed(drawerView);
            if (mHasNewAccountOrFolder) {
                refreshDrawer();
            }

            // When closed, we want to use either the burger, or up, based on where we are
            final int mode = mViewMode.getMode();
            final boolean isTopLevel = Folder.isRoot(mFolder);
            mDrawerToggle.setDrawerIndicatorEnabled(getShouldShowDrawerIndicator(mode, isTopLevel));

            for (DrawerLayout.DrawerListener l : mObservers) {
                l.onDrawerClosed(drawerView);
            }
        }

        /**
         * As part of the overriden function, it will animate the alpha of the conversation list
         * view along with the drawer sliding when we're in the process of switching accounts or
         * folders. Note, this is the same amount of work done as {@link ValueAnimator#ofFloat}.
         */
        @Override
        public void onDrawerSlide(View drawerView, float slideOffset) {
            mDrawerToggle.onDrawerSlide(drawerView, slideOffset);
            if (mHasNewAccountOrFolder && mListViewForAnimating != null) {
                mListViewForAnimating.setAlpha(slideOffset);
            }

            // This code handles when to change the visibility of action items
            // based on drawer state. The basic logic is that right when we
            // open the drawer, we hide the action items. We show the action items
            // when the drawer closes. However, due to the animation of the drawer closing,
            // to make the reshowing of the action items feel right, we make the items visible
            // slightly sooner.
            //
            // However, to make the animating behavior work properly, we have to know whether
            // we're animating open or closed. Only if we're animating closed do we want to
            // show the action items early. We save the last slide offset so that we can compare
            // the current slide offset to it to determine if we're opening or closing.
            if (mDrawerState == DrawerLayout.STATE_SETTLING) {
                if (mHideMenuItems && slideOffset < 0.15f && mOldSlideOffset > slideOffset) {
                    mHideMenuItems = false;
                    mActivity.supportInvalidateOptionsMenu();
                    maybeEnableCabMode();
                } else if (!mHideMenuItems && slideOffset > 0.f && mOldSlideOffset < slideOffset) {
                    mHideMenuItems = true;
                    mActivity.supportInvalidateOptionsMenu();
                    disableCabMode();
                }
            } else {
                if (mHideMenuItems && Float.compare(slideOffset, 0.f) == 0) {
                    mHideMenuItems = false;
                    mActivity.supportInvalidateOptionsMenu();
                    maybeEnableCabMode();
                } else if (!mHideMenuItems && slideOffset > 0.f) {
                    mHideMenuItems = true;
                    mActivity.supportInvalidateOptionsMenu();
                    disableCabMode();
                }
            }

            mOldSlideOffset = slideOffset;

            // If we're sliding, we always want to show the burger
            mDrawerToggle.setDrawerIndicatorEnabled(true /* enable */);

            for (DrawerLayout.DrawerListener l : mObservers) {
                l.onDrawerSlide(drawerView, slideOffset);
            }
        }

        /**
         * This condition here should only be called when the drawer is stuck in a weird state
         * and doesn't register the onDrawerClosed, but shows up as idle. Make sure to refresh
         * and, more importantly, unlock the drawer when this is the case.
         */
        @Override
        public void onDrawerStateChanged(int newState) {
            LogUtils.d(LOG_TAG, "AAC onDrawerStateChanged %d", newState);
            mDrawerState = newState;
            mDrawerToggle.onDrawerStateChanged(mDrawerState);

            for (DrawerLayout.DrawerListener l : mObservers) {
                l.onDrawerStateChanged(newState);
            }

            if (mViewMode.isSearchMode()) {
                return;
            }
            if (mDrawerState == DrawerLayout.STATE_IDLE) {
                if (mHasNewAccountOrFolder) {
                    refreshDrawer();
                }
                if (mConversationListLoadFinishedIgnored) {
                    mConversationListLoadFinishedIgnored = false;
                    final Bundle args = new Bundle();
                    args.putParcelable(BUNDLE_ACCOUNT_KEY, mAccount);
                    args.putParcelable(BUNDLE_FOLDER_KEY, mFolder);
                    mActivity.getLoaderManager().initLoader(
                            LOADER_CONVERSATION_LIST, args, mListCursorCallbacks);
                }
            }
        }

        /**
         * If we've reached a stable drawer state, unlock the drawer for usage, clear the
         * conversation list, and finish end actions. Also, make
         * {@link #mHasNewAccountOrFolder} false to reflect we're done changing.
         */
        public void refreshDrawer() {
            mHasNewAccountOrFolder = false;
            mDrawerContainer.setDrawerLockMode(DrawerLayout.LOCK_MODE_UNLOCKED);
            ConversationListFragment conversationList = getConversationListFragment();
            if (conversationList != null) {
                conversationList.clear();
            }
            mFolderOrAccountObservers.notifyChanged();
        }

        /**
         * Returns the most recent update of the {@link DrawerLayout}'s state provided
         * by {@link #onDrawerStateChanged(int)}.
         * @return The {@link DrawerLayout}'s current state. One of
         * {@link DrawerLayout#STATE_DRAGGING}, {@link DrawerLayout#STATE_IDLE},
         * or {@link DrawerLayout#STATE_SETTLING}.
         */
        public int getDrawerState() {
            return mDrawerState;
        }
    }

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

    @Override
    public boolean shouldHideMenuItems() {
        return mHideMenuItems;
    }

    protected void navigateUpFolderHierarchy() {
        new AsyncTask<Void, Void, Folder>() {
            @Override
            protected Folder doInBackground(final Void... params) {
                if (mInbox == null) {
                    // We don't have an inbox, but we need it
                    final Cursor cursor = mContext.getContentResolver().query(
                            mAccount.settings.defaultInbox, UIProvider.FOLDERS_PROJECTION, null,
                            null, null);

                    if (cursor != null) {
                        try {
                            if (cursor.moveToFirst()) {
                                mInbox = new Folder(cursor);
                            }
                        } finally {
                            cursor.close();
                        }
                    }
                }

                // Now try to load our parent
                final Folder folder;

                if (mFolder != null) {
                    Cursor cursor = null;
                    try {
                        cursor = mContext.getContentResolver().query(mFolder.parent,
                                UIProvider.FOLDERS_PROJECTION, null, null, null);

                        if (cursor == null || !cursor.moveToFirst()) {
                            // We couldn't load the parent, so use the inbox
                            folder = mInbox;
                        } else {
                            folder = new Folder(cursor);
                        }
                    } finally {
                        if (cursor != null) {
                            cursor.close();
                        }
                    }
                } else {
                    folder = mInbox;
                }

                return folder;
            }

            @Override
            protected void onPostExecute(final Folder result) {
                onFolderSelected(result);
            }
        }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, (Void[]) null);
    }

    @Override
    public Parcelable getConversationListScrollPosition(final String folderUri) {
        return mConversationListScrollPositions.getParcelable(folderUri);
    }

    @Override
    public void setConversationListScrollPosition(final String folderUri,
            final Parcelable savedPosition) {
        mConversationListScrollPositions.putParcelable(folderUri, savedPosition);
    }

    @Override
    public View.OnClickListener getNavigationViewClickListener() {
        return mHomeButtonListener;
    }

    // TODO: Fold this into the outer class when b/16627877 is fixed
    private class HomeButtonListener implements View.OnClickListener {
        @Override
        public void onClick(View v) {
            handleUpPress();
        }
    }
}
