package com.kickstarter.viewmodels;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import com.kickstarter.libs.ActivityViewModel;
import com.kickstarter.libs.Environment;
import com.kickstarter.libs.rx.transformers.Transformers;
import com.kickstarter.libs.utils.BooleanUtils;
import com.kickstarter.libs.utils.NumberUtils;
import com.kickstarter.libs.utils.ObjectUtils;
import com.kickstarter.libs.utils.ProgressBarUtils;
import com.kickstarter.libs.utils.ProjectUtils;
import com.kickstarter.models.Category;
import com.kickstarter.models.Project;
import com.kickstarter.models.User;
import com.kickstarter.ui.viewholders.ProjectCardViewHolder;
import org.joda.time.DateTime;
import java.util.List;
import rx.Observable;
import rx.subjects.PublishSubject;
import static com.kickstarter.libs.rx.transformers.Transformers.coalesce;
public interface ProjectCardHolderViewModel {
interface Inputs {
void configureWith(Project project);
void projectClicked();
}
interface Outputs {
Observable<String> backersCountTextViewText();
Observable<Boolean> backingViewGroupIsGone();
Observable<String> categoryNameTextViewText();
Observable<String> deadlineCountdownText();
Observable<Boolean> featuredViewGroupIsGone();
Observable<List<User>> friendsForNamepile();
Observable<String> friendAvatarUrl();
Observable<Boolean> imageIsInvisible();
Observable<Boolean> friendBackingViewIsHidden();
Observable<Boolean> fundingUnsuccessfulTextViewIsGone();
Observable<Boolean> metadataViewGroupIsGone();
Observable<Project> projectForDeadlineCountdownDetail();
Observable<Integer> percentageFunded();
Observable<Boolean> percentageFundedProgressBarIsGone();
Observable<String> percentageFundedTextViewText();
Observable<String> photoUrl();
Observable<String> blurbText();
Observable<String> nameText();
Observable<Project> notifyDelegateOfProjectClick();
Observable<Boolean> potdViewGroupIsGone();
Observable<DateTime> projectCanceledAt();
Observable<DateTime> projectFailedAt();
Observable<Boolean> projectStateViewGroupIsGone();
Observable<DateTime> projectSuccessfulAt();
Observable<DateTime> projectSuspendedAt();
Observable<String> rootCategoryNameForFeatured();
Observable<Boolean> setDefaultTopPadding();
Observable<Boolean> starredViewGroupIsGone();
Observable<Boolean> successfullyFundedTextViewIsGone();
}
final class ViewModel extends ActivityViewModel<ProjectCardViewHolder> implements Inputs, Outputs {
public ViewModel(final @NonNull Environment environment) {
super(environment);
this.projectForDeadlineCountdownDetail = this.project;
this.backersCountTextViewText = this.project
.map(Project::backersCount)
.map(NumberUtils::format);
this.backingViewGroupIsGone = this.project
.map(p -> metadataForProject(p) != Metadata.BACKING);
this.blurbText = this.project
.map(Project::blurb);
this.categoryNameTextViewText = this.project
.map(Project::category)
.map(Category::name)
.compose(coalesce(""));
this.deadlineCountdownText = this.project
.map(ProjectUtils::deadlineCountdownValue)
.map(NumberUtils::format);
this.featuredViewGroupIsGone = this.project
.map(p -> metadataForProject(p) != Metadata.CATEGORY_FEATURED);
this.friendAvatarUrl = this.project
.filter(Project::isFriendBacking)
.map(Project::friends)
.map(friends -> friends.get(0).avatar().small());
this.friendBackingViewIsHidden = this.project
.map(Project::isFriendBacking)
.map(BooleanUtils::negate);
this.friendsForNamepile = this.project
.filter(Project::isFriendBacking)
.map(Project::friends);
this.fundingUnsuccessfulTextViewIsGone = this.project
.map(p ->
!p.state().equals(Project.STATE_CANCELED)
&& !p.state().equals(Project.STATE_FAILED)
&& !p.state().equals(Project.STATE_SUSPENDED));
this.imageIsInvisible = this.project
.map(Project::photo)
.map(ObjectUtils::isNull);
this.metadataViewGroupIsGone = this.project
.map(p -> metadataForProject(p) == null);
this.nameText = this.project
.map(Project::name);
this.notifyDelegateOfProjectClick = this.project
.compose(Transformers.takeWhen(this.projectClicked));
this.percentageFunded = this.project
.map(Project::percentageFunded)
.map(ProgressBarUtils::progress);
this.percentageFundedProgressBarIsGone = this.project
.map(ProjectUtils::isCompleted);
this.percentageFundedTextViewText = this.project
.map(Project::percentageFunded)
.map(NumberUtils::flooredPercentage);
this.photoUrl = this.project
.map(p -> p.photo() == null ? null : p.photo().med());
this.potdViewGroupIsGone = this.project
.map(p -> metadataForProject(p) != Metadata.POTD);
this.projectCanceledAt = this.project
.filter(p -> p.state().equals(Project.STATE_CANCELED))
.map(Project::stateChangedAt)
.compose(coalesce(new DateTime()));
this.projectFailedAt = this.project
.filter(p -> p.state().equals(Project.STATE_FAILED))
.map(Project::stateChangedAt)
.compose(coalesce(new DateTime()));
this.projectStateViewGroupIsGone = this.project
.map(ProjectUtils::isCompleted)
.map(BooleanUtils::negate);
this.projectSuccessfulAt = this.project
.filter(p -> p.state().equals(Project.STATE_SUCCESSFUL))
.map(Project::stateChangedAt)
.compose(coalesce(new DateTime()));
this.projectSuspendedAt = this.project
.filter(p -> p.state().equals(Project.STATE_SUSPENDED))
.map(Project::stateChangedAt)
.compose(coalesce(new DateTime()));
this.rootCategoryNameForFeatured = this.project
.map(Project::category)
.filter(ObjectUtils::isNotNull)
.map(Category::root)
.filter(ObjectUtils::isNotNull)
.map(Category::name);
this.setDefaultTopPadding = this.metadataViewGroupIsGone;
this.starredViewGroupIsGone = this.project
.map(p -> metadataForProject(p) != Metadata.STARRING);
this.successfullyFundedTextViewIsGone = this.project
.map(p -> !p.state().equals(Project.STATE_SUCCESSFUL));
}
private final PublishSubject<Project> project = PublishSubject.create();
private final PublishSubject<Void> projectClicked = PublishSubject.create();
private final Observable<String> backersCountTextViewText;
private final Observable<Boolean> backingViewGroupIsGone;
private final Observable<String> blurbText;
private final Observable<String> categoryNameTextViewText;
private final Observable<String> deadlineCountdownText;
private final Observable<Boolean> featuredViewGroupIsGone;
private final Observable<String> friendAvatarUrl;
private final Observable<Boolean> friendBackingViewIsHidden;
private final Observable<List<User>> friendsForNamepile;
private final Observable<Boolean> fundingUnsuccessfulTextViewIsGone;
private final Observable<Boolean> imageIsInvisible;
private final Observable<Boolean> metadataViewGroupIsGone;
private final Observable<String> nameText;
private final Observable<Project> notifyDelegateOfProjectClick;
private final Observable<Integer> percentageFunded;
private final Observable<Boolean> percentageFundedProgressBarIsGone;
private final Observable<String> percentageFundedTextViewText;
private final Observable<String> photoUrl;
private final Observable<Boolean> potdViewGroupIsGone;
private final Observable<Project> projectForDeadlineCountdownDetail;
private final Observable<Boolean> projectStateViewGroupIsGone;
private final Observable<DateTime> projectCanceledAt;
private final Observable<DateTime> projectFailedAt;
private final Observable<DateTime> projectSuccessfulAt;
private final Observable<DateTime> projectSuspendedAt;
private final Observable<String> rootCategoryNameForFeatured;
private final Observable<Boolean> setDefaultTopPadding;
private final Observable<Boolean> starredViewGroupIsGone;
private final Observable<Boolean> successfullyFundedTextViewIsGone;
public final Inputs inputs = this;
public final Outputs outputs = this;
@Override
public void configureWith(final @NonNull Project project) {
this.project.onNext(project);
}
@Override
public void projectClicked() {
this.projectClicked.onNext(null);
}
@Override public @NonNull Observable<String> backersCountTextViewText() {
return this.backersCountTextViewText;
}
@Override public @NonNull Observable<Boolean> backingViewGroupIsGone() {
return this.backingViewGroupIsGone;
}
@Override public @NonNull Observable<String> blurbText() {
return this.blurbText;
}
@Override public @NonNull Observable<String> categoryNameTextViewText() {
return this.categoryNameTextViewText;
}
@Override public @NonNull Observable<String> deadlineCountdownText() {
return this.deadlineCountdownText;
}
@Override public @NonNull Observable<Boolean> featuredViewGroupIsGone() {
return this.featuredViewGroupIsGone;
}
@Override public @NonNull Observable<String> friendAvatarUrl() {
return this.friendAvatarUrl;
}
@Override public @NonNull Observable<Boolean> friendBackingViewIsHidden() {
return this.friendBackingViewIsHidden;
}
@Override public @NonNull Observable<List<User>> friendsForNamepile() {
return this.friendsForNamepile;
}
@Override public @NonNull Observable<Boolean> fundingUnsuccessfulTextViewIsGone() {
return this.fundingUnsuccessfulTextViewIsGone;
}
@Override public @NonNull Observable<Boolean> imageIsInvisible() {
return this.imageIsInvisible;
}
@Override public @NonNull Observable<Boolean> metadataViewGroupIsGone() {
return this.metadataViewGroupIsGone;
}
@Override public @NonNull Observable<String> nameText() {
return this.nameText;
}
@Override public @NonNull Observable<Project> notifyDelegateOfProjectClick() {
return this.notifyDelegateOfProjectClick;
}
@Override public @NonNull Observable<Integer> percentageFunded() {
return this.percentageFunded;
}
@Override public @NonNull Observable<Boolean> percentageFundedProgressBarIsGone() {
return this.percentageFundedProgressBarIsGone;
}
@Override public @NonNull Observable<String> percentageFundedTextViewText() {
return this.percentageFundedTextViewText;
}
@Override public @NonNull Observable<String> photoUrl() {
return this.photoUrl;
}
@Override public @NonNull Observable<Boolean> potdViewGroupIsGone() {
return this.potdViewGroupIsGone;
}
@Override public @NonNull Observable<Project> projectForDeadlineCountdownDetail() {
return this.projectForDeadlineCountdownDetail;
}
@Override public @NonNull Observable<Boolean> projectStateViewGroupIsGone() {
return this.projectStateViewGroupIsGone;
}
@Override public @NonNull Observable<DateTime> projectCanceledAt() {
return this.projectCanceledAt;
}
@Override public @NonNull Observable<DateTime> projectFailedAt() {
return this.projectFailedAt;
}
@Override public @NonNull Observable<DateTime> projectSuccessfulAt() {
return this.projectSuccessfulAt;
}
@Override public @NonNull Observable<DateTime> projectSuspendedAt() {
return this.projectSuspendedAt;
}
@Override public @NonNull Observable<String> rootCategoryNameForFeatured() {
return this.rootCategoryNameForFeatured;
}
@Override public @NonNull Observable<Boolean> setDefaultTopPadding() {
return this.setDefaultTopPadding;
}
@Override public @NonNull Observable<Boolean> starredViewGroupIsGone() {
return this.starredViewGroupIsGone;
}
@Override public @NonNull Observable<Boolean> successfullyFundedTextViewIsGone() {
return this.successfullyFundedTextViewIsGone;
}
private enum Metadata {
BACKING, STARRING, POTD, CATEGORY_FEATURED
}
private static @Nullable Metadata metadataForProject(final @NonNull Project project) {
if (project.isBacking()) {
return Metadata.BACKING;
} else if (project.isStarred()) {
return Metadata.STARRING;
} else if (project.isPotdToday()) {
return Metadata.POTD;
} else if (project.isFeaturedToday()) {
return Metadata.CATEGORY_FEATURED;
}
return null;
}
}
}