package com.android.exchange.service;

import android.content.ContentValues;
import android.content.Context;
import android.os.Build;
import android.os.Bundle;

import com.android.emailcommon.mail.MessagingException;
import com.android.emailcommon.provider.Account;
import com.android.emailcommon.provider.EmailContent.AccountColumns;
import com.android.emailcommon.provider.HostAuth;
import com.android.emailcommon.provider.Policy;
import com.android.emailcommon.service.EmailServiceProxy;
import com.android.emailcommon.service.PolicyServiceProxy;
import com.android.exchange.CommandStatusException;
import com.android.exchange.CommandStatusException.CommandStatus;
import com.android.exchange.Eas;
import com.android.exchange.EasResponse;
import com.android.exchange.adapter.FolderSyncParser;
import com.android.exchange.adapter.ProvisionParser;
import com.android.exchange.adapter.Serializer;
import com.android.exchange.adapter.SettingsParser;
import com.android.exchange.adapter.Tags;
import com.android.mail.utils.LogUtils;
import com.google.common.collect.Sets;

import org.apache.http.Header;
import org.apache.http.HttpStatus;

import java.io.IOException;
import java.security.cert.CertificateException;
import java.util.HashSet;

/**
 * Base class to perform the various requests needed to validate or sync an account.
 * "Account sync" consists primarily of syncing all folders for this account, but also includes
 * handling the protocol version, security policies, and other authentication issues.
 */
public class EasAccountValidator extends EasServerConnection {
    /** Logging tag. */
    private static final String TAG = "EasAccountValidator";

    /**
     * The maximum number of redirects we permit before giving up. Ideally the server should not
     * send us on a chase like this, so this is here to prevent infinite recursion in a bad case.
     */
    private static final int MAX_REDIRECTS = 3;

    public static final String EAS_12_POLICY_TYPE = "MS-EAS-Provisioning-WBXML";
    public static final String EAS_2_POLICY_TYPE = "MS-WAP-Provisioning-XML";

    /** The EAS protocol Provision status for "we implement all of the policies" */
    private static final String PROVISION_STATUS_OK = "1";
    /** The EAS protocol Provision status meaning "we partially implement the policies" */
    private static final String PROVISION_STATUS_PARTIAL = "2";

    /** Set of Exchange protocol versions we understand. */
    private static final HashSet<String> SUPPORTED_PROTOCOL_VERSIONS = Sets.newHashSet(
            Eas.SUPPORTED_PROTOCOL_EX2003,
            Eas.SUPPORTED_PROTOCOL_EX2007, Eas.SUPPORTED_PROTOCOL_EX2007_SP1,
            Eas.SUPPORTED_PROTOCOL_EX2010, Eas.SUPPORTED_PROTOCOL_EX2010_SP1);

    /** The number of times we've been redirected so far. */
    private int mRedirectCount;

    /**
     * An exception type used exclusively within this class -- some sub-functions throw this to
     * signal that a response from the Exchange server indicated that we should be using a different
     * host. This exception is caught
     */
    private static class RedirectException extends Exception {
        public final String mRedirectAddress;
        public RedirectException(final EasResponse resp) {
            mRedirectAddress = resp.getRedirectAddress();
        }
    }

    private EasAccountValidator(final Context context, final Account account,
            final HostAuth hostAuth) {
        super(context, account, hostAuth);
        mRedirectCount = 0;
    }

    protected EasAccountValidator(final Context context, final Account account) {
        this(context, account, HostAuth.restoreHostAuthWithId(context, account.mHostAuthKeyRecv));
    }

    public EasAccountValidator(final Context context, final HostAuth hostAuth) {
        this(context, new Account(), hostAuth);
        mAccount.mEmailAddress = hostAuth.mLogin;
    }

