class LoginPresenter extends BaseViperPresenter<LoginView, LoginInteractor> {

    @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.Success || 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));
    }

    @Inject public  LoginPresenter(@NonNull Context context, @NonNull LoginView view, @NonNull LoginInteractor interactor);

}