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

        // Menu items that are targetted, only perform if there actually is a target.
        boolean handled = false;
        if (target.size() > 0) {
            handled = true;
            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(target, 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 == R.id.move_to || id == R.id.change_folders) {
                final FolderSelectionDialog dialog = FolderSelectionDialog.getInstance(mAccount,
                        target, 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, target, true, true /* showUndo */, false /* isMoveTo */);
                    }
                }.execute((Void[]) null);
            } else {
                handled = false;
            }
        }

        // Not handled by the targetted menu items, check the general ones.
        if (!handled) {
            handled = true;
            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.toggle_drawer) {
                toggleDrawerState();
            } 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.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;
            }
        }

        // If the controller didn't handle this event, check the CAB menu if it's active.
        // This is necessary because keyboard shortcuts don't seem to check CAB menus.
        if (!handled && mCabActionMenu != null && mCabActionMenu.isActivated() &&
                    mCabActionMenu.onActionItemClicked(item)) {
            handled = true;
        }

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