    /**
     * Update our account's protocol version based on the server's supported versions.
     * @param versionHeader The {@link Header} for the server's supported versions.
     * @return Whether we found a suitable protocol version.
     */
    private boolean setProtocolVersion(final Header versionHeader) {
        // The string is a comma separated list of EAS versions in ascending order
        // e.g. 1.0,2.0,2.5,12.0,12.1,14.0,14.1
        final String supportedVersions = versionHeader.getValue();
        LogUtils.i(TAG, "Server supports versions: %s", supportedVersions);
        final String[] supportedVersionsArray = supportedVersions.split(",");
        // Find the most recent version we support
        String newProtocolVersion = null;
        for (final String version: supportedVersionsArray) {
            if (SUPPORTED_PROTOCOL_VERSIONS.contains(version)) {
                newProtocolVersion = version;
            }
        }
        if (newProtocolVersion == null) {
            LogUtils.w(TAG, "No supported EAS versions: %s", supportedVersions);
            // TODO: if mAccount.isSaved(), we should delete the account.
            return false;
        }

        // Update our account with the new protocol version.
        final boolean protocolChanged = !newProtocolVersion.equals(mAccount.mProtocolVersion);
        if (protocolChanged) {
            mAccount.mProtocolVersion = newProtocolVersion;
            setProtocolVersion(newProtocolVersion);
        }

        // Fixup search flags, if they're not set.
        final boolean flagsChanged;
        if (getProtocolVersion() >= 12.0) {
            int oldFlags = mAccount.mFlags;
            mAccount.mFlags |= Account.FLAGS_SUPPORTS_GLOBAL_SEARCH + Account.FLAGS_SUPPORTS_SEARCH;
            flagsChanged = (oldFlags != mAccount.mFlags);
        } else {
            flagsChanged = false;
        }

        // Write account back to DB if needed.
        if ((protocolChanged || flagsChanged) && mAccount.isSaved()) {
            final ContentValues cv = new ContentValues();
            if (protocolChanged) {
                cv.put(AccountColumns.PROTOCOL_VERSION, mAccount.mProtocolVersion);
            }
            if (flagsChanged) {
                cv.put(AccountColumns.FLAGS, mAccount.mFlags);
            }
            mAccount.update(mContext, cv);
        }
        return true;
    }

    /**
     * Make an OPTIONS request to determine the protocol version to use, and update our account to
     * use the most recent protocol that both we and the server understand.
     * @return A status code for getting the protocol version. If NO_ERROR, then mAccount will be
     *     updated to the best version we mutually understand.
     */
    private int getServerProtocolVersion() throws IOException, RedirectException {
        final EasResponse resp = sendHttpClientOptions();
        try {
            final int code = resp.getStatus();
            LogUtils.d(TAG, "Validation (OPTIONS) response: %d", code);
            if (code == HttpStatus.SC_OK) {
                // No exception means successful validation
                final Header commands = resp.getHeader("MS-ASProtocolCommands");
                final Header versions = resp.getHeader("ms-asprotocolversions");
                final boolean hasProtocolVersion;
                if (commands == null || versions == null) {
                    LogUtils.e(TAG, "OPTIONS response without commands or versions");
                    hasProtocolVersion = false;
                } else {
                    hasProtocolVersion = setProtocolVersion(versions);
                }
                if (!hasProtocolVersion) {
                    return MessagingException.PROTOCOL_VERSION_UNSUPPORTED;
                }
                return MessagingException.NO_ERROR;
            }
            if (resp.isAuthError()) {
                return resp.isMissingCertificate()
                        ? MessagingException.CLIENT_CERTIFICATE_REQUIRED
                        : MessagingException.AUTHENTICATION_FAILED;
            }
            if (code == HttpStatus.SC_INTERNAL_SERVER_ERROR) {
                return MessagingException.AUTHENTICATION_FAILED_OR_SERVER_ERROR;
            }
            if (resp.isRedirectError()) {
                throw new RedirectException(resp);
            }
            // TODO Need to catch other kinds of errors (e.g. policy) For now, report code.
            LogUtils.w(TAG, "Validation failed, reporting I/O error: %d", code);
            return MessagingException.IOERROR;
        } finally {
            resp.close();
        }
    }

