package com.kickstarter.viewmodels;
import android.support.annotation.NonNull;
import android.util.Pair;
import com.kickstarter.libs.ActivityViewModel;
import com.kickstarter.libs.CurrentUserType;
import com.kickstarter.libs.Environment;
import com.kickstarter.libs.rx.transformers.Transformers;
import com.kickstarter.libs.utils.ListUtils;
import com.kickstarter.libs.utils.UserUtils;
import com.kickstarter.models.User;
import com.kickstarter.services.ApiClientType;
import com.kickstarter.ui.activities.SettingsActivity;
import com.kickstarter.ui.data.Newsletter;
import com.kickstarter.viewmodels.errors.SettingsViewModelErrors;
import com.kickstarter.viewmodels.inputs.SettingsViewModelInputs;
import com.kickstarter.viewmodels.outputs.SettingsViewModelOutputs;
import rx.Observable;
import rx.subjects.BehaviorSubject;
import rx.subjects.PublishSubject;
public class SettingsViewModel extends ActivityViewModel<SettingsActivity> implements SettingsViewModelInputs,
SettingsViewModelErrors, SettingsViewModelOutputs {
// INPUTS
private final PublishSubject<Void> contactEmailClicked = PublishSubject.create();
private final PublishSubject<Pair<Boolean, Newsletter>> newsletterInput = PublishSubject.create();
private final PublishSubject<User> userInput = PublishSubject.create();
public void logoutClicked() {
showConfirmLogoutPrompt.onNext(true);
}
public void closeLogoutConfirmationClicked() {
showConfirmLogoutPrompt.onNext(false);
}
private final PublishSubject<Void> confirmLogoutClicked = PublishSubject.create();
@Override
public void confirmLogoutClicked() {
confirmLogoutClicked.onNext(null);
}
// OUTPUTS
private final PublishSubject<Newsletter> showOptInPrompt = PublishSubject.create();
public @NonNull Observable<Newsletter> showOptInPrompt() {
return showOptInPrompt;
}
private final PublishSubject<Void> updateSuccess = PublishSubject.create();
public @NonNull final Observable<Void> updateSuccess() {
return updateSuccess;
}
private final BehaviorSubject<User> userOutput = BehaviorSubject.create();
public @NonNull Observable<User> user() {
return userOutput;
}
private final BehaviorSubject<Boolean> showConfirmLogoutPrompt = BehaviorSubject.create();
public @NonNull Observable<Boolean> showConfirmLogoutPrompt() {
return showConfirmLogoutPrompt;
}
private final BehaviorSubject<Void> logout = BehaviorSubject.create();
@Override
public @NonNull Observable<Void> logout() {
return logout;
}
// ERRORS
private final PublishSubject<Throwable> unableToSavePreferenceError = PublishSubject.create();
public @NonNull final Observable<String> unableToSavePreferenceError() {
return unableToSavePreferenceError
.takeUntil(updateSuccess)
.map(__ -> null);
}
public final SettingsViewModelInputs inputs = this;
public final SettingsViewModelOutputs outputs = this;
public final SettingsViewModelErrors errors = this;
private final ApiClientType client;
private final CurrentUserType currentUser;
@Override
public void contactEmailClicked() {
this.contactEmailClicked.onNext(null);
}
@Override
public void notifyMobileOfFollower(final boolean b) {
userInput.onNext(userOutput.getValue().toBuilder().notifyMobileOfFollower(b).build());
}
@Override
public void notifyMobileOfFriendActivity(final boolean b) {
userInput.onNext(userOutput.getValue().toBuilder().notifyMobileOfFriendActivity(b).build());
}
@Override
public void notifyMobileOfUpdates(final boolean b) {
userInput.onNext(userOutput.getValue().toBuilder().notifyMobileOfUpdates(b).build());
}
@Override
public void notifyOfFollower(final boolean b) {
userInput.onNext(userOutput.getValue().toBuilder().notifyOfFollower(b).build());
}
@Override
public void notifyOfFriendActivity(final boolean b) {
userInput.onNext(userOutput.getValue().toBuilder().notifyOfFriendActivity(b).build());
}
@Override
public void notifyOfUpdates(final boolean b) {
userInput.onNext(userOutput.getValue().toBuilder().notifyOfUpdates(b).build());
}
@Override
public void sendGamesNewsletter(final boolean checked) {
userInput.onNext(userOutput.getValue().toBuilder().gamesNewsletter(checked).build());
newsletterInput.onNext(new Pair<>(checked, Newsletter.GAMES));
}
@Override
public void sendHappeningNewsletter(final boolean checked) {
userInput.onNext(userOutput.getValue().toBuilder().happeningNewsletter(checked).build());
newsletterInput.onNext(new Pair<>(checked, Newsletter.HAPPENING));
}
@Override
public void sendPromoNewsletter(final boolean checked) {
userInput.onNext(userOutput.getValue().toBuilder().promoNewsletter(checked).build());
newsletterInput.onNext(new Pair<>(checked, Newsletter.PROMO));
}
@Override
public void sendWeeklyNewsletter(final boolean checked) {
userInput.onNext(userOutput.getValue().toBuilder().weeklyNewsletter(checked).build());
newsletterInput.onNext(new Pair<>(checked, Newsletter.WEEKLY));
}
public SettingsViewModel(final @NonNull Environment environment) {
super(environment);
client = environment.apiClient();
currentUser = environment.currentUser();
client.fetchCurrentUser()
.retry(2)
.compose(Transformers.neverError())
.compose(bindToLifecycle())
.subscribe(currentUser::refresh);
currentUser.observable()
.take(1)
.compose(bindToLifecycle())
.subscribe(userOutput::onNext);
userInput
.concatMap(this::updateSettings)
.compose(bindToLifecycle())
.subscribe(this::success);
userInput
.compose(bindToLifecycle())
.subscribe(userOutput);
userOutput
.window(2, 1)
.flatMap(Observable::toList)
.map(ListUtils::first)
.compose(Transformers.takeWhen(unableToSavePreferenceError))
.compose(bindToLifecycle())
.subscribe(userOutput);
currentUser.observable()
.compose(Transformers.takePairWhen(newsletterInput))
.filter(us -> requiresDoubleOptIn(us.first, us.second.first))
.map(us -> us.second.second)
.compose(bindToLifecycle())
.subscribe(showOptInPrompt);
contactEmailClicked
.compose(bindToLifecycle())
.subscribe(__ -> koala.trackContactEmailClicked());
newsletterInput
.map(bs -> bs.first)
.compose(bindToLifecycle())
.subscribe(koala::trackNewsletterToggle);
confirmLogoutClicked
.compose(bindToLifecycle())
.subscribe(__ -> {
koala.trackLogout();
logout.onNext(null);
});
koala.trackSettingsView();
}
private boolean requiresDoubleOptIn(final @NonNull User user, final boolean checked) {
return UserUtils.isLocationGermany(user) && checked;
}
private void success(final @NonNull User user) {
currentUser.refresh(user);
this.updateSuccess.onNext(null);
}
private @NonNull Observable<User> updateSettings(final @NonNull User user) {
return client.updateUserSettings(user)
.compose(Transformers.pipeErrorsTo(unableToSavePreferenceError));
}
}