/*
 * Copyright (C) 2010 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.email.activity.setup;

import android.app.ActionBar;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
import android.database.ContentObserver;
import android.database.Cursor;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceActivity;
import android.text.TextUtils;
import android.text.SpannableString;
import android.text.method.LinkMovementMethod;
import android.text.util.Linkify;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;

import com.android.email.R;
import com.android.email.activity.ActivityHelper;
import com.android.email.provider.EmailProvider;
import com.android.emailcommon.Logging;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent.AccountColumns;
import com.android.emailcommon.utility.IntentUtilities;
import com.android.emailcommon.utility.Utility;
import com.android.mail.providers.Folder;
import com.android.mail.providers.UIProvider.EditSettingsExtras;
import com.android.mail.ui.FeedbackEnabledActivity;
import com.android.mail.utils.LogUtils;
import com.android.mail.utils.Utils;

import java.util.List;

/**
 * Handles account preferences, using multi-pane arrangement when possible.
 *
 * This activity uses the following fragments:
 *   AccountSettingsFragment
 *   Account{Incoming/Outgoing}Fragment
 *   AccountCheckSettingsFragment
 *   GeneralPreferences
 *   DebugFragment
 *
 * TODO: Delete account - on single-pane view (phone UX) the account list doesn't update properly
 * TODO: Handle dynamic changes to the account list (exit if necessary).  It probably makes
 *       sense to use a loader for the accounts list, because it would provide better support for
 *       dealing with accounts being added/deleted and triggering the header reload.
 */