    /**
     * Send a FolderSync request and handle the response. Depending on isStatusOnly, this either
     * simply verifies that the response is valid, or it will also actually sync the folders.
     * @param isStatusOnly If true, this is only a validation, otherwise it's a full sync.
     * @return A status code indicating the result of this check.
     * @throws IOException
     * @throws CommandStatusException
     * @throws RedirectException
     */
    private int doFolderSync(final boolean isStatusOnly)
            throws IOException, CommandStatusException, RedirectException {
        LogUtils.i(TAG, "FolderSync (%s) for %s, %s, ssl = %s", isStatusOnly ? "validate" : "sync",
                mHostAuth.mAddress, mHostAuth.mLogin, mHostAuth.shouldUseSsl() ? "1" : "0");

        // Send "0" as the sync key for new accounts; otherwise, use the current key
        final String syncKey = mAccount.mSyncKey != null ? mAccount.mSyncKey : "0";
        final Serializer s = new Serializer();
        s.start(Tags.FOLDER_FOLDER_SYNC).start(Tags.FOLDER_SYNC_KEY).text(syncKey)
            .end().end().done();
        final EasResponse resp = sendHttpClientPost("FolderSync", s.toByteArray());
        final int resultCode;
        try {
            final int code = resp.getStatus();
            LogUtils.d(TAG, "FolderSync response: %d", code);
            if (code == HttpStatus.SC_OK) {
                // We need to parse the result to see if we've got a provisioning issue
                // (EAS 14.0 only)
                if (!resp.isEmpty()) {
                    new FolderSyncParser(mContext, mContext.getContentResolver(),
                            resp.getInputStream(), mAccount, isStatusOnly).parse();
                }
                resultCode = MessagingException.NO_ERROR;
            } else if (code == HttpStatus.SC_FORBIDDEN) {
                // For validation only, we take 403 as ACCESS_DENIED (the account isn't
                // authorized, possibly due to device type)
                resultCode = MessagingException.ACCESS_DENIED;
            } else if (resp.isProvisionError()) {
                // The device needs to have security policies enforced
                throw new CommandStatusException(CommandStatus.NEEDS_PROVISIONING);
            } else if (code == HttpStatus.SC_NOT_FOUND) {
                // We get a 404 from OWA addresses (which are NOT EAS addresses)
                resultCode = MessagingException.PROTOCOL_VERSION_UNSUPPORTED;
            } else if (code == HttpStatus.SC_UNAUTHORIZED) {
                resultCode = resp.isMissingCertificate()
                        ? MessagingException.CLIENT_CERTIFICATE_REQUIRED
                        : MessagingException.AUTHENTICATION_FAILED;
            } else if (resp.isRedirectError()) {
                throw new RedirectException(resp);
            } else {
                resultCode = MessagingException.UNSPECIFIED_EXCEPTION;
            }
        } finally {
            resp.close();
        }
        return resultCode;
    }

    /**
     * Send a Settings request to the server and process the response.
     * @return Whether the request succeeded.
     * @throws IOException
     */
    private boolean sendSettings() throws IOException {
        final Serializer s = new Serializer();
        s.start(Tags.SETTINGS_SETTINGS);
        s.start(Tags.SETTINGS_DEVICE_INFORMATION).start(Tags.SETTINGS_SET);
        s.data(Tags.SETTINGS_MODEL, Build.MODEL);
        s.data(Tags.SETTINGS_OS, "Android " + Build.VERSION.RELEASE);
        s.data(Tags.SETTINGS_USER_AGENT, getUserAgent());
        s.end().end().end().done(); // SETTINGS_SET, SETTINGS_DEVICE_INFORMATION, SETTINGS_SETTINGS
        final EasResponse resp = sendHttpClientPost("Settings", s.toByteArray());
        try {
            if (resp.getStatus() == HttpStatus.SC_OK) {
                return new SettingsParser(resp.getInputStream()).parse();
            }
        } finally {
            resp.close();
        }
        // On failures, simply return false
        return false;
    }

