package com.kickstarter.viewmodels;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.util.Pair;
import com.kickstarter.libs.ActivityViewModel;
import com.kickstarter.libs.CurrentConfigType;
import com.kickstarter.libs.CurrentUserType;
import com.kickstarter.libs.Environment;
import com.kickstarter.libs.rx.transformers.Transformers;
import com.kickstarter.libs.utils.I18nUtils;
import com.kickstarter.services.ApiClientType;
import com.kickstarter.services.apiresponses.AccessTokenEnvelope;
import com.kickstarter.services.apiresponses.ErrorEnvelope;
import com.kickstarter.ui.IntentKey;
import com.kickstarter.ui.activities.FacebookConfirmationActivity;
import com.kickstarter.viewmodels.errors.FacebookConfirmationViewModelErrors;
import com.kickstarter.viewmodels.inputs.FacebookConfirmationViewModelInputs;
import com.kickstarter.viewmodels.outputs.FacebookConfirmationViewModelOutputs;
import rx.Observable;
import rx.subjects.BehaviorSubject;
import rx.subjects.PublishSubject;
public class FacebookConfirmationViewModel extends ActivityViewModel<FacebookConfirmationActivity> implements
FacebookConfirmationViewModelInputs, FacebookConfirmationViewModelOutputs, FacebookConfirmationViewModelErrors {
private final ApiClientType client;
private final CurrentUserType currentUser;
private final CurrentConfigType currentConfig;
// INPUTS
private final PublishSubject<Void> createNewAccountClick = PublishSubject.create();
public void createNewAccountClick() {
createNewAccountClick.onNext(null);
}
private final PublishSubject<Boolean> sendNewslettersClick = PublishSubject.create();
public void sendNewslettersClick(final boolean b) {
sendNewslettersClick.onNext(b);
}
// OUTPUTS
private final BehaviorSubject<String> prefillEmail = BehaviorSubject.create();
public @NonNull Observable<String> prefillEmail() {
return prefillEmail;
}
private final PublishSubject<Void> signupSuccess = PublishSubject.create();
public @NonNull Observable<Void> signupSuccess() {
return signupSuccess;
}
private final BehaviorSubject<Boolean> sendNewslettersIsChecked = BehaviorSubject.create();
public @NonNull Observable<Boolean> sendNewslettersIsChecked() {
return sendNewslettersIsChecked;
}
// ERRORS
private final PublishSubject<ErrorEnvelope> signupError = PublishSubject.create();
public Observable<String> signupError() {
return signupError
.takeUntil(signupSuccess)
.map(ErrorEnvelope::errorMessage);
}
public final FacebookConfirmationViewModelInputs inputs = this;
public final FacebookConfirmationViewModelOutputs outputs = this;
public final FacebookConfirmationViewModelErrors errors = this;
public FacebookConfirmationViewModel(final @NonNull Environment environment) {
super(environment);
this.client = environment.apiClient();
this.currentConfig = environment.currentConfig();
this.currentUser = environment.currentUser();
final Observable<String> facebookAccessToken = intent()
.map(i -> i.getStringExtra(IntentKey.FACEBOOK_TOKEN))
.ofType(String.class);
final Observable<Pair<String, Boolean>> tokenAndNewsletter = facebookAccessToken
.compose(Transformers.combineLatestPair(sendNewslettersIsChecked));
intent()
.map(i -> i.getParcelableExtra(IntentKey.FACEBOOK_USER))
.ofType(ErrorEnvelope.FacebookUser.class)
.map(ErrorEnvelope.FacebookUser::email)
.compose(bindToLifecycle())
.subscribe(prefillEmail::onNext);
tokenAndNewsletter
.compose(Transformers.takeWhen(createNewAccountClick))
.flatMap(tn -> createNewAccount(tn.first, tn.second))
.compose(bindToLifecycle())
.subscribe(this::registerWithFacebookSuccess);
sendNewslettersClick
.compose(bindToLifecycle())
.subscribe(sendNewslettersIsChecked::onNext);
}
@Override
protected void onCreate(final @NonNull Context context, final @Nullable Bundle savedInstanceState) {
super.onCreate(context, savedInstanceState);
currentConfig.observable()
.take(1)
.map(config -> I18nUtils.isCountryUS(config.countryCode()))
.subscribe(sendNewslettersIsChecked::onNext);
signupError
.compose(bindToLifecycle())
.subscribe(__ -> koala.trackRegisterError());
sendNewslettersClick
.compose(bindToLifecycle())
.subscribe(koala::trackSignupNewsletterToggle);
signupSuccess
.compose(bindToLifecycle())
.subscribe(__ -> {
koala.trackLoginSuccess();
koala.trackRegisterSuccess();
});
koala.trackFacebookConfirmation();
koala.trackRegisterFormView();
}
public Observable<AccessTokenEnvelope> createNewAccount(final @NonNull String fbAccessToken, final boolean sendNewsletters) {
return client.registerWithFacebook(fbAccessToken, sendNewsletters)
.compose(Transformers.pipeApiErrorsTo(signupError))
.compose(Transformers.neverError());
}
private void registerWithFacebookSuccess(final @NonNull AccessTokenEnvelope envelope) {
currentUser.login(envelope.user(), envelope.accessToken());
signupSuccess.onNext(null);
}
}