public class AccountSettings extends PreferenceActivity implements FeedbackEnabledActivity,
        SetupDataFragment.SetupDataContainer {
    /*
     * Intent to open account settings for account=1
        adb shell am start -a android.intent.action.EDIT \
            -d '"content://ui.email.android.com/settings?ACCOUNT_ID=1"'
     */

    // Intent extras for our internal activity launch
    private static final String EXTRA_ENABLE_DEBUG = "AccountSettings.enable_debug";
    private static final String EXTRA_LOGIN_WARNING_FOR_ACCOUNT = "AccountSettings.for_account";
    private static final String EXTRA_LOGIN_WARNING_REASON_FOR_ACCOUNT =
            "AccountSettings.for_account_reason";
    private static final String EXTRA_TITLE = "AccountSettings.title";
    public static final String EXTRA_NO_ACCOUNTS = "AccountSettings.no_account";

    // Intent extras for launch directly from system account manager
    // NOTE: This string must match the one in res/xml/account_preferences.xml
    private static String INTENT_ACCOUNT_MANAGER_ENTRY;
    // NOTE: This constant should eventually be defined in android.accounts.Constants
    private static final String EXTRA_ACCOUNT_MANAGER_ACCOUNT = "account";

    // Key for arguments bundle for QuickResponse editing
    private static final String QUICK_RESPONSE_ACCOUNT_KEY = "account";

    // Key codes used to open a debug settings fragment.
    private static final int[] SECRET_KEY_CODES = {
            KeyEvent.KEYCODE_D, KeyEvent.KEYCODE_E, KeyEvent.KEYCODE_B, KeyEvent.KEYCODE_U,
            KeyEvent.KEYCODE_G
            };
    private int mSecretKeyCodeIndex = 0;

    // Support for account-by-name lookup
    private static final String SELECTION_ACCOUNT_EMAIL_ADDRESS =
        AccountColumns.EMAIL_ADDRESS + "=?";

    // When the user taps "Email Preferences" 10 times in a row, we'll enable the debug settings.
    private int mNumGeneralHeaderClicked = 0;

    private long mRequestedAccountId;
    private Header[] mAccountListHeaders;
    private Header mAppPreferencesHeader;
    /* package */ Fragment mCurrentFragment;
    private long mDeletingAccountId = -1;
    private boolean mShowDebugMenu;
    private List<Header> mGeneratedHeaders;
    private Uri mFeedbackUri;
    private MenuItem mFeedbackMenuItem;

    private SetupDataFragment mSetupData;

    // Async Tasks
    private LoadAccountListTask mLoadAccountListTask;
    private GetAccountIdFromAccountTask mGetAccountIdFromAccountTask;
    private ContentObserver mAccountObserver;

    // Specific callbacks used by settings fragments
    private final AccountSettingsFragmentCallback mAccountSettingsFragmentCallback
            = new AccountSettingsFragmentCallback();
    private final AccountServerSettingsFragmentCallback mAccountServerSettingsFragmentCallback
            = new AccountServerSettingsFragmentCallback();

    /**
     * Display (and edit) settings for a specific account, or -1 for any/all accounts
     */
    public static void actionSettings(Activity fromActivity, long accountId) {
        fromActivity.startActivity(createAccountSettingsIntent(accountId, null, null));
    }

    /**
     * Create and return an intent to display (and edit) settings for a specific account, or -1
     * for any/all accounts.  If an account name string is provided, a warning dialog will be
     * displayed as well.
     */
    public static Intent createAccountSettingsIntent(long accountId,
            String loginWarningAccountName, String loginWarningReason) {
        final Uri.Builder b = IntentUtilities.createActivityIntentUrlBuilder(
                IntentUtilities.PATH_SETTINGS);
        IntentUtilities.setAccountId(b, accountId);
        final Intent i = new Intent(Intent.ACTION_EDIT, b.build());
        if (loginWarningAccountName != null) {
            i.putExtra(EXTRA_LOGIN_WARNING_FOR_ACCOUNT, loginWarningAccountName);
        }
        if (loginWarningReason != null) {
            i.putExtra(EXTRA_LOGIN_WARNING_REASON_FOR_ACCOUNT, loginWarningReason);
        }
        return i;
    }

    @Override
    public Intent getIntent() {
        final Intent intent = super.getIntent();
        final long accountId = IntentUtilities.getAccountIdFromIntent(intent);
        if (accountId < 0) {
            return intent;
        }
        Intent modIntent = new Intent(intent);
        modIntent.putExtra(EXTRA_SHOW_FRAGMENT, AccountSettingsFragment.class.getCanonicalName());
        modIntent.putExtra(
                EXTRA_SHOW_FRAGMENT_ARGUMENTS,
                AccountSettingsFragment.buildArguments(
                        accountId, IntentUtilities.getAccountNameFromIntent(intent)));
        modIntent.putExtra(EXTRA_NO_HEADERS, true);
        return modIntent;
    }


    /**
     * Launch generic settings and pre-enable the debug preferences
     */
    public static void actionSettingsWithDebug(Context fromContext) {
        final Intent i = new Intent(fromContext, AccountSettings.class);
        i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        i.putExtra(EXTRA_ENABLE_DEBUG, true);
        fromContext.startActivity(i);
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        ActivityHelper.debugSetWindowFlags(this);

        final Intent i = getIntent();
        if (savedInstanceState == null) {
            // If we are not restarting from a previous instance, we need to
            // figure out the initial prefs to show.  (Otherwise, we want to
            // continue showing whatever the user last selected.)
            if (INTENT_ACCOUNT_MANAGER_ENTRY == null) {
                INTENT_ACCOUNT_MANAGER_ENTRY = getString(R.string.intent_account_manager_entry);
            }
            if (INTENT_ACCOUNT_MANAGER_ENTRY.equals(i.getAction())) {
                // This case occurs if we're changing account settings from Settings -> Accounts
                mGetAccountIdFromAccountTask =
                        (GetAccountIdFromAccountTask) new GetAccountIdFromAccountTask()
                        .executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, i);
            } else if (i.hasExtra(EditSettingsExtras.EXTRA_FOLDER)) {
                launchMailboxSettings(i);
                return;
            } else if (i.hasExtra(EXTRA_NO_ACCOUNTS)) {
                AccountSetupBasics.actionNewAccountWithResult(this);
                finish();
                return;
            } else {
                // Otherwise, we're called from within the Email app and look for our extras
                mRequestedAccountId = IntentUtilities.getAccountIdFromIntent(i);
                String loginWarningAccount = i.getStringExtra(EXTRA_LOGIN_WARNING_FOR_ACCOUNT);
                String loginWarningReason =
                        i.getStringExtra(EXTRA_LOGIN_WARNING_REASON_FOR_ACCOUNT);
                if (loginWarningAccount != null) {
                    // Show dialog (first time only - don't re-show on a rotation)
                    LoginWarningDialog dialog =
                            LoginWarningDialog.newInstance(loginWarningAccount, loginWarningReason);
                    dialog.show(getFragmentManager(), "loginwarning");
                }
            }
        } else {
            mSetupData = savedInstanceState.getParcelable(SetupDataFragment.EXTRA_SETUP_DATA);
        }
        mShowDebugMenu = i.getBooleanExtra(EXTRA_ENABLE_DEBUG, false);

        final String title = i.getStringExtra(EXTRA_TITLE);
        if (title != null) {
            setTitle(title);
        }

        getActionBar().setDisplayOptions(
                ActionBar.DISPLAY_HOME_AS_UP, ActionBar.DISPLAY_HOME_AS_UP);

        mAccountObserver = new ContentObserver(Utility.getMainThreadHandler()) {
            @Override
            public void onChange(boolean selfChange) {
                updateAccounts();
            }
        };

        mFeedbackUri = Utils.getValidUri(getString(R.string.email_feedback_uri));
    }

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(
                outState);
        // TODO: use the fragment manager to persist this
        outState.putParcelable(SetupDataFragment.EXTRA_SETUP_DATA, mSetupData);
    }

    @Override
    public void onResume() {
        super.onResume();
        getContentResolver().registerContentObserver(Account.NOTIFIER_URI, true, mAccountObserver);
        updateAccounts();
    }

    @Override
    public void onPause() {
        super.onPause();
        getContentResolver().unregisterContentObserver(mAccountObserver);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Utility.cancelTaskInterrupt(mLoadAccountListTask);
        mLoadAccountListTask = null;
        Utility.cancelTaskInterrupt(mGetAccountIdFromAccountTask);
        mGetAccountIdFromAccountTask = null;
    }

    /**
     * Listen for secret sequence and, if heard, enable debug menu
     */
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        if (event.getKeyCode() == SECRET_KEY_CODES[mSecretKeyCodeIndex]) {
            mSecretKeyCodeIndex++;
            if (mSecretKeyCodeIndex == SECRET_KEY_CODES.length) {
                mSecretKeyCodeIndex = 0;
                enableDebugMenu();
            }
        } else {
            mSecretKeyCodeIndex = 0;
        }
        return super.onKeyDown(keyCode, event);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        super.onCreateOptionsMenu(menu);
        getMenuInflater().inflate(R.menu.settings_menu, menu);

        mFeedbackMenuItem = menu.findItem(R.id.feedback_menu_item);
        return true;
    }

    @Override
    public boolean onPrepareOptionsMenu(Menu menu) {
        super.onPrepareOptionsMenu(menu);

        if (mFeedbackMenuItem != null) {
            // We only want to enable the feedback menu item, if there is a valid feedback uri
            mFeedbackMenuItem.setVisible(!Uri.EMPTY.equals(mFeedbackUri));
        }
        return true;
    }


    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                // The app icon on the action bar is pressed.  Just emulate a back press.
                // TODO: this should navigate to the main screen, even if a sub-setting is open.
                // But we shouldn't just finish(), as we want to show "discard changes?" dialog
                // when necessary.
                onBackPressed();
                break;
            case R.id.add_new_account:
                onAddNewAccount();
                break;
            case R.id.feedback_menu_item:
                Utils.sendFeedback(this, mFeedbackUri, false /* reportingProblem */);
                break;
            default:
                return super.onOptionsItemSelected(item);
        }
        return true;
    }

    public boolean isValidFragment(String fragmentName) {
        // We need to make sure that a fragment about to be attached is valid. This corrects
        // a security vulnerability.
        return (TextUtils.equals(AccountSettingsFragment.class.getName(), fragmentName) ||
                TextUtils.equals(GeneralPreferences.class.getName(), fragmentName) ||
                super.isValidFragment(fragmentName));
    }

    @Override
    public Intent onBuildStartFragmentIntent(String fragmentName, Bundle args,
            int titleRes, int shortTitleRes) {
        final Intent intent = super.onBuildStartFragmentIntent(
                fragmentName, args, titleRes, shortTitleRes);

        // When opening a sub-settings page (e.g. account specific page), see if we want to modify
        // the activity title.
        String title = AccountSettingsFragment.getTitleFromArgs(args);
        if ((titleRes == 0) && (title != null)) {
            intent.putExtra(EXTRA_TITLE, title);
        }
        return intent;
    }

    /**
     * Any time we exit via this pathway, and we are showing a server settings fragment,
     * we put up the exit-save-changes dialog.  This will work for the following cases:
     *   Cancel button
     *   Back button
     *   Up arrow in application icon
     * It will *not* apply in the following cases:
     *   Click the parent breadcrumb - need to find a hook for this
     *   Click in the header list (e.g. another account) - handled elsewhere
     */
    @Override
    public void onBackPressed() {
        if (mCurrentFragment instanceof AccountServerBaseFragment) {
            if (((AccountServerBaseFragment) mCurrentFragment).haveSettingsChanged()) {
                UnsavedChangesDialogFragment dialogFragment =
                        UnsavedChangesDialogFragment.newInstanceForBack();
                dialogFragment.show(getFragmentManager(), UnsavedChangesDialogFragment.TAG);
                return; // Prevent "back" from being handled
            }
        }
        super.onBackPressed();
    }

    private void launchMailboxSettings(Intent intent) {
        final Folder folder = intent.getParcelableExtra(EditSettingsExtras.EXTRA_FOLDER);

        // TODO: determine from the account if we should navigate to the mailbox settings.
        // See bug 6242668

        // Get the mailbox id from the folder
        final long mailboxId =
                Long.parseLong(folder.folderUri.fullUri.getPathSegments().get(1));

        MailboxSettings.start(this, mailboxId);
        finish();
    }


    private void enableDebugMenu() {
        mShowDebugMenu = true;
        invalidateHeaders();
    }

    private void onAddNewAccount() {
        AccountSetupBasics.actionNewAccount(this);
    }

    /**
     * Start the async reload of the accounts list (if the headers are being displayed)
     */
    private void updateAccounts() {
        if (hasHeaders()) {
            Utility.cancelTaskInterrupt(mLoadAccountListTask);
            mLoadAccountListTask = (LoadAccountListTask)
                    new LoadAccountListTask().executeOnExecutor(
                            AsyncTask.THREAD_POOL_EXECUTOR, mDeletingAccountId);
        }
    }

    /**
     * Write the current header (accounts) array into the one provided by the PreferenceActivity.
     * Skip any headers that match mDeletingAccountId (this is a quick-hide algorithm while a
     * background thread works on deleting the account).  Also sets mRequestedAccountHeader if
     * we find the requested account (by id).
     */
    @Override
    public void onBuildHeaders(List<Header> target) {
        // Always add app preferences as first header
        target.clear();
        target.add(getAppPreferencesHeader());

        // Then add zero or more account headers as necessary
        if (mAccountListHeaders != null) {
            final int headerCount = mAccountListHeaders.length;
            for (int index = 0; index < headerCount; index++) {
                Header header = mAccountListHeaders[index];
                if (header != null && header.id != HEADER_ID_UNDEFINED) {
                    if (header.id != mDeletingAccountId) {
                        target.add(header);
                        if (header.id == mRequestedAccountId) {
                            mRequestedAccountId = -1;
                        }
                    }
                }
            }
        }

        // finally, if debug header is enabled, show it
        if (mShowDebugMenu) {
            // setup lightweight header for debugging
            final Header debugHeader = new Header();
            debugHeader.title = getText(R.string.debug_title);
            debugHeader.summary = null;
            debugHeader.iconRes = 0;
            debugHeader.fragment = DebugFragment.class.getCanonicalName();
            debugHeader.fragmentArguments = null;
            target.add(debugHeader);
        }

        // Save for later use (see forceSwitch)
        mGeneratedHeaders = target;
    }

    /**
     * Generate and return the first header, for app preferences
     */
    private Header getAppPreferencesHeader() {
        // Set up fixed header for general settings
        if (mAppPreferencesHeader == null) {
            mAppPreferencesHeader = new Header();
            mAppPreferencesHeader.title = getText(R.string.header_label_general_preferences);
            mAppPreferencesHeader.summary = null;
            mAppPreferencesHeader.iconRes = 0;
            mAppPreferencesHeader.fragment = GeneralPreferences.class.getCanonicalName();
            mAppPreferencesHeader.fragmentArguments = null;
        }
        return mAppPreferencesHeader;
    }

    /**
     * This AsyncTask reads the accounts list and generates the headers.  When the headers are
     * ready, we'll trigger PreferenceActivity to refresh the account list with them.
     *
     * The array generated and stored in mAccountListHeaders may be sparse so any readers should
     * check for and skip over null entries, and should not assume array length is # of accounts.
     *
     * TODO: Smaller projection
     * TODO: Convert to Loader
     * TODO: Write a test, including operation of deletingAccountId param
     */
    private class LoadAccountListTask extends AsyncTask<Long, Void, Object[]> {

        @Override
        protected Object[] doInBackground(Long... params) {
            Header[] result = null;
            Boolean deletingAccountFound = false;
            final long deletingAccountId = params[0];

            Cursor c = getContentResolver().query(
                    Account.CONTENT_URI,
                    Account.CONTENT_PROJECTION, null, null, null);
            try {
                int index = 0;
                result = new Header[c.getCount()];

                while (c.moveToNext()) {
                    final long accountId = c.getLong(Account.CONTENT_ID_COLUMN);
                    if (accountId == deletingAccountId) {
                        deletingAccountFound = true;
                        continue;
                    }
                    final String name = c.getString(Account.CONTENT_DISPLAY_NAME_COLUMN);
                    final String email = c.getString(Account.CONTENT_EMAIL_ADDRESS_COLUMN);
                    final Header newHeader = new Header();
                    newHeader.id = accountId;
                    newHeader.title = name;
                    newHeader.summary = email;
                    newHeader.fragment = AccountSettingsFragment.class.getCanonicalName();
                    newHeader.fragmentArguments =
                            AccountSettingsFragment.buildArguments(accountId, email);

                    result[index++] = newHeader;
                }
            } finally {
                if (c != null) {
                    c.close();
                }
            }
            return new Object[] { result, deletingAccountFound };
        }

        @Override
        protected void onPostExecute(Object[] result) {
            if (isCancelled() || result == null) return;
            // Extract the results
            final Header[] headers = (Header[]) result[0];
            final boolean deletingAccountFound = (Boolean) result[1];
            // report the settings
            mAccountListHeaders = headers;
            invalidateHeaders();
            if (!deletingAccountFound) {
                mDeletingAccountId = -1;
            }
        }
    }

    /**
     * Called when the user selects an item in the header list.  Handles save-data cases as needed
     *
     * @param header The header that was selected.
     * @param position The header's position in the list.
     */
    @Override
    public void onHeaderClick(Header header, int position) {
        // special case when exiting the server settings fragments
        if ((mCurrentFragment instanceof AccountServerBaseFragment)
                && (((AccountServerBaseFragment)mCurrentFragment).haveSettingsChanged())) {
            UnsavedChangesDialogFragment dialogFragment =
                UnsavedChangesDialogFragment.newInstanceForHeader(position);
            dialogFragment.show(getFragmentManager(), UnsavedChangesDialogFragment.TAG);
            return;
        }

        // Secret keys:  Click 10x to enable debug settings
        if (position == 0) {
            mNumGeneralHeaderClicked++;
            if (mNumGeneralHeaderClicked == 10) {
                enableDebugMenu();
            }
        } else {
            mNumGeneralHeaderClicked = 0;
        }

        // Process header click normally
        super.onHeaderClick(header, position);
    }

    /**
     * Switch to a specific header without checking for server settings fragments as done
     * in {@link #onHeaderClick(Header, int)}.  Called after we interrupted a header switch
     * with a dialog, and the user OK'd it.
     */
    private void forceSwitchHeader(int position) {
        // Clear the current fragment; we're navigating away
        mCurrentFragment = null;
        // Ensure the UI visually shows the correct header selected
        setSelection(position);
        switchToHeader(mGeneratedHeaders.get(position));
    }

    /**
     * Forcefully go backward in the stack. This may potentially discard unsaved settings.
     */
    private void forceBack() {
        // Clear the current fragment; we're navigating away
        mCurrentFragment = null;
        onBackPressed();
    }

    @Override
    public void onAttachFragment(Fragment f) {
        super.onAttachFragment(f);

        if (f instanceof AccountSettingsFragment) {
            final AccountSettingsFragment asf = (AccountSettingsFragment) f;
            asf.setCallback(mAccountSettingsFragmentCallback);
        } else if (f instanceof AccountServerBaseFragment) {
            final AccountServerBaseFragment asbf = (AccountServerBaseFragment) f;
            asbf.setCallback(mAccountServerSettingsFragmentCallback);
        } else {
            // Possibly uninteresting fragment, such as a dialog.
            return;
        }
        mCurrentFragment = f;

        // When we're changing fragments, enable/disable the add account button
        invalidateOptionsMenu();
    }

    /**
     * Callbacks for AccountSettingsFragment
     */
    private class AccountSettingsFragmentCallback implements AccountSettingsFragment.Callback {
        @Override
        public void onSettingsChanged(Account account, String preference, Object value) {
            AccountSettings.this.onSettingsChanged(account, preference, value);
        }
        @Override
        public void onEditQuickResponses(com.android.mail.providers.Account account) {
            AccountSettings.this.onEditQuickResponses(account);
        }
        @Override
        public void onIncomingSettings(Account account) {
            AccountSettings.this.onIncomingSettings(account);
        }
        @Override
        public void onOutgoingSettings(Account account) {
            AccountSettings.this.onOutgoingSettings(account);
        }
        @Override
        public void abandonEdit() {
            finish();
        }
    }

    /**
     * Callbacks for AccountServerSettingsFragmentCallback
     */
    private class AccountServerSettingsFragmentCallback
            implements AccountServerBaseFragment.Callback {
        @Override
        public void onEnableProceedButtons(boolean enable) {
            // This is not used - it's a callback for the legacy activities
        }

        @Override
        public void onProceedNext(int checkMode, AccountServerBaseFragment target) {
            AccountCheckSettingsFragment checkerFragment =
                AccountCheckSettingsFragment.newInstance(checkMode, target);
            startPreferenceFragment(checkerFragment, true);
        }

        /**
         * After verifying a new server configuration as OK, we return here and continue.  This
         * simply does a "back" to exit the settings screen.
         */
        @Override
        public void onCheckSettingsComplete(int result, SetupDataFragment setupData) {
            if (result == AccountCheckSettingsFragment.CHECK_SETTINGS_OK) {
                // Settings checked & saved; clear current fragment
                mCurrentFragment = null;
                onBackPressed();
            }
        }
    }

    /**
     * Some of the settings have changed. Update internal state as necessary.
     */
    public void onSettingsChanged(Account account, String preference, Object value) {
        if (AccountSettingsFragment.PREFERENCE_DESCRIPTION.equals(preference)) {
            for (Header header : mAccountListHeaders) {
                if (header.id == account.mId) {
                    // Manually tweak the header title. We cannot rebuild the header list from
                    // an account cursor as the account database has not been saved yet.
                    header.title = value.toString();
                    invalidateHeaders();
                    break;
                }
            }
        }
    }

    /**
     * Dispatch to edit quick responses.
     */
    public void onEditQuickResponses(com.android.mail.providers.Account account) {
        try {
            final Bundle args = new Bundle(1);
            args.putParcelable(QUICK_RESPONSE_ACCOUNT_KEY, account);
            startPreferencePanel(AccountSettingsEditQuickResponsesFragment.class.getName(), args,
                    R.string.account_settings_edit_quick_responses_label, null, null, 0);
        } catch (Exception e) {
            LogUtils.d(Logging.LOG_TAG, "Error while trying to invoke edit quick responses.", e);
        }
    }

    /**
     * Dispatch to edit incoming settings.
     */
    public void onIncomingSettings(Account account) {
        try {
            mSetupData = new SetupDataFragment(SetupDataFragment.FLOW_MODE_EDIT, account);
            final Fragment f = new AccountSetupIncomingFragment();
            f.setArguments(AccountSetupIncomingFragment.getArgs(true));
            // Use startPreferenceFragment here because we need to keep this activity instance
            startPreferenceFragment(f, true);
        } catch (Exception e) {
            LogUtils.d(Logging.LOG_TAG, "Error while trying to invoke store settings.", e);
        }
    }

    /**
     * Dispatch to edit outgoing settings.
     *
     * TODO: Make things less hardwired
     */
    public void onOutgoingSettings(Account account) {
        try {
            mSetupData = new SetupDataFragment(SetupDataFragment.FLOW_MODE_EDIT, account);
            final Fragment f = new AccountSetupOutgoingFragment();
            f.setArguments(AccountSetupOutgoingFragment.getArgs(true));
            // Use startPreferenceFragment here because we need to keep this activity instance
            startPreferenceFragment(f, true);
        } catch (Exception e) {
            LogUtils.d(Logging.LOG_TAG, "Error while trying to invoke sender settings.", e);
        }
    }

    /**
     * Delete the selected account
     */
    public void deleteAccount(final Account account) {
        // Kick off the work to actually delete the account
        new Thread(new Runnable() {
            @Override
            public void run() {
                final Uri uri = EmailProvider.uiUri("uiaccount", account.mId);
                getContentResolver().delete(uri, null, null);
            }}).start();

        // TODO: Remove ui glue for unified
        // Then update the UI as appropriate:
        // If single pane, return to the header list.  If multi, rebuild header list
        if (onIsMultiPane()) {
            final Header prefsHeader = getAppPreferencesHeader();
            this.switchToHeader(prefsHeader.fragment, prefsHeader.fragmentArguments);
            mDeletingAccountId = account.mId;
            updateAccounts();
        } else {
            // We should only be calling this while showing AccountSettingsFragment,
            // so a finish() should bring us back to headers.  No point hiding the deleted account.
            finish();
        }
    }

    /**
     * This AsyncTask looks up an account based on its email address (which is what we get from
     * the Account Manager).  When the account id is determined, we refresh the header list,
     * which will select the preferences for that account.
     */
    private class GetAccountIdFromAccountTask extends AsyncTask<Intent, Void, Long> {

        @Override
        protected Long doInBackground(Intent... params) {
            final Intent intent = params[0];
            android.accounts.Account acct =
                intent.getParcelableExtra(EXTRA_ACCOUNT_MANAGER_ACCOUNT);
            return Utility.getFirstRowLong(AccountSettings.this, Account.CONTENT_URI,
                    Account.ID_PROJECTION, SELECTION_ACCOUNT_EMAIL_ADDRESS,
                    new String[] {acct.name}, null, Account.ID_PROJECTION_COLUMN, -1L);
        }

        @Override
        protected void onPostExecute(Long accountId) {
            if (accountId != -1 && !isCancelled()) {
                mRequestedAccountId = accountId;
                invalidateHeaders();
            }
        }
    }

    /**
     * Dialog fragment to show "exit with unsaved changes?" dialog
     */
    public static class UnsavedChangesDialogFragment extends DialogFragment {
        final static String TAG = "UnsavedChangesDialogFragment";

        // Argument bundle keys
        private final static String BUNDLE_KEY_HEADER = "UnsavedChangesDialogFragment.Header";
        private final static String BUNDLE_KEY_BACK = "UnsavedChangesDialogFragment.Back";

        /**
         * Creates a save changes dialog when the user selects a new header
         * @param position The new header index to make active if the user accepts the dialog. This
         * must be a valid header index although there is no error checking.
         */
        public static UnsavedChangesDialogFragment newInstanceForHeader(int position) {
            final UnsavedChangesDialogFragment f = new UnsavedChangesDialogFragment();
            final Bundle b = new Bundle(1);
            b.putInt(BUNDLE_KEY_HEADER, position);
            f.setArguments(b);
            return f;
        }

        /**
         * Creates a save changes dialog when the user navigates "back".
         * {@link #onBackPressed()} defines in which case this may be triggered.
         */
        public static UnsavedChangesDialogFragment newInstanceForBack() {
            final UnsavedChangesDialogFragment f = new UnsavedChangesDialogFragment();
            final Bundle b = new Bundle(1);
            b.putBoolean(BUNDLE_KEY_BACK, true);
            f.setArguments(b);
            return f;
        }

        // Force usage of newInstance()
        public UnsavedChangesDialogFragment() {}

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            final AccountSettings activity = (AccountSettings) getActivity();
            final int position = getArguments().getInt(BUNDLE_KEY_HEADER);
            final boolean isBack = getArguments().getBoolean(BUNDLE_KEY_BACK);

            return new AlertDialog.Builder(activity)
                .setIconAttribute(android.R.attr.alertDialogIcon)
                .setTitle(android.R.string.dialog_alert_title)
                .setMessage(R.string.account_settings_exit_server_settings)
                .setPositiveButton(
                        R.string.okay_action,
                        new DialogInterface.OnClickListener() {
                            @Override
                            public void onClick(DialogInterface dialog, int which) {
                                if (isBack) {
                                    activity.forceBack();
                                } else {
                                    activity.forceSwitchHeader(position);
                                }
                                dismiss();
                            }
                        })
                .setNegativeButton(
                        activity.getString(R.string.cancel_action), null)
                .create();
        }
    }

    /**
     * Dialog briefly shown in some cases, to indicate the user that login failed.  If the user
     * clicks OK, we simply dismiss the dialog, leaving the user in the account settings for
     * that account;  If the user clicks "cancel", we exit account settings.
     */
    public static class LoginWarningDialog extends DialogFragment
            implements DialogInterface.OnClickListener {
        private static final String BUNDLE_KEY_ACCOUNT_NAME = "account_name";
        private String mReason;

        // Public no-args constructor needed for fragment re-instantiation
        public LoginWarningDialog() {}

        /**
         * Create a new dialog.
         */
        public static LoginWarningDialog newInstance(String accountName, String reason) {
            final LoginWarningDialog dialog = new LoginWarningDialog();
            final Bundle b = new Bundle(1);
            b.putString(BUNDLE_KEY_ACCOUNT_NAME, accountName);
            dialog.setArguments(b);
            dialog.mReason = reason;
            return dialog;
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            final String accountName = getArguments().getString(BUNDLE_KEY_ACCOUNT_NAME);

            final Context context = getActivity();
            final Resources res = context.getResources();
            final AlertDialog.Builder b = new AlertDialog.Builder(context);
            b.setTitle(R.string.account_settings_login_dialog_title);
            b.setIconAttribute(android.R.attr.alertDialogIcon);
            if (mReason != null) {
                final TextView message = new TextView(context);
                final String alert = res.getString(
                        R.string.account_settings_login_dialog_reason_fmt, accountName, mReason);
                SpannableString spannableAlertString = new SpannableString(alert);
                Linkify.addLinks(spannableAlertString, Linkify.WEB_URLS);
                message.setText(spannableAlertString);
                // There must be a better way than specifying size/padding this way
                // It does work and look right, though
                final int textSize = res.getDimensionPixelSize(R.dimen.dialog_text_size);
                message.setTextSize(textSize);
                final int paddingLeft = res.getDimensionPixelSize(R.dimen.dialog_padding_left);
                final int paddingOther = res.getDimensionPixelSize(R.dimen.dialog_padding_other);
                message.setPadding(paddingLeft, paddingOther, paddingOther, paddingOther);
                message.setMovementMethod(LinkMovementMethod.getInstance());
                b.setView(message);
            } else {
                b.setMessage(res.getString(R.string.account_settings_login_dialog_content_fmt,
                        accountName));
            }
            b.setPositiveButton(R.string.okay_action, this);
            b.setNegativeButton(R.string.cancel_action, this);
            return b.create();
        }

        @Override
        public void onClick(DialogInterface dialog, int which) {
            dismiss();
            if (which == DialogInterface.BUTTON_NEGATIVE) {
                getActivity().finish();
            }
        }
    }

    @Override
    public Context getActivityContext() {
        return this;
    }

    @Override
    public SetupDataFragment getSetupData() {
        return mSetupData;
    }

    @Override
    public void setSetupData(SetupDataFragment setupData) {
        mSetupData = setupData;
    }
}