    private String getPolicyType() {
        return (getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2007_DOUBLE) ?
                EAS_12_POLICY_TYPE : EAS_2_POLICY_TYPE;
    }

    /**
     * Acknowledge a remote wipe command from the server.
     * @param tempKey The security key of our current (temporary) policy.
     * @throws IOException
     */
    private void acknowledgeRemoteWipe(final String tempKey)
            throws IOException {
        acknowledgeProvisionImpl(tempKey, PROVISION_STATUS_OK, true);
    }

    /**
     * Acknowledge that we've set the required policy.
     * @param tempKey The security key of our current (temporary) policy.
     * @param result One of {@link #PROVISION_STATUS_OK} or {@link #PROVISION_STATUS_PARTIAL}
     *               indicating how well we enforce the policy.
     * @return A new security sync key, or null on failure.
     * @throws IOException
     */
    private String acknowledgeProvision(final String tempKey, final String result)
            throws IOException {
        return acknowledgeProvisionImpl(tempKey, result, false);
    }

    /**
     * Common function doing the work for acknowledging remote wipes or provisioning.
     * @param tempKey The security key of our current (temporary) policy.
     * @param status One of {@link #PROVISION_STATUS_OK} or {@link #PROVISION_STATUS_PARTIAL}
     *               indicating how well we enforce the policy.
     * @param remoteWipe Whether this is a remote wipe.
     * @return A new security sync key, or null on failure.
     * @throws IOException
     */
    private String acknowledgeProvisionImpl(final String tempKey, final String status,
            final boolean remoteWipe) throws IOException {
        final Serializer s = new Serializer();
        s.start(Tags.PROVISION_PROVISION).start(Tags.PROVISION_POLICIES);
        s.start(Tags.PROVISION_POLICY);

        // Use the proper policy type, depending on EAS version
        s.data(Tags.PROVISION_POLICY_TYPE, getPolicyType());

        s.data(Tags.PROVISION_POLICY_KEY, tempKey);
        s.data(Tags.PROVISION_STATUS, status);
        s.end().end(); // PROVISION_POLICY, PROVISION_POLICIES
        if (remoteWipe) {
            s.start(Tags.PROVISION_REMOTE_WIPE);
            s.data(Tags.PROVISION_STATUS, PROVISION_STATUS_OK);
            s.end();
        }
        s.end().done(); // PROVISION_PROVISION
        EasResponse resp = sendHttpClientPost("Provision", s.toByteArray());
        try {
            if (resp.getStatus() == HttpStatus.SC_OK) {
                final ProvisionParser pp = new ProvisionParser(mContext, resp.getInputStream());
                if (pp.parse()) {
                    // Return the final policy key from the ProvisionParser
                    final String result =
                            (pp.getSecuritySyncKey() == null) ? "failed" : "confirmed";
                    LogUtils.i(TAG, "Provision %s for %s set", result,
                            PROVISION_STATUS_PARTIAL.equals(status) ? "PART" : "FULL");
                    return pp.getSecuritySyncKey();
                }
            }
        } finally {
            resp.close();
        }
        // On failures, log issue and return null
        LogUtils.i(TAG, "Provisioning failed for %s set",
                PROVISION_STATUS_PARTIAL.equals(status) ? "PART" : "FULL");
        return null;
    }

