package com.kickstarter.ui.activities;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.Html;
import android.util.Pair;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import com.kickstarter.KSApplication;
import com.kickstarter.R;
import com.kickstarter.libs.ActivityRequestCodes;
import com.kickstarter.libs.BaseActivity;
import com.kickstarter.libs.KSString;
import com.kickstarter.libs.qualifiers.RequiresActivityViewModel;
import com.kickstarter.libs.utils.ObjectUtils;
import com.kickstarter.libs.utils.ViewUtils;
import com.kickstarter.ui.IntentKey;
import com.kickstarter.ui.toolbars.LoginToolbar;
import com.kickstarter.ui.views.ConfirmDialog;
import com.kickstarter.viewmodels.LoginViewModel;
import javax.inject.Inject;
import butterknife.Bind;
import butterknife.BindString;
import butterknife.ButterKnife;
import butterknife.OnClick;
import butterknife.OnTextChanged;
import rx.Observable;
import static com.kickstarter.libs.rx.transformers.Transformers.observeForUI;
import static com.kickstarter.libs.utils.TransitionUtils.slideInFromLeft;
@RequiresActivityViewModel(LoginViewModel.class)
public final class LoginActivity extends BaseActivity<LoginViewModel> {
protected @Bind(R.id.email) EditText emailEditText;
protected @Bind(R.id.forgot_your_password_text_view) TextView forgotPasswordTextView;
protected @Bind(R.id.login_button) Button loginButton;
protected @Bind(R.id.login_toolbar) LoginToolbar loginToolbar;
protected @Bind(R.id.password) EditText passwordEditText;
protected @BindString(R.string.login_buttons_forgot_password_html) String forgotPasswordString;
protected @BindString(R.string.forgot_password_we_sent_an_email_to_email_address_with_instructions_to_reset_your_password) String forgotPasswordSentEmailString;
protected @BindString(R.string.login_errors_does_not_match) String loginDoesNotMatchString;
protected @BindString(R.string.login_errors_unable_to_log_in) String unableToLoginString;
protected @BindString(R.string.login_buttons_log_in) String loginString;
protected @BindString(R.string.login_errors_title) String errorTitleString;
private ConfirmDialog confirmResetPasswordSuccessDialog;
@Inject KSString ksString;
@Override
protected void onCreate(final @Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.login_layout);
((KSApplication) getApplication()).component().inject(this);
ButterKnife.bind(this);
loginToolbar.setTitle(loginString);
forgotPasswordTextView.setText(Html.fromHtml(forgotPasswordString));
errorMessages()
.compose(bindToLifecycle())
.compose(observeForUI())
.subscribe(e -> ViewUtils.showDialog(this, errorTitleString, e));
viewModel.errors.tfaChallenge()
.compose(bindToLifecycle())
.compose(observeForUI())
.subscribe(__ -> startTwoFactorActivity());
viewModel.outputs.loginSuccess()
.compose(bindToLifecycle())
.compose(observeForUI())
.subscribe(__ -> onSuccess());
viewModel.outputs.prefillEmailFromPasswordReset()
.compose(bindToLifecycle())
.compose(observeForUI())
.subscribe(emailEditText::setText);
viewModel.outputs.showResetPasswordSuccessDialog()
.compose(bindToLifecycle())
.compose(observeForUI())
.subscribe(showAndEmail -> {
final boolean show = showAndEmail.first;
final String email = showAndEmail.second;
if (show) {
resetPasswordSuccessDialog(email).show();
} else {
resetPasswordSuccessDialog(email).dismiss();
}
});
viewModel.outputs.setLoginButtonIsEnabled()
.compose(bindToLifecycle())
.compose(observeForUI())
.subscribe(this::setLoginButtonEnabled);
}
/**
* Lazily creates a reset password success confirmation dialog and stores it in an instance variable.
*/
private @NonNull ConfirmDialog resetPasswordSuccessDialog(final @NonNull String email) {
if (confirmResetPasswordSuccessDialog == null) {
final String message = ksString.format(forgotPasswordSentEmailString, "email", email);
confirmResetPasswordSuccessDialog = new ConfirmDialog(this, null, message);
confirmResetPasswordSuccessDialog
.setOnDismissListener(__ -> viewModel.inputs.resetPasswordConfirmationDialogDismissed());
confirmResetPasswordSuccessDialog
.setOnCancelListener(__ -> viewModel.inputs.resetPasswordConfirmationDialogDismissed());
}
return confirmResetPasswordSuccessDialog;
}
private Observable<String> errorMessages() {
return viewModel.errors.invalidLoginError()
.map(ObjectUtils.coalesceWith(loginDoesNotMatchString))
.mergeWith(viewModel.errors.genericLoginError()
.map(ObjectUtils.coalesceWith(unableToLoginString))
);
}
@Override
protected void onActivityResult(final int requestCode, final int resultCode, final @Nullable Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if (requestCode != ActivityRequestCodes.LOGIN_FLOW) {
return;
}
setResult(resultCode, intent);
finish();
}
@OnTextChanged(R.id.email)
void onEmailTextChanged(final @NonNull CharSequence email) {
viewModel.inputs.email(email.toString());
}
@OnTextChanged(R.id.password)
void onPasswordTextChanged(final @NonNull CharSequence password) {
viewModel.inputs.password(password.toString());
}
@OnClick(R.id.forgot_your_password_text_view)
public void forgotYourPasswordTextViewClick() {
final Intent intent = new Intent(this, ResetPasswordActivity.class);
startActivityWithTransition(intent, R.anim.slide_in_right, R.anim.fade_out_slide_out_left);
}
@OnClick(R.id.login_button)
public void loginButtonOnClick() {
viewModel.inputs.loginClick();
}
public void onSuccess() {
setResult(Activity.RESULT_OK);
finish();
}
public void setLoginButtonEnabled(final boolean enabled) {
loginButton.setEnabled(enabled);
}
public void startTwoFactorActivity() {
final Intent intent = new Intent(this, TwoFactorActivity.class)
.putExtra(IntentKey.EMAIL, emailEditText.getText().toString())
.putExtra(IntentKey.PASSWORD, passwordEditText.getText().toString());
startActivityForResult(intent, ActivityRequestCodes.LOGIN_FLOW);
overridePendingTransition(R.anim.slide_in_right, R.anim.fade_out_slide_out_left);
}
@Override
protected @Nullable Pair<Integer, Integer> exitTransition() {
return slideInFromLeft();
}
}