package co.smartreceipts.android.identity.widget.login;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.google.common.base.Preconditions;
import java.util.concurrent.TimeUnit;
import javax.inject.Inject;
import co.smartreceipts.android.R;
import co.smartreceipts.android.di.scopes.FragmentScope;
import co.smartreceipts.android.identity.apis.login.SmartReceiptsUserLogin;
import co.smartreceipts.android.identity.apis.login.SmartReceiptsUserSignUp;
import co.smartreceipts.android.identity.apis.login.UserCredentialsPayload;
import co.smartreceipts.android.identity.widget.login.model.UiInputValidationIndicator;
import co.smartreceipts.android.widget.model.UiIndicator;
import co.smartreceipts.android.widget.viper.BasePresenter;
import io.reactivex.Observable;
import io.reactivex.functions.BiFunction;
@FragmentScope
public class LoginPresenter extends BasePresenter<LoginView, LoginInteractor> {
private static final int MINIMUM_EMAIL_LENGTH = 6;
private static final int MINIMUM_PASSWORD_LENGTH = 8;
private final Context context;
@Inject
public LoginPresenter(@NonNull Context context, @NonNull LoginView view, @NonNull LoginInteractor interactor) {
super(view, interactor);
this.context = Preconditions.checkNotNull(context.getApplicationContext());
}
@Override
public void subscribe() {
compositeDisposable.add(Observable.concat(
interactor.getLastUserCredentialsPayload().toObservable(), // Start by emitting our previous request
Observable.merge( // Next, get the stream of clicks as payloads for the ongoing stream
Observable.combineLatest(
view.getEmailTextChanges(),
view.getPasswordTextChanges(),
(BiFunction<CharSequence, CharSequence, UserCredentialsPayload>) SmartReceiptsUserLogin::new)
.flatMap(userCredentialsPayload -> view.getLoginButtonClicks().map(ignored -> userCredentialsPayload)),
Observable.combineLatest(
view.getEmailTextChanges(),
view.getPasswordTextChanges(),
(BiFunction<CharSequence, CharSequence, UserCredentialsPayload>) SmartReceiptsUserSignUp::new)
.flatMap(userCredentialsPayload -> view.getSignUpButtonClicks().map(ignored -> userCredentialsPayload)))
)
.flatMap(interactor::loginOrSignUp)
.startWith(UiIndicator.idle())
.subscribe(uiIndicator -> {
view.present(uiIndicator);
if (uiIndicator.getState() == UiIndicator.State.Succcess || uiIndicator.getState() == UiIndicator.State.Error) {
interactor.onLoginResultsConsumed();
}
}));
compositeDisposable.add(Observable.combineLatest(simpleEmailFieldValidator(), simplePasswordFieldValidator(),
(isEmailValid, isPasswordValid) -> {
final String message;
if (!isEmailValid) {
message = context.getString(R.string.login_fields_hint_email);
} else if (!isPasswordValid) {
message = context.getString(R.string.login_fields_hint_password);
} else {
message = context.getString(R.string.login_fields_hint_valid);
}
return new UiInputValidationIndicator(message, isEmailValid, isPasswordValid);
})
.distinctUntilChanged()
.subscribe(view::present));
}
@NonNull
private Observable<Boolean> simpleEmailFieldValidator() {
return view.getEmailTextChanges()
.map(emailCharSequence -> {
if (emailCharSequence != null && emailCharSequence.length() >= MINIMUM_EMAIL_LENGTH) {
final String email = emailCharSequence.toString();
return email.contains("@") && email.contains(".");
} else {
return false;
}
});
}
@NonNull
private Observable<Boolean> simplePasswordFieldValidator() {
return view.getPasswordTextChanges()
.map(password -> password != null && password.length() >= MINIMUM_PASSWORD_LENGTH);
}
}