    /**
     * Send an Exchange Provision request, and process the response to see if we can handle the
     * provisioning requirements returned by the server.
     * @return A {@link ProvisionParser} for the response, or null if we can't handle it.
     * @throws IOException
     */
    private ProvisionParser canProvision() throws IOException {
        final Serializer s = new Serializer();
        s.start(Tags.PROVISION_PROVISION);
        if (getProtocolVersion() >= Eas.SUPPORTED_PROTOCOL_EX2010_SP1_DOUBLE) {
            // Send settings information in 14.1 and greater
            s.start(Tags.SETTINGS_DEVICE_INFORMATION).start(Tags.SETTINGS_SET);
            s.data(Tags.SETTINGS_MODEL, Build.MODEL);
            //s.data(Tags.SETTINGS_IMEI, "");
            //s.data(Tags.SETTINGS_FRIENDLY_NAME, "Friendly Name");
            s.data(Tags.SETTINGS_OS, "Android " + Build.VERSION.RELEASE);
            //s.data(Tags.SETTINGS_OS_LANGUAGE, "");
            //s.data(Tags.SETTINGS_PHONE_NUMBER, "");
            //s.data(Tags.SETTINGS_MOBILE_OPERATOR, "");
            s.data(Tags.SETTINGS_USER_AGENT, getUserAgent());
            s.end().end();  // SETTINGS_SET, SETTINGS_DEVICE_INFORMATION
        }
        s.start(Tags.PROVISION_POLICIES);
        s.start(Tags.PROVISION_POLICY);
        s.data(Tags.PROVISION_POLICY_TYPE, getPolicyType());
        s.end().end().end().done(); // PROVISION_POLICY, PROVISION_POLICIES, PROVISION_PROVISION
        final EasResponse resp = sendHttpClientPost("Provision", s.toByteArray());
        try {
            int code = resp.getStatus();
            if (code == HttpStatus.SC_OK) {
                final ProvisionParser pp = new ProvisionParser(mContext, resp.getInputStream());
                if (pp.parse()) {
                    // The PolicySet in the ProvisionParser will have the requirements for all KNOWN
                    // policies.  If others are required, hasSupportablePolicySet will be false
                    if (pp.hasSupportablePolicySet() &&
                            getProtocolVersion() == Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE) {
                        // In EAS 14.0, we need the final security key in order to use the settings
                        // command
                        final String policyKey = acknowledgeProvision(pp.getSecuritySyncKey(),
                                PROVISION_STATUS_OK);
                        if (policyKey != null) {
                            pp.setSecuritySyncKey(policyKey);
                        }
                    } else if (!pp.hasSupportablePolicySet())  {
                        // Try to acknowledge using the "partial" status (i.e. we can partially
                        // accommodate the required policies).  The server will agree to this if the
                        // "allow non-provisionable devices" setting is enabled on the server
                        LogUtils.i(TAG, "PolicySet is NOT fully supportable");
                        if (acknowledgeProvision(pp.getSecuritySyncKey(),
                                PROVISION_STATUS_PARTIAL) != null) {
                            // The server's ok with our inability to support policies, so we'll
                            // clear them
                            pp.clearUnsupportablePolicies();
                        }
                    }
                    return pp;
                }
            }
        } finally {
            resp.close();
        }

        // On failures, simply return null
        return null;
    }

