private void updatePortFromSecurityType() {
    ConnectionSecurity securityType = getSelectedSecurity();
    updateAuthPlainTextFromSecurityType(securityType);

    // Remove listener so as not to trigger validateFields() which is called
    // elsewhere as a result of user interaction.
    mPortView.removeTextChangedListener(validationTextWatcher);
    mPortView.setText(String.valueOf(AccountCreator.getDefaultPort(securityType, mStoreType)));
    mPortView.addTextChangedListener(validationTextWatcher);
  }
  /**
   * This is invoked only when the user makes changes to a widget, not when widgets are changed
   * programmatically. (The logic is simpler when you know that this is the last thing called after
   * an input change.)
   */
  private void validateFields() {
    AuthType authType = getSelectedAuthType();
    boolean isAuthTypeExternal = (AuthType.EXTERNAL == authType);

    ConnectionSecurity connectionSecurity = getSelectedSecurity();
    boolean hasConnectionSecurity = (connectionSecurity != ConnectionSecurity.NONE);

    if (isAuthTypeExternal && !hasConnectionSecurity) {

      // Notify user of an invalid combination of AuthType.EXTERNAL & ConnectionSecurity.NONE
      String toastText =
          getString(
              R.string.account_setup_incoming_invalid_setting_combo_notice,
              getString(R.string.account_setup_incoming_auth_type_label),
              AuthType.EXTERNAL.toString(),
              getString(R.string.account_setup_incoming_security_label),
              ConnectionSecurity.NONE.toString());
      Toast.makeText(this, toastText, Toast.LENGTH_LONG).show();

      // Reset the views back to their previous settings without recursing through here again
      OnItemSelectedListener onItemSelectedListener = mAuthTypeView.getOnItemSelectedListener();
      mAuthTypeView.setOnItemSelectedListener(null);
      mAuthTypeView.setSelection(mCurrentAuthTypeViewPosition, false);
      mAuthTypeView.setOnItemSelectedListener(onItemSelectedListener);
      updateViewFromAuthType();

      onItemSelectedListener = mSecurityTypeView.getOnItemSelectedListener();
      mSecurityTypeView.setOnItemSelectedListener(null);
      mSecurityTypeView.setSelection(mCurrentSecurityTypeViewPosition, false);
      mSecurityTypeView.setOnItemSelectedListener(onItemSelectedListener);
      updateAuthPlainTextFromSecurityType(getSelectedSecurity());

      mPortView.removeTextChangedListener(validationTextWatcher);
      mPortView.setText(mCurrentPortViewSetting);
      mPortView.addTextChangedListener(validationTextWatcher);

      authType = getSelectedAuthType();
      isAuthTypeExternal = (AuthType.EXTERNAL == authType);

      connectionSecurity = getSelectedSecurity();
      hasConnectionSecurity = (connectionSecurity != ConnectionSecurity.NONE);
    } else {
      mCurrentAuthTypeViewPosition = mAuthTypeView.getSelectedItemPosition();
      mCurrentSecurityTypeViewPosition = mSecurityTypeView.getSelectedItemPosition();
      mCurrentPortViewSetting = mPortView.getText().toString();
    }

    boolean hasValidCertificateAlias = mClientCertificateSpinner.getAlias() != null;
    boolean hasValidUserName = Utility.requiredFieldValid(mUsernameView);

    boolean hasValidPasswordSettings =
        hasValidUserName && !isAuthTypeExternal && Utility.requiredFieldValid(mPasswordView);

    boolean hasValidExternalAuthSettings =
        hasValidUserName && isAuthTypeExternal && hasConnectionSecurity && hasValidCertificateAlias;

    mNextButton.setEnabled(
        Utility.domainFieldValid(mServerView)
            && Utility.requiredFieldValid(mPortView)
            && (hasValidPasswordSettings || hasValidExternalAuthSettings)
            && (Intent.ACTION_EDIT.equals(getIntent().getAction())
                || !mAccountName.getText().toString().equals("")));
    Utility.setCompoundDrawablesAlpha(mNextButton, mNextButton.isEnabled() ? 255 : 128);
  }
  /**
   * Called at the end of either {@code onCreate()} or {@code onRestoreInstanceState()}, after the
   * views have been initialized, so that the listeners are not triggered during the view
   * initialization. This avoids needless calls to {@code validateFields()} which is called
   * immediately after this is called.
   */
  private void initializeViewListeners() {

    /*
     * Updates the port when the user changes the security type. This allows
     * us to show a reasonable default which the user can change.
     */
    mSecurityTypeView.setOnItemSelectedListener(
        new OnItemSelectedListener() {
          @Override
          public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {

            /*
             * We keep our own record of the spinner state so we
             * know for sure that onItemSelected() was called
             * because of user input, not because of spinner
             * state initialization. This assures that the port
             * will not be replaced with a default value except
             * on user input.
             */
            if (mCurrentSecurityTypeViewPosition != position) {
              updatePortFromSecurityType();
              validateFields();
            }
          }

          @Override
          public void onNothingSelected(AdapterView<?> parent) {
            /* unused */
          }
        });

    mAuthTypeView.setOnItemSelectedListener(
        new OnItemSelectedListener() {
          @Override
          public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
            if (mCurrentAuthTypeViewPosition == position) {
              return;
            }

            updateViewFromAuthType();
            validateFields();
            AuthType selection = getSelectedAuthType();

            // Have the user select (or confirm) the client certificate
            if (AuthType.EXTERNAL == selection) {

              // This may again invoke validateFields()
              mClientCertificateSpinner.chooseCertificate();
            } else {
              mPasswordView.requestFocus();
            }
          }

          @Override
          public void onNothingSelected(AdapterView<?> parent) {
            /* unused */
          }
        });

    mClientCertificateSpinner.setOnClientCertificateChangedListener(
        clientCertificateChangedListener);
    mUsernameView.addTextChangedListener(validationTextWatcher);
    mPasswordView.addTextChangedListener(validationTextWatcher);
    mServerView.addTextChangedListener(validationTextWatcher);
    mPortView.addTextChangedListener(validationTextWatcher);
  }