/*
 * Copyright (C) 2014 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.accounts.AccountAuthenticatorResponse;
import android.accounts.AccountManager;
import android.app.ActionBar;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.Dialog;
import android.app.DialogFragment;
import android.app.Fragment;
import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.app.LoaderManager;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.CursorLoader;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.Loader;
import android.database.Cursor;
import android.os.Bundle;
import android.provider.ContactsContract;
import android.support.annotation.NonNull;
import android.text.TextUtils;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.Toast;

import com.android.email.R;
import com.android.email.activity.RequestPermissionsActivity;
import com.android.email.setup.AuthenticatorSetupIntentHelper;
import com.android.email.service.EmailServiceUtils;
import com.android.emailcommon.VendorPolicyLoader;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.HostAuth;
import com.android.emailcommon.service.SyncWindow;
import com.android.mail.analytics.Analytics;
import com.android.mail.providers.MailAppProvider;
import com.android.mail.providers.UIProvider;
import com.android.mail.utils.LogUtils;

import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;

public class AccountSetupFinal extends AccountSetupActivity
        implements AccountFinalizeFragment.Callback,
        AccountSetupNoteDialogFragment.Callback, AccountCreationFragment.Callback,
        AccountCheckSettingsFragment.Callback, SecurityRequiredDialogFragment.Callback,
        CheckSettingsErrorDialogFragment.Callback, CheckSettingsProgressDialogFragment.Callback,
        AccountSetupTypeFragment.Callback, AccountSetupNamesFragment.Callback,
        AccountSetupOptionsFragment.Callback, AccountSetupBasicsFragment.Callback,
        AccountServerBaseFragment.Callback, AccountSetupCredentialsFragment.Callback,
        DuplicateAccountDialogFragment.Callback, AccountSetupABFragment.Callback {

    /**
     * Direct access for forcing account creation
     * For use by continuous automated test system (e.g. in conjunction with monkey tests)
     *
     * === Support for automated testing ==
     * This activity can also be launched directly via INTENT_FORCE_CREATE_ACCOUNT. This is intended
     * only for use by continuous test systems, and is currently only available when
     * {@link ActivityManager#isRunningInTestHarness()} is set.  To use this mode, you must
     * construct an intent which contains all necessary information to create the account.  No
     * connection checking is done, so the account may or may not actually work.  Here is a sample
     * command, for a gmail account "test_account" with a password of "test_password".
     *
     *      $ adb shell am start -a com.android.email.FORCE_CREATE_ACCOUNT \
     *          -e EMAIL test_account@gmail.com \
     *          -e USER "Test Account Name" \
     *          -e INCOMING imap+ssl+://test_account:test_password@imap.gmail.com \
     *          -e OUTGOING smtp+ssl+://test_account:test_password@smtp.gmail.com
     *
     * Note: For accounts that require the full email address in the login, encode the @ as %40.
     * Note: Exchange accounts that require device security policies cannot be created
     * automatically.
     *
     * For accounts that correspond to services in providers.xml you can also use the following form
     *
     *      $adb shell am start -a com.android.email.FORCE_CREATE_ACCOUNT \
     *          -e EMAIL test_account@gmail.com \
     *          -e PASSWORD test_password
     *
     * and the appropriate incoming/outgoing information will be filled in automatically.
     */
    private static String INTENT_FORCE_CREATE_ACCOUNT;
    private static final String EXTRA_CREATE_ACCOUNT_EMAIL = "EMAIL";
    private static final String EXTRA_CREATE_ACCOUNT_USER = "USER";
    private static final String EXTRA_CREATE_ACCOUNT_PASSWORD = "PASSWORD";
    private static final String EXTRA_CREATE_ACCOUNT_INCOMING = "INCOMING";
    private static final String EXTRA_CREATE_ACCOUNT_OUTGOING = "OUTGOING";
    private static final String EXTRA_CREATE_ACCOUNT_SYNC_LOOKBACK = "SYNC_LOOKBACK";

    private static final String CREATE_ACCOUNT_SYNC_ALL_VALUE = "ALL";

    private static final Boolean DEBUG_ALLOW_NON_TEST_HARNESS_CREATION = false;

    protected static final String ACTION_JUMP_TO_INCOMING = "jumpToIncoming";
    protected static final String ACTION_JUMP_TO_OUTGOING = "jumpToOutgoing";
    protected static final String ACTION_JUMP_TO_OPTIONS = "jumpToOptions";

    private static final String SAVESTATE_KEY_IS_PROCESSING = "AccountSetupFinal.is_processing";
    private static final String SAVESTATE_KEY_STATE = "AccountSetupFinal.state";
    private static final String SAVESTATE_KEY_PROVIDER = "AccountSetupFinal.provider";
    private static final String SAVESTATE_KEY_AUTHENTICATOR_RESPONSE = "AccountSetupFinal.authResp";
    private static final String SAVESTATE_KEY_REPORT_AUTHENTICATOR_ERROR =
            "AccountSetupFinal.authErr";
    private static final String SAVESTATE_KEY_IS_PRE_CONFIGURED = "AccountSetupFinal.preconfig";
    private static final String SAVESTATE_KEY_SKIP_AUTO_DISCOVER = "AccountSetupFinal.noAuto";
    private static final String SAVESTATE_KEY_PASSWORD_FAILED = "AccountSetupFinal.passwordFailed";

    private static final String CONTENT_FRAGMENT_TAG = "AccountSetupContentFragment";
    private static final String CREDENTIALS_BACKSTACK_TAG = "AccountSetupCredentialsFragment";

    // Collecting initial email and password
    private static final int STATE_BASICS = 0;
    // Show the user some interstitial message after email entry
    private static final int STATE_BASICS_POST = 1;
    // Account is not pre-configured, query user for account type
    private static final int STATE_TYPE = 2;
    // Account is pre-configured, but the user picked a different protocol
    private static final int STATE_AB = 3;
    // Collect initial password or oauth token
    private static final int STATE_CREDENTIALS = 4;
    // Account is a pre-configured account, run the checker
    private static final int STATE_CHECKING_PRECONFIGURED = 5;
    // Auto-discovering exchange account info, possibly other protocols later
    private static final int STATE_AUTO_DISCOVER = 6;
    // User is entering incoming settings
    private static final int STATE_MANUAL_INCOMING = 7;
    // We're checking incoming settings
    private static final int STATE_CHECKING_INCOMING = 8;
    // User is entering outgoing settings
    private static final int STATE_MANUAL_OUTGOING = 9;
    // We're checking outgoing settings
    private static final int STATE_CHECKING_OUTGOING = 10;
    // User is entering sync options
    private static final int STATE_OPTIONS = 11;
    // We're creating the account
    private static final int STATE_CREATING = 12;
    // User is entering account name and real name
    private static final int STATE_NAMES = 13;
    // we're finalizing the account
    private static final int STATE_FINALIZE = 14;

    private int mState = STATE_BASICS;

    private boolean mIsProcessing = false;
    private boolean mForceCreate = false;
    private boolean mReportAccountAuthenticatorError;
    private AccountAuthenticatorResponse mAccountAuthenticatorResponse;
    // True if this provider is found in our providers.xml, set after Basics
    private boolean mIsPreConfiguredProvider = false;
    // True if the user selected manual setup
    private boolean mSkipAutoDiscover = false;
    // True if validating the pre-configured provider failed and we want manual setup
    private boolean mPreConfiguredFailed = false;

    private VendorPolicyLoader.Provider mProvider;
    private boolean mPasswordFailed;

    private static final int OWNER_NAME_LOADER_ID = 0;
    private String mOwnerName;

    private static final int EXISTING_ACCOUNTS_LOADER_ID = 1;
    private Map<String, String> mExistingAccountsMap;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        if (RequestPermissionsActivity.startPermissionActivity(this)) {
            finish();
        }
        super.onCreate(savedInstanceState);

        final Intent intent = getIntent();
        final String action = intent.getAction();

        if (INTENT_FORCE_CREATE_ACCOUNT == null) {
            INTENT_FORCE_CREATE_ACCOUNT = getString(R.string.intent_force_create_email_account);
        }

        setContentView(R.layout.account_setup_activity);

        final ActionBar actionBar = getActionBar();
        if (actionBar != null) {
            // Hide the app icon.
            actionBar.setIcon(android.R.color.transparent);
            actionBar.setDisplayUseLogoEnabled(false);
        }

        if (savedInstanceState != null) {
            mIsProcessing = savedInstanceState.getBoolean(SAVESTATE_KEY_IS_PROCESSING, false);
            mState = savedInstanceState.getInt(SAVESTATE_KEY_STATE, STATE_OPTIONS);
            mProvider = (VendorPolicyLoader.Provider)
                    savedInstanceState.getSerializable(SAVESTATE_KEY_PROVIDER);
            mAccountAuthenticatorResponse =
                    savedInstanceState.getParcelable(SAVESTATE_KEY_AUTHENTICATOR_RESPONSE);
            mReportAccountAuthenticatorError =
                    savedInstanceState.getBoolean(SAVESTATE_KEY_REPORT_AUTHENTICATOR_ERROR);
            mIsPreConfiguredProvider =
                    savedInstanceState.getBoolean(SAVESTATE_KEY_IS_PRE_CONFIGURED);
            mSkipAutoDiscover = savedInstanceState.getBoolean(SAVESTATE_KEY_SKIP_AUTO_DISCOVER);
            mPasswordFailed = savedInstanceState.getBoolean(SAVESTATE_KEY_PASSWORD_FAILED);
        } else {
            // If we're not restoring from a previous state, we want to configure the initial screen

            // Set aside incoming AccountAuthenticatorResponse, if there was any
            mAccountAuthenticatorResponse = getIntent()
                    .getParcelableExtra(AccountManager.KEY_ACCOUNT_AUTHENTICATOR_RESPONSE);
            if (mAccountAuthenticatorResponse != null) {
                // When this Activity is called as part of account authentification flow,
                // we are responsible for eventually reporting the result (success or failure) to
                // the account manager.  Most exit paths represent an failed or abandoned setup,
                // so the default is to report the error.  Success will be reported by the code in
                // AccountSetupOptions that commits the finally created account.
                mReportAccountAuthenticatorError = true;
            }

            // Initialize the SetupDataFragment
            if (INTENT_FORCE_CREATE_ACCOUNT.equals(action)) {
                mSetupData.setFlowMode(AuthenticatorSetupIntentHelper.FLOW_MODE_FORCE_CREATE);
            } else {
                final int intentFlowMode = intent.getIntExtra(
                        AuthenticatorSetupIntentHelper.EXTRA_FLOW_MODE,
                        AuthenticatorSetupIntentHelper.FLOW_MODE_UNSPECIFIED);
                final String flowAccountType = intent.getStringExtra(
                        AuthenticatorSetupIntentHelper.EXTRA_FLOW_ACCOUNT_TYPE);
                mSetupData.setAmProtocol(
                        EmailServiceUtils.getProtocolFromAccountType(this, flowAccountType));
                mSetupData.setFlowMode(intentFlowMode);
            }

            mState = STATE_BASICS;
            // Support unit testing individual screens
            if (TextUtils.equals(ACTION_JUMP_TO_INCOMING, action)) {
                mState = STATE_MANUAL_INCOMING;
            } else if (TextUtils.equals(ACTION_JUMP_TO_OUTGOING, action)) {
                mState = STATE_MANUAL_OUTGOING;
            } else if (TextUtils.equals(ACTION_JUMP_TO_OPTIONS, action)) {
                mState = STATE_OPTIONS;
            }
            updateContentFragment(false /* addToBackstack */);
            mPasswordFailed = false;
        }

        if (!mIsProcessing && mSetupData.getFlowMode() ==
                AuthenticatorSetupIntentHelper.FLOW_MODE_FORCE_CREATE) {
            /**
             * To support continuous testing, we allow the forced creation of accounts.
             * This works in a manner fairly similar to automatic setup, in which the complete
             * server Uri's are available, except that we will also skip checking (as if both
             * checks were true) and all other UI.
             *
             * email: The email address for the new account
             * user: The user name for the new account
             * incoming: The URI-style string defining the incoming account
             * outgoing: The URI-style string defining the outgoing account
             */
            final String email = intent.getStringExtra(EXTRA_CREATE_ACCOUNT_EMAIL);
            final String user = intent.getStringExtra(EXTRA_CREATE_ACCOUNT_USER);
            final String password = intent.getStringExtra(EXTRA_CREATE_ACCOUNT_PASSWORD);
            final String incoming = intent.getStringExtra(EXTRA_CREATE_ACCOUNT_INCOMING);
            final String outgoing = intent.getStringExtra(EXTRA_CREATE_ACCOUNT_OUTGOING);
            final String syncLookbackText = intent.getStringExtra(EXTRA_CREATE_ACCOUNT_SYNC_LOOKBACK);
            final int syncLookback;
            if (TextUtils.equals(syncLookbackText, CREATE_ACCOUNT_SYNC_ALL_VALUE)) {
                syncLookback = SyncWindow.SYNC_WINDOW_ALL;
            } else {
                syncLookback = -1;
            }
            // If we've been explicitly provided with all the details to fill in the account, we
            // can use them
            final boolean explicitForm = !(TextUtils.isEmpty(user) ||
                    TextUtils.isEmpty(incoming) || TextUtils.isEmpty(outgoing));
            // If we haven't been provided the details, but we have the password, we can look up
            // the info from providers.xml
            final boolean implicitForm = !TextUtils.isEmpty(password) && !explicitForm;
            if (TextUtils.isEmpty(email) || !(explicitForm || implicitForm)) {
                LogUtils.e(LogUtils.TAG, "Force account create requires extras EMAIL, " +
                        "USER, INCOMING, OUTGOING, or EMAIL and PASSWORD");
                finish();
                return;
            }

            if (implicitForm) {
                final String[] emailParts = email.split("@");
                final String domain = emailParts[1].trim();
                mProvider = AccountSettingsUtils.findProviderForDomain(this, domain);
                if (mProvider == null) {
                    LogUtils.e(LogUtils.TAG, "findProviderForDomain couldn't find provider");
                    finish();
                    return;
                }
                mIsPreConfiguredProvider = true;
                mSetupData.setEmail(email);
                boolean autoSetupCompleted = finishAutoSetup();
                if (!autoSetupCompleted) {
                    LogUtils.e(LogUtils.TAG, "Force create account failed to create account");
                    finish();
                    return;
                }
                final Account account = mSetupData.getAccount();
                final HostAuth recvAuth = account.getOrCreateHostAuthRecv(this);
                recvAuth.mPassword = password;
                final HostAuth sendAuth = account.getOrCreateHostAuthSend(this);
                sendAuth.mPassword = password;
            } else {
                final Account account = mSetupData.getAccount();

                try {
                    final HostAuth recvAuth = account.getOrCreateHostAuthRecv(this);
                    recvAuth.setHostAuthFromString(incoming);

                    final HostAuth sendAuth = account.getOrCreateHostAuthSend(this);
                    sendAuth.setHostAuthFromString(outgoing);
                } catch (URISyntaxException e) {
                    // If we can't set up the URL, don't continue
                    Toast.makeText(this, R.string.account_setup_username_password_toast,
                            Toast.LENGTH_LONG)
                            .show();
                    finish();
                    return;
                }

                populateSetupData(user, email);
                // We need to do this after calling populateSetupData(), because that will
                // overwrite it with the default values.
                if (syncLookback >= SyncWindow.SYNC_WINDOW_ACCOUNT &&
                    syncLookback <= SyncWindow.SYNC_WINDOW_ALL) {
                    account.mSyncLookback = syncLookback;
                }
            }

            mState = STATE_OPTIONS;
            updateContentFragment(false /* addToBackstack */);
            getFragmentManager().executePendingTransactions();

            if (!DEBUG_ALLOW_NON_TEST_HARNESS_CREATION &&
                    !ActivityManager.isRunningInTestHarness()) {
                LogUtils.e(LogUtils.TAG,
                        "ERROR: Force account create only allowed while in test harness");
                finish();
                return;
            }

            mForceCreate = true;
        }

        // Launch a loader to look up the owner name.  It should be ready well in advance of
        // the time the user clicks next or manual.
        getLoaderManager().initLoader(OWNER_NAME_LOADER_ID, null, new OwnerNameLoaderCallbacks());

        // Launch a loader to cache some info about existing accounts so we can dupe-check against
        // them.
        getLoaderManager().initLoader(EXISTING_ACCOUNTS_LOADER_ID, null,
                new ExistingAccountsLoaderCallbacks());
    }

    private class OwnerNameLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
        @Override
        public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
            return new CursorLoader(AccountSetupFinal.this,
                    ContactsContract.Profile.CONTENT_URI,
                    new String[] {ContactsContract.Profile.DISPLAY_NAME_PRIMARY},
                    null, null, null);
        }

        @Override
        public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
            if (data != null && data.moveToFirst()) {
                mOwnerName = data.getString(data.getColumnIndex(
                        ContactsContract.Profile.DISPLAY_NAME_PRIMARY));
            }
        }

        @Override
        public void onLoaderReset(final Loader<Cursor> loader) {}
    }

    private class ExistingAccountsLoaderCallbacks implements LoaderManager.LoaderCallbacks<Cursor> {
        @Override
        public Loader<Cursor> onCreateLoader(final int id, final Bundle args) {
            return new CursorLoader(AccountSetupFinal.this, MailAppProvider.getAccountsUri(),
                    new String[] {UIProvider.AccountColumns.ACCOUNT_MANAGER_NAME,
                            UIProvider.AccountColumns.NAME},
                    null, null, null);
        }

        @Override
        public void onLoadFinished(final Loader<Cursor> loader, final Cursor data) {
            if (data == null || !data.moveToFirst()) {
                mExistingAccountsMap = null;
                return;
            }

            mExistingAccountsMap = new HashMap<>();

            final int emailColumnIndex = data.getColumnIndex(
                    UIProvider.AccountColumns.ACCOUNT_MANAGER_NAME);
            final int displayNameColumnIndex =
                    data.getColumnIndex(UIProvider.AccountColumns.NAME);

            do {
                final String email = data.getString(emailColumnIndex);
                final String displayName = data.getString(displayNameColumnIndex);
                mExistingAccountsMap.put(email,
                        TextUtils.isEmpty(displayName) ? email : displayName);
            } while (data.moveToNext());
        }

        @Override
        public void onLoaderReset(final Loader<Cursor> loader) {
            mExistingAccountsMap = null;
        }
    }

    @Override
    protected void onStart() {
        super.onStart();

        Analytics.getInstance().activityStart(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (mForceCreate) {
            mForceCreate = false;

            // We need to do this after onCreate so that we can ensure that the fragment is
            // fully created before querying it.
            // This will call initiateAccountCreation() for us
            proceed();
        }
    }

    @Override
    public void onSaveInstanceState(@NonNull Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean(SAVESTATE_KEY_IS_PROCESSING, mIsProcessing);
        outState.putInt(SAVESTATE_KEY_STATE, mState);
        outState.putSerializable(SAVESTATE_KEY_PROVIDER, mProvider);
        outState.putParcelable(SAVESTATE_KEY_AUTHENTICATOR_RESPONSE, mAccountAuthenticatorResponse);
        outState.putBoolean(SAVESTATE_KEY_REPORT_AUTHENTICATOR_ERROR,
                mReportAccountAuthenticatorError);
        outState.putBoolean(SAVESTATE_KEY_IS_PRE_CONFIGURED, mIsPreConfiguredProvider);
        outState.putBoolean(SAVESTATE_KEY_PASSWORD_FAILED, mPasswordFailed);
    }

    @Override
    protected void onStop() {
        super.onStop();

        Analytics.getInstance().activityStop(this);
    }

    /**
     * Swap in the new fragment according to mState. This pushes the current fragment onto the back
     * stack, so only call it once per transition.
     */
    private void updateContentFragment(boolean addToBackstack) {
        final AccountSetupFragment f;
        String backstackTag = null;

        switch (mState) {
            case STATE_BASICS:
                f = AccountSetupBasicsFragment.newInstance();
                break;
            case STATE_TYPE:
                f = AccountSetupTypeFragment.newInstance();
                break;
            case STATE_AB:
                f = AccountSetupABFragment.newInstance(mSetupData.getEmail(),
                        mSetupData.getAmProtocol(), mSetupData.getIncomingProtocol(this));
                break;
            case STATE_CREDENTIALS:
                f = AccountSetupCredentialsFragment.newInstance(mSetupData.getEmail(),
                        mSetupData.getIncomingProtocol(this), mSetupData.getClientCert(this),
                        mPasswordFailed, false /* standalone */);
                backstackTag = CREDENTIALS_BACKSTACK_TAG;
                break;
            case STATE_MANUAL_INCOMING:
                f = AccountSetupIncomingFragment.newInstance(false);
                break;
            case STATE_MANUAL_OUTGOING:
                f = AccountSetupOutgoingFragment.newInstance(false);
                break;
            case STATE_OPTIONS:
                f = AccountSetupOptionsFragment.newInstance();
                break;
            case STATE_NAMES:
                f = AccountSetupNamesFragment.newInstance();
                break;
            default:
                throw new IllegalStateException("Incorrect state " + mState);
        }
        f.setState(mState);
        final FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.setCustomAnimations(R.anim.fade_in, R.anim.fade_out, R.anim.fade_in, R.anim.fade_out);
        ft.replace(R.id.setup_fragment_container, f, CONTENT_FRAGMENT_TAG);
        if (addToBackstack) {
            ft.addToBackStack(backstackTag);
        }
        ft.commit();

        final InputMethodManager imm =
                (InputMethodManager)getSystemService(Context.INPUT_METHOD_SERVICE);
        final View fragment_container = findViewById(R.id.setup_fragment_container);
        imm.hideSoftInputFromWindow(fragment_container.getWindowToken(),
                0 /* flags: always hide */);
    }

    /**
     * Retrieve the current content fragment
     * @return The content fragment or null if it wasn't found for some reason
     */
    private AccountSetupFragment getContentFragment() {
        return (AccountSetupFragment) getFragmentManager().findFragmentByTag(CONTENT_FRAGMENT_TAG);
    }

    /**
     * Reads the flow state saved into the current fragment and restores mState to it, also
     * resetting the headline at the same time.
     */
    private void resetStateFromCurrentFragment() {
        AccountSetupFragment f = getContentFragment();
        mState = f.getState();
    }

    /**
     * Main choreography function to handle moving forward through scenes. Moving back should be
     * generally handled for us by the back stack
     */
    protected void proceed() {
        mIsProcessing = false;
        final AccountSetupFragment oldContentFragment = getContentFragment();
        if (oldContentFragment != null) {
            oldContentFragment.setNextButtonEnabled(true);
        }

        getFragmentManager().executePendingTransactions();

        switch (mState) {
            case STATE_BASICS:
                final boolean advance = onBasicsComplete();
                if (!advance) {
                    mState = STATE_BASICS_POST;
                    break;
                } // else fall through
            case STATE_BASICS_POST:
                if (shouldDivertToManual()) {
                    mSkipAutoDiscover = true;
                    mIsPreConfiguredProvider = false;
                    mState = STATE_TYPE;
                } else {
                    mSkipAutoDiscover = false;
                    if (mIsPreConfiguredProvider) {
                        if (!TextUtils.isEmpty(mSetupData.getAmProtocol()) &&
                                !TextUtils.equals(mSetupData.getAmProtocol(),
                                        mSetupData.getIncomingProtocol(this))) {
                            mState = STATE_AB;
                        } else {
                            mState = STATE_CREDENTIALS;
                            if (possiblyDivertToGmail()) {
                                return;
                            }
                        }
                    } else {
                        final String amProtocol = mSetupData.getAmProtocol();
                        if (!TextUtils.isEmpty(amProtocol)) {
                            mSetupData.setIncomingProtocol(this, amProtocol);
                            final Account account = mSetupData.getAccount();
                            setDefaultsForProtocol(account);
                            mState = STATE_CREDENTIALS;
                        } else {
                            mState = STATE_TYPE;
                        }
                    }
                }
                updateContentFragment(true /* addToBackstack */);
                break;
            case STATE_TYPE:
                // We either got here through "Manual Setup" or because we didn't find the provider
                mState = STATE_CREDENTIALS;
                updateContentFragment(true /* addToBackstack */);
                break;
            case STATE_AB:
                if (possiblyDivertToGmail()) {
                    return;
                }
                mState = STATE_CREDENTIALS;
                updateContentFragment(true /* addToBackstack */);
                break;
            case STATE_CREDENTIALS:
                collectCredentials();
                if (mIsPreConfiguredProvider) {
                    mState = STATE_CHECKING_PRECONFIGURED;
                    initiateCheckSettingsFragment(SetupDataFragment.CHECK_INCOMING
                            | SetupDataFragment.CHECK_OUTGOING);
                } else {
                    populateHostAuthsFromSetupData();
                    if (mSkipAutoDiscover) {
                        mState = STATE_MANUAL_INCOMING;
                        updateContentFragment(true /* addToBackstack */);
                    } else {
                        mState = STATE_AUTO_DISCOVER;
                        initiateAutoDiscover();
                    }
                }
                break;
            case STATE_CHECKING_PRECONFIGURED:
                if (mPreConfiguredFailed) {
                    if (mPasswordFailed) {
                        // Get rid of the previous instance of the AccountSetupCredentialsFragment.
                        FragmentManager fm = getFragmentManager();
                        fm.popBackStackImmediate(CREDENTIALS_BACKSTACK_TAG, 0);
                        final AccountSetupCredentialsFragment f = (AccountSetupCredentialsFragment)
                                getContentFragment();
                        f.setPasswordFailed(mPasswordFailed);
                        resetStateFromCurrentFragment();
                    } else {
                        mState = STATE_MANUAL_INCOMING;
                        updateContentFragment(true /* addToBackstack */);
                    }
                } else {
                    mState = STATE_OPTIONS;
                    updateContentFragment(true /* addToBackstack */);
                }
                break;
            case STATE_AUTO_DISCOVER:
                // TODO: figure out if we can skip past manual setup
                mState = STATE_MANUAL_INCOMING;
                updateContentFragment(true);
                break;
            case STATE_MANUAL_INCOMING:
                onIncomingComplete();
                mState = STATE_CHECKING_INCOMING;
                initiateCheckSettingsFragment(SetupDataFragment.CHECK_INCOMING);
                break;
            case STATE_CHECKING_INCOMING:
                final EmailServiceUtils.EmailServiceInfo serviceInfo =
                        mSetupData.getIncomingServiceInfo(this);
                if (serviceInfo.usesSmtp) {
                    mState = STATE_MANUAL_OUTGOING;
                } else {
                    mState = STATE_OPTIONS;
                }
                updateContentFragment(true /* addToBackstack */);
                break;
            case STATE_MANUAL_OUTGOING:
                onOutgoingComplete();
                mState = STATE_CHECKING_OUTGOING;
                initiateCheckSettingsFragment(SetupDataFragment.CHECK_OUTGOING);
                break;
            case STATE_CHECKING_OUTGOING:
                mState = STATE_OPTIONS;
                updateContentFragment(true /* addToBackstack */);
                break;
            case STATE_OPTIONS:
                mState = STATE_CREATING;
                initiateAccountCreation();
                break;
            case STATE_CREATING:
                mState = STATE_NAMES;
                updateContentFragment(true /* addToBackstack */);
                if (mSetupData.getFlowMode() ==
                        AuthenticatorSetupIntentHelper.FLOW_MODE_FORCE_CREATE) {
                    getFragmentManager().executePendingTransactions();
                    initiateAccountFinalize();
                }
                break;
            case STATE_NAMES:
                initiateAccountFinalize();
                break;
            case STATE_FINALIZE:
                finish();
                break;
            default:
                LogUtils.wtf(LogUtils.TAG, "Unknown state %d", mState);
                break;
        }
    }

    /**
     * Check if we should divert to creating a Gmail account instead
     * @return true if we diverted
     */
    private boolean possiblyDivertToGmail() {
        // TODO: actually divert here
        final EmailServiceUtils.EmailServiceInfo info =
                mSetupData.getIncomingServiceInfo(this);
        if (TextUtils.equals(info.protocol, "gmail")) {
            final Bundle options = new Bundle(1);
            options.putBoolean("allowSkip", false);
            AccountManager.get(this).addAccount("com.google",
                    "mail" /* authTokenType */,
                    null,
                    options,
                    this, null, null);

            finish();
            return true;
        }
        return false;
    }

    /**
     * Block the back key if we are currently processing the "next" key"
     */
    @Override
    public void onBackPressed() {
        if (mIsProcessing) {
            return;
        }
        if (mState == STATE_NAMES) {
            finish();
        } else {
            super.onBackPressed();
        }
        // After super.onBackPressed() our fragment should be in place, so query the state we
        // installed it for
        resetStateFromCurrentFragment();
    }

    @Override
    public void setAccount(Account account) {
        mSetupData.setAccount(account);
    }

    @Override
    public void finish() {
        // If the account manager initiated the creation, and success was not reported,
        // then we assume that we're giving up (for any reason) - report failure.
        if (mReportAccountAuthenticatorError) {
            if (mAccountAuthenticatorResponse != null) {
                mAccountAuthenticatorResponse
                        .onError(AccountManager.ERROR_CODE_CANCELED, "canceled");
                mAccountAuthenticatorResponse = null;
            }
        }
        super.finish();
    }

    @Override
    public void onNextButton() {
        // Some states are handled without UI, block double-presses here
        if (!mIsProcessing) {
            proceed();
        }
    }

    /**
     * @return true to proceed, false to remain on the current screen
     */
    private boolean onBasicsComplete() {
        final AccountSetupBasicsFragment f = (AccountSetupBasicsFragment) getContentFragment();
        final String email = f.getEmail();

        // Reset the protocol choice in case the user has back-navigated here
        mSetupData.setIncomingProtocol(this, null);

        if (!TextUtils.equals(email, mSetupData.getEmail())) {
            // If the user changes their email address, clear the password failed state
            mPasswordFailed = false;
        }
        mSetupData.setEmail(email);

        final String[] emailParts = email.split("@");
        final String domain = emailParts[1].trim();
        mProvider = AccountSettingsUtils.findProviderForDomain(this, domain);
        if (mProvider != null) {
            mIsPreConfiguredProvider = true;
            if (mProvider.note != null) {
                final AccountSetupNoteDialogFragment dialogFragment =
                        AccountSetupNoteDialogFragment.newInstance(mProvider.note);
                dialogFragment.show(getFragmentManager(), AccountSetupNoteDialogFragment.TAG);
                return false;
            } else {
                return finishAutoSetup();
            }
        } else {
            mIsPreConfiguredProvider = false;
            final String existingAccountName =
                mExistingAccountsMap != null ? mExistingAccountsMap.get(email) : null;
            if (!TextUtils.isEmpty(existingAccountName)) {
                showDuplicateAccountDialog(existingAccountName);
                return false;
            } else {
                populateSetupData(mOwnerName, email);
                mSkipAutoDiscover = false;
                return true;
            }
        }
    }

    private void showDuplicateAccountDialog(final String existingAccountName) {
        final DuplicateAccountDialogFragment dialogFragment =
                DuplicateAccountDialogFragment.newInstance(existingAccountName);
        dialogFragment.show(getFragmentManager(), DuplicateAccountDialogFragment.TAG);
    }

    @Override
    public void onDuplicateAccountDialogDismiss() {
        resetStateFromCurrentFragment();
    }

    private boolean shouldDivertToManual() {
        final AccountSetupBasicsFragment f = (AccountSetupBasicsFragment) getContentFragment();
        return f.isManualSetup();
    }

    @Override
    public void onCredentialsComplete(Bundle results) {
        proceed();
    }

    private void collectCredentials() {
        final AccountSetupCredentialsFragment f = (AccountSetupCredentialsFragment)
                getContentFragment();
        final Bundle results = f.getCredentialResults();
        mSetupData.setCredentialResults(results);
        final Account account = mSetupData.getAccount();
        final HostAuth recvAuth = account.getOrCreateHostAuthRecv(this);
        AccountSetupCredentialsFragment.populateHostAuthWithResults(this, recvAuth,
                mSetupData.getCredentialResults());
        mSetupData.setIncomingCredLoaded(true);
        final EmailServiceUtils.EmailServiceInfo info = mSetupData.getIncomingServiceInfo(this);
        if (info.usesSmtp) {
            final HostAuth sendAuth = account.getOrCreateHostAuthSend(this);
            AccountSetupCredentialsFragment.populateHostAuthWithResults(this, sendAuth,
                    mSetupData.getCredentialResults());
            mSetupData.setOutgoingCredLoaded(true);
        }
    }

    @Override
    public void onNoteDialogComplete() {
        finishAutoSetup();
        proceed();
    }

    @Override
    public void onNoteDialogCancel() {
        resetStateFromCurrentFragment();
    }

    /**
     * Finish the auto setup process, in some cases after showing a warning dialog.
     * Happens after onBasicsComplete
     * @return true to proceed, false to remain on the current screen
     */
    private boolean finishAutoSetup() {
        final String email = mSetupData.getEmail();

        try {
            mProvider.expandTemplates(email);

            final String primaryProtocol = HostAuth.getProtocolFromString(mProvider.incomingUri);
            EmailServiceUtils.EmailServiceInfo info =
                    EmailServiceUtils.getServiceInfo(this, primaryProtocol);
            // If the protocol isn't one we can use, and we're not diverting to gmail, try the alt
            if (!info.isGmailStub && !EmailServiceUtils.isServiceAvailable(this, info.protocol)) {
                LogUtils.d(LogUtils.TAG, "Protocol %s not available, using alternate",
                        info.protocol);
                mProvider.expandAlternateTemplates(email);
                final String alternateProtocol = HostAuth.getProtocolFromString(
                        mProvider.incomingUri);
                info = EmailServiceUtils.getServiceInfo(this, alternateProtocol);
            }
            final Account account = mSetupData.getAccount();
            final HostAuth recvAuth = account.getOrCreateHostAuthRecv(this);
            recvAuth.setHostAuthFromString(mProvider.incomingUri);

            recvAuth.setUserName(mProvider.incomingUsername);
            recvAuth.mPort =
                    ((recvAuth.mFlags & HostAuth.FLAG_SSL) != 0) ? info.portSsl : info.port;

            if (info.usesSmtp) {
                final HostAuth sendAuth = account.getOrCreateHostAuthSend(this);
                sendAuth.setHostAuthFromString(mProvider.outgoingUri);
                sendAuth.setUserName(mProvider.outgoingUsername);
            }

            // Populate the setup data, assuming that the duplicate account check will succeed
            populateSetupData(mOwnerName, email);

            final String duplicateAccountName =
                    mExistingAccountsMap != null ? mExistingAccountsMap.get(email) : null;
            if (duplicateAccountName != null) {
                showDuplicateAccountDialog(duplicateAccountName);
                return false;
            }
        } catch (URISyntaxException e) {
            mSkipAutoDiscover = false;
            mPreConfiguredFailed = true;
        }
        return true;
    }


    /**
     * Helper method to fill in some per-protocol defaults
     * @param account Account object to fill in
     */
    public void setDefaultsForProtocol(Account account) {
        final EmailServiceUtils.EmailServiceInfo info = mSetupData.getIncomingServiceInfo(this);
        if (info == null) return;
        account.mSyncInterval = info.defaultSyncInterval;
        account.mSyncLookback = info.defaultLookback;
        if (info.offerLocalDeletes) {
            account.setDeletePolicy(info.defaultLocalDeletes);
        }
    }

    /**
     * Populate SetupData's account with complete setup info, assumes that the receive auth is
     * created and its protocol is set
     */
    private void populateSetupData(String senderName, String senderEmail) {
        final Account account = mSetupData.getAccount();
        account.setSenderName(senderName);
        account.setEmailAddress(senderEmail);
        account.setDisplayName(senderEmail);
        setDefaultsForProtocol(account);
    }

    private void onIncomingComplete() {
        AccountSetupIncomingFragment f = (AccountSetupIncomingFragment) getContentFragment();
        f.collectUserInput();
    }

    private void onOutgoingComplete() {
        AccountSetupOutgoingFragment f = (AccountSetupOutgoingFragment) getContentFragment();
        f.collectUserInput();
    }

    // This callback method is only applicable to using Incoming/Outgoing fragments in settings mode
    @Override
    public void onAccountServerUIComplete(int checkMode) {}

    // This callback method is only applicable to using Incoming/Outgoing fragments in settings mode
    @Override
    public void onAccountServerSaveComplete() {}

    private void populateHostAuthsFromSetupData() {
        final String email = mSetupData.getEmail();
        final String[] emailParts = email.split("@");
        final String domain = emailParts[1];

        final Account account = mSetupData.getAccount();
        final EmailServiceUtils.EmailServiceInfo info =
                mSetupData.getIncomingServiceInfo(this);

        final HostAuth recvAuth = account.getOrCreateHostAuthRecv(this);
        recvAuth.setUserName(email);
        recvAuth.setConnection(mSetupData.getIncomingProtocol(), domain,
                HostAuth.PORT_UNKNOWN, info.offerTls ? HostAuth.FLAG_TLS : HostAuth.FLAG_SSL);
        AccountSetupCredentialsFragment.populateHostAuthWithResults(this, recvAuth,
                mSetupData.getCredentialResults());
        mSetupData.setIncomingCredLoaded(true);

        if (info.usesSmtp) {
            final HostAuth sendAuth = account.getOrCreateHostAuthSend(this);
            sendAuth.setUserName(email);
            sendAuth.setConnection(HostAuth.LEGACY_SCHEME_SMTP, domain,
                    HostAuth.PORT_UNKNOWN, HostAuth.FLAG_TLS);
            AccountSetupCredentialsFragment.populateHostAuthWithResults(this, sendAuth,
                    mSetupData.getCredentialResults());
            mSetupData.setOutgoingCredLoaded(true);
        }
    }

    private void initiateAutoDiscover() {
        // Populate the setup data, assuming that the duplicate account check will succeed
        initiateCheckSettingsFragment(SetupDataFragment.CHECK_AUTODISCOVER);
    }

    private void initiateCheckSettingsFragment(int checkMode) {
        final Fragment f = AccountCheckSettingsFragment.newInstance(checkMode);
        final Fragment d = CheckSettingsProgressDialogFragment.newInstance(checkMode);
        getFragmentManager().beginTransaction()
                .add(f, AccountCheckSettingsFragment.TAG)
                .add(d, CheckSettingsProgressDialogFragment.TAG)
                .commit();
    }

    @Override
    public void onCheckSettingsProgressDialogCancel() {
        dismissCheckSettingsFragment();
        resetStateFromCurrentFragment();
    }

    private void dismissCheckSettingsFragment() {
        final Fragment f = getFragmentManager().findFragmentByTag(AccountCheckSettingsFragment.TAG);
        final Fragment d =
                getFragmentManager().findFragmentByTag(CheckSettingsProgressDialogFragment.TAG);
        getFragmentManager().beginTransaction()
                .remove(f)
                .remove(d)
                .commit();
    }

    @Override
    public void onCheckSettingsError(int reason, String message) {
        if (reason == CheckSettingsErrorDialogFragment.REASON_AUTHENTICATION_FAILED ||
                reason == CheckSettingsErrorDialogFragment.REASON_CERTIFICATE_REQUIRED) {
            // TODO: possibly split password and cert error conditions
            mPasswordFailed = true;
        }
        dismissCheckSettingsFragment();
        final DialogFragment f =
                CheckSettingsErrorDialogFragment.newInstance(reason, message);
        f.show(getFragmentManager(), CheckSettingsErrorDialogFragment.TAG);
    }

    @Override
    public void onCheckSettingsErrorDialogEditCertificate() {
        if (mState == STATE_CHECKING_PRECONFIGURED) {
            mPreConfiguredFailed = true;
            proceed();
        } else {
            resetStateFromCurrentFragment();
        }
        final AccountSetupIncomingFragment f = (AccountSetupIncomingFragment) getContentFragment();
        f.onCertificateRequested();
    }

    @Override
    public void onCheckSettingsErrorDialogEditSettings() {
        // If we're checking pre-configured, set a flag that we failed and navigate forwards to
        // incoming settings
        if (mState == STATE_CHECKING_PRECONFIGURED || mState == STATE_AUTO_DISCOVER) {
            mPreConfiguredFailed = true;
            proceed();
        } else {
            resetStateFromCurrentFragment();
        }
    }

    @Override
    public void onCheckSettingsComplete() {
        mPreConfiguredFailed = false;
        mPasswordFailed = false;
        dismissCheckSettingsFragment();
        proceed();
    }

    @Override
    public void onCheckSettingsAutoDiscoverComplete(int result) {
        dismissCheckSettingsFragment();
        proceed();
    }

    @Override
    public void onCheckSettingsSecurityRequired(String hostName) {
        dismissCheckSettingsFragment();
        final DialogFragment f = SecurityRequiredDialogFragment.newInstance(hostName);
        f.show(getFragmentManager(), SecurityRequiredDialogFragment.TAG);
    }

    @Override
    public void onSecurityRequiredDialogResult(boolean ok) {
        if (ok) {
            proceed();
        } else {
            resetStateFromCurrentFragment();
        }
    }

    @Override
    public void onChooseProtocol(String protocol) {
        mSetupData.setIncomingProtocol(this, protocol);
        final Account account = mSetupData.getAccount();
        setDefaultsForProtocol(account);
        proceed();
    }

    @Override
    public void onABProtocolDisambiguated(String chosenProtocol) {
        if (!TextUtils.equals(mSetupData.getIncomingProtocol(this), chosenProtocol)) {
            mIsPreConfiguredProvider = false;
            mSetupData.setIncomingProtocol(this, chosenProtocol);
            final Account account = mSetupData.getAccount();
            setDefaultsForProtocol(account);
        }
        proceed();
    }

    /**
     * Ths is called when the user clicks the "done" button.
     * It collects the data from the UI, updates the setup account record, and launches a fragment
     * which handles creating the account in the system and database.
     */
    private void initiateAccountCreation() {
        mIsProcessing = true;
        getContentFragment().setNextButtonEnabled(false);

        final Account account = mSetupData.getAccount();
        if (account.mHostAuthRecv == null) {
            throw new IllegalStateException("in AccountSetupOptions with null mHostAuthRecv");
        }

        final AccountSetupOptionsFragment fragment = (AccountSetupOptionsFragment)
                getContentFragment();
        if (fragment == null) {
            throw new IllegalStateException("Fragment missing!");
        }

        account.setDisplayName(account.getEmailAddress());
        int newFlags = account.getFlags() & ~(Account.FLAGS_BACKGROUND_ATTACHMENTS);
        final EmailServiceUtils.EmailServiceInfo serviceInfo =
                mSetupData.getIncomingServiceInfo(this);
        if (serviceInfo.offerAttachmentPreload && fragment.getBackgroundAttachmentsValue()) {
            newFlags |= Account.FLAGS_BACKGROUND_ATTACHMENTS;
        }
        final HostAuth hostAuth = account.getOrCreateHostAuthRecv(this);
        if (hostAuth.mProtocol.equals(getString(R.string.protocol_eas))) {
            try {
                final double protocolVersionDouble = Double.parseDouble(account.mProtocolVersion);
                if (protocolVersionDouble >= 12.0) {
                    // If the the account is EAS and the protocol version is above 12.0,
                    // we know that SmartForward is enabled and the various search flags
                    // should be enabled first.
                    // TODO: Move this into protocol specific code in the future.
                    newFlags |= Account.FLAGS_SUPPORTS_SMART_FORWARD |
                            Account.FLAGS_SUPPORTS_GLOBAL_SEARCH | Account.FLAGS_SUPPORTS_SEARCH;
                }
            } catch (NumberFormatException e) {
                LogUtils.wtf(LogUtils.TAG, e, "Exception thrown parsing the protocol version.");
            }
        }
        account.setFlags(newFlags);
        account.setSyncInterval(fragment.getCheckFrequencyValue());
        final Integer syncWindowValue = fragment.getAccountSyncWindowValue();
        if (syncWindowValue != null) {
            account.setSyncLookback(syncWindowValue);
        }

        // Finish setting up the account, and commit it to the database
        if (mSetupData.getPolicy() != null) {
            account.mFlags |= Account.FLAGS_SECURITY_HOLD;
            account.mPolicy = mSetupData.getPolicy();
        }

        // Finally, write the completed account (for the first time) and then
        // install it into the Account manager as well.  These are done off-thread.
        // The account manager will report back via the callback, which will take us to
        // the next operations.
        final boolean syncEmail = fragment.getSyncEmailValue();
        final boolean syncCalendar = serviceInfo.syncCalendar && fragment.getSyncCalendarValue();
        final boolean syncContacts = serviceInfo.syncContacts && fragment.getSyncContactsValue();
        final boolean enableNotifications = fragment.getNotifyValue();

        final Fragment f = AccountCreationFragment.newInstance(account, syncEmail, syncCalendar,
                syncContacts, enableNotifications);
        final FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.add(f, AccountCreationFragment.TAG);
        ft.commit();

        showCreateAccountDialog();
    }

    /**
     * Called by the account creation fragment after it has completed.
     * We do a small amount of work here before moving on to the next state.
     */
    @Override
    public void onAccountCreationFragmentComplete() {
        destroyAccountCreationFragment();
        // If the account manager initiated the creation, and success was not reported,
        // then we assume that we're giving up (for any reason) - report failure.
        if (mAccountAuthenticatorResponse != null) {
            final EmailServiceUtils.EmailServiceInfo info = mSetupData.getIncomingServiceInfo(this);
            final Bundle b = new Bundle(2);
            b.putString(AccountManager.KEY_ACCOUNT_NAME, mSetupData.getEmail());
            b.putString(AccountManager.KEY_ACCOUNT_TYPE, info.accountType);
            mAccountAuthenticatorResponse.onResult(b);
            mAccountAuthenticatorResponse = null;
            mReportAccountAuthenticatorError = false;
        }
        setResult(RESULT_OK);
        proceed();
    }

    @Override
    public void destroyAccountCreationFragment() {
        dismissCreateAccountDialog();

        final Fragment f = getFragmentManager().findFragmentByTag(AccountCreationFragment.TAG);
        if (f == null) {
            LogUtils.wtf(LogUtils.TAG, "Couldn't find AccountCreationFragment to destroy");
        }
        getFragmentManager().beginTransaction()
                .remove(f)
                .commit();
    }


    public static class CreateAccountDialogFragment extends DialogFragment {
        public static final String TAG = "CreateAccountDialogFragment";
        public CreateAccountDialogFragment() {}

        public static CreateAccountDialogFragment newInstance() {
            return new CreateAccountDialogFragment();
        }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            /// Show "Creating account..." dialog
            setCancelable(false);
            final ProgressDialog d = new ProgressDialog(getActivity());
            d.setIndeterminate(true);
            d.setMessage(getString(R.string.account_setup_creating_account_msg));
            return d;
        }
    }

    protected void showCreateAccountDialog() {
        CreateAccountDialogFragment.newInstance()
                .show(getFragmentManager(), CreateAccountDialogFragment.TAG);
    }

    protected void dismissCreateAccountDialog() {
        final DialogFragment f = (DialogFragment)
                getFragmentManager().findFragmentByTag(CreateAccountDialogFragment.TAG);
        if (f != null) {
            f.dismiss();
        }
    }

    public static class CreateAccountErrorDialogFragment extends DialogFragment
            implements DialogInterface.OnClickListener {
        public CreateAccountErrorDialogFragment() {}

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            final String message = getString(R.string.account_setup_failed_dlg_auth_message,
                    R.string.system_account_create_failed);

            setCancelable(false);
            return new AlertDialog.Builder(getActivity())
                    .setIconAttribute(android.R.attr.alertDialogIcon)
                    .setTitle(R.string.account_setup_failed_dlg_title)
                    .setMessage(message)
                    .setPositiveButton(android.R.string.ok, this)
                    .create();
        }

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

    /**
     * This is called if MailService.setupAccountManagerAccount() fails for some reason
     */
    @Override
    public void showCreateAccountErrorDialog() {
        new CreateAccountErrorDialogFragment().show(getFragmentManager(), null);
    }

    /**
     * Collect the data from AccountSetupNames and finish up account creation
     */
    private void initiateAccountFinalize() {
        mIsProcessing = true;
        getContentFragment().setNextButtonEnabled(false);

        AccountSetupNamesFragment fragment = (AccountSetupNamesFragment) getContentFragment();
        // Update account object from UI
        final Account account = mSetupData.getAccount();
        final String description = fragment.getDescription();
        if (!TextUtils.isEmpty(description)) {
            account.setDisplayName(description);
        }
        account.setSenderName(fragment.getSenderName());

        final Fragment f = AccountFinalizeFragment.newInstance(account);
        final FragmentTransaction ft = getFragmentManager().beginTransaction();
        ft.add(f, AccountFinalizeFragment.TAG);
        ft.commit();
    }

    /**
     * Called when the AccountFinalizeFragment has finished its tasks
     */
    @Override
    public void onAccountFinalizeFragmentComplete() {
        finish();
    }
}