    /**
     * Process the provisioning requirements that's returned by the server in response to a
     * Provision request.
     * @param pp  A {@link ProvisionParser} for the server response to the Provision request.
     * @return Whether we successfully handled the provisioning requirements.
     * @throws IOException
     */
    private boolean tryProvision(final ProvisionParser pp) throws IOException {
        if (pp == null) return false;
        // Get the policies from ProvisionParser
        final Policy policy = pp.getPolicy();
        final Policy oldPolicy;
        // Grab the old policy (if any)
        if (mAccount.mPolicyKey > 0) {
            oldPolicy = Policy.restorePolicyWithId(mContext, mAccount.mPolicyKey);
        } else {
            oldPolicy = null;
        }
        // Update the account with a null policyKey (the key we've gotten is
        // temporary and cannot be used for syncing)
        PolicyServiceProxy.setAccountPolicy(mContext, mAccount.mId, policy, null);
        // Make sure mAccount is current (with latest policy key)
        mAccount.refresh(mContext);
        if (pp.getRemoteWipe()) {
            // We've gotten a remote wipe command
            LogUtils.i(TAG, "!!! Remote wipe request received");
            // Start by setting the account to security hold
            PolicyServiceProxy.setAccountHoldFlag(mContext, mAccount, true);

            // First, we've got to acknowledge it, but wrap the wipe in try/catch so that
            // we wipe the device regardless of any errors in acknowledgment
            try {
                LogUtils.i(TAG, "!!! Acknowledging remote wipe to server");
                acknowledgeRemoteWipe(pp.getSecuritySyncKey());
            } catch (Exception e) {
                // Because remote wipe is such a high priority task, we don't want to
                // circumvent it if there's an exception in acknowledgment
            }
            // Then, tell SecurityPolicy to wipe the device
            LogUtils.i(TAG, "!!! Executing remote wipe");
            PolicyServiceProxy.remoteWipe(mContext);
            return false;
        } else if (pp.hasSupportablePolicySet() && PolicyServiceProxy.isActive(mContext, policy)) {
            // See if the required policies are in force; if they are, acknowledge the policies
            // to the server and get the final policy key
            // NOTE: For EAS 14.0, we already have the acknowledgment in the ProvisionParser
            String securitySyncKey;
            if (getProtocolVersion() == Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE) {
                securitySyncKey = pp.getSecuritySyncKey();
            } else {
                securitySyncKey = acknowledgeProvision(pp.getSecuritySyncKey(),
                        PROVISION_STATUS_OK);
            }
            if (securitySyncKey != null) {
                // If attachment policies have changed, fix up any affected attachment records
                if (oldPolicy != null) {
                    if ((oldPolicy.mDontAllowAttachments != policy.mDontAllowAttachments) ||
                            (oldPolicy.mMaxAttachmentSize != policy.mMaxAttachmentSize)) {
                        Policy.setAttachmentFlagsForNewPolicy(mContext, mAccount, policy);
                    }
                }
                // Write the final policy key to the Account and say we've been successful
                PolicyServiceProxy.setAccountPolicy(mContext, mAccount.mId, policy,
                        securitySyncKey);
                return true;
            }
        }
        return false;
    }

    /**
     * Do the heavy lifting for validation and sync:
     * - HTTP OPTIONS request to get protocol version from the server, if we don't already have it.
     * - Exchange FolderSync request to get the folder info.
     * (And exception handling for those operations.)
     * Validation differs from sync in four ways:
     * - Validation registers the client cert.
     * - Validation doesn't save the FolderSync results.
     * - Validation doesn't attempt to set device policies.
     * - Validation must populate a bundle with the results of the validation.
     * @param bundle If this is a validation call, this will be non-null, and this function will
     *               write the results to it (specifically it writes
     *               {@link EmailServiceProxy#VALIDATE_BUNDLE_RESULT_CODE},
     *               {@link EmailServiceProxy#VALIDATE_BUNDLE_PROTOCOL_VERSION}, and
     *               {@link EmailServiceProxy#VALIDATE_BUNDLE_POLICY_SET} (when there's a policy to
     *               be had).
     *               If this is a sync call, bundle will be null.
     *               This function also uses the null/not null status to differentiate behavior in
     *               the few places where validation and sync don't do the same thing.
     */
    protected void doValidationOrSync(final Bundle bundle) {
        LogUtils.i(TAG, "Performing %s: %s, %s, ssl = %s", bundle != null ? "validation" : "sync",
                mHostAuth.mAddress, mHostAuth.mLogin, mHostAuth.shouldUseSsl() ? "1" : "0");

        if (bundle != null) {
            if (mHostAuth.mClientCertAlias != null) {
                try {
                    getClientConnectionManager().registerClientCert(mContext, mHostAuth);
                } catch (final CertificateException e) {
                    // The client certificate the user specified is invalid/inaccessible.
                    bundle.putInt(EmailServiceProxy.VALIDATE_BUNDLE_RESULT_CODE,
                            MessagingException.CLIENT_CERTIFICATE_ERROR);
                    return;
                }
            }
        }

        int resultCode;

        // Need a nested try here because the provisioning exception handler can throw IOException.
        try {
            try {
                // TODO: also want to check protocol version at least once in a while after setup.
                if (mAccount.mProtocolVersion == null) {
                    final int optionsResult = getServerProtocolVersion();
                    if (optionsResult != MessagingException.NO_ERROR) {
                        if (bundle != null) {
                            bundle.putInt(EmailServiceProxy.VALIDATE_BUNDLE_RESULT_CODE,
                                    optionsResult);
                        }
                        return;
                    }
                    if (bundle != null) {
                        bundle.putString(EmailServiceProxy.VALIDATE_BUNDLE_PROTOCOL_VERSION,
                                mAccount.mProtocolVersion);
                    }
                }
                resultCode = doFolderSync(bundle != null);
            } catch (final CommandStatusException e) {
                final int status = e.mStatus;
                if (CommandStatus.isNeedsProvisioning(status)) {
                    // Get the policies and see if we are able to support them
                    final ProvisionParser pp = canProvision();
                    if (pp != null && pp.hasSupportablePolicySet()) {
                        // Set the proper result code and save the PolicySet in our Bundle
                        if (bundle != null) {
                            resultCode = MessagingException.SECURITY_POLICIES_REQUIRED;
                            bundle.putParcelable(EmailServiceProxy.VALIDATE_BUNDLE_POLICY_SET,
                                    pp.getPolicy());
                            if (getProtocolVersion() == Eas.SUPPORTED_PROTOCOL_EX2010_DOUBLE) {
                                mAccount.mSecuritySyncKey = pp.getSecuritySyncKey();
                                if (!sendSettings()) {
                                    LogUtils.i(TAG, "Denied access: %s",
                                            CommandStatus.toString(status));
                                    resultCode = MessagingException.ACCESS_DENIED;
                                }
                            }
                        } else if (tryProvision(pp)) {
                            resultCode = MessagingException.NO_ERROR;
                        } else {
                            resultCode = MessagingException.GENERAL_SECURITY;
                        }
                    } else {
                        // If not, set the proper code (the account will not be created)
                        resultCode = MessagingException.SECURITY_POLICIES_UNSUPPORTED;
                        if (bundle != null) {
                            bundle.putParcelable(EmailServiceProxy.VALIDATE_BUNDLE_POLICY_SET,
                                    pp.getPolicy());
                        }
                    }
                } else if (CommandStatus.isDeniedAccess(status)) {
                    LogUtils.i(TAG, "Denied access: %s", CommandStatus.toString(status));
                    resultCode = MessagingException.ACCESS_DENIED;
                } else if (CommandStatus.isTransientError(status)) {
                    LogUtils.i(TAG, "Transient error: %s", CommandStatus.toString(status));
                    resultCode = MessagingException.IOERROR;
                } else {
                    LogUtils.i(TAG, "Unexpected response: %s", CommandStatus.toString(status));
                    resultCode = MessagingException.UNSPECIFIED_EXCEPTION;
                }
            } catch (final RedirectException e) {
                // We handle a limited number of redirects by recursion.
                if (mRedirectCount < MAX_REDIRECTS && e.mRedirectAddress != null) {
                    ++mRedirectCount;
                    redirectHostAuth(e.mRedirectAddress);
                    if (bundle != null) {
                        bundle.putString(EmailServiceProxy.VALIDATE_BUNDLE_REDIRECT_ADDRESS,
                                e.mRedirectAddress);
                    }
                    doValidationOrSync(bundle);
                    return;
                } else {
                    resultCode = MessagingException.UNSPECIFIED_EXCEPTION;
                }
            }
        } catch (final IOException e) {
            final Throwable cause = e.getCause();
            if (cause != null && cause instanceof CertificateException) {
                // This could be because the server's certificate failed to validate.
                resultCode = MessagingException.GENERAL_SECURITY;
            } else {
                resultCode = MessagingException.IOERROR;
            }
        }

        if (bundle != null) {
            bundle.putInt(EmailServiceProxy.VALIDATE_BUNDLE_RESULT_CODE, resultCode);
        }
    }


    /**
     * Perform the actual validation.
     * @return The validation response.
     */
    public Bundle validate() {
        final Bundle bundle = new Bundle();
        doValidationOrSync(bundle);
        return bundle;
    }
}
