package com.hitherejoe.mvvm_hackernews.data;
import android.content.Context;
import com.hitherejoe.mvvm_hackernews.HackerNewsApplication;
import com.hitherejoe.mvvm_hackernews.model.Comment;
import com.hitherejoe.mvvm_hackernews.model.Post;
import com.hitherejoe.mvvm_hackernews.model.User;
import com.hitherejoe.mvvm_hackernews.data.remote.HackerNewsService;
import com.hitherejoe.mvvm_hackernews.injection.component.DaggerDataManagerComponent;
import com.hitherejoe.mvvm_hackernews.injection.module.DataManagerModule;
import java.util.List;
import javax.inject.Inject;
import rx.Observable;
import rx.Scheduler;
import rx.functions.Func1;
public class DataManager {
@Inject protected HackerNewsService mHackerNewsService;
@Inject protected Scheduler mSubscribeScheduler;
public DataManager(Context context) {
injectDependencies(context);
}
/* This constructor is provided so we can set up a DataManager with mocks from unit test.
* At the moment this is not possible to do with Dagger because the Gradle APT plugin doesn't
* work for the unit test variant, plus Dagger 2 doesn't provide a nice way of overriding
* modules */
public DataManager(HackerNewsService watchTowerService,
Scheduler subscribeScheduler) {
mHackerNewsService = watchTowerService;
mSubscribeScheduler = subscribeScheduler;
}
protected void injectDependencies(Context context) {
DaggerDataManagerComponent.builder()
.applicationComponent(HackerNewsApplication.get(context).getComponent())
.dataManagerModule(new DataManagerModule())
.build()
.inject(this);
}
public Scheduler getScheduler() {
return mSubscribeScheduler;
}
public Observable<Post> getTopStories() {
return mHackerNewsService.getTopStories()
.concatMap(new Func1<List<Long>, Observable<? extends Post>>() {
@Override
public Observable<? extends Post> call(List<Long> longs) {
return getPostsFromIds(longs);
}
});
}
public Observable<Post> getUserPosts(String user) {
return mHackerNewsService.getUser(user)
.concatMap(new Func1<User, Observable<? extends Post>>() {
@Override
public Observable<? extends Post> call(User user) {
return getPostsFromIds(user.submitted);
}
});
}
public Observable<Post> getPostsFromIds(List<Long> storyIds) {
return Observable.from(storyIds)
.concatMap(new Func1<Long, Observable<Post>>() {
@Override
public Observable<Post> call(Long aLong) {
return mHackerNewsService.getStoryItem(String.valueOf(aLong));
}
}).flatMap(new Func1<Post, Observable<Post>>() {
@Override
public Observable<Post> call(Post post) {
return post.title != null ? Observable.just(post) : Observable.<Post>empty();
}
});
}
public Observable<Comment> getPostComments(final List<Long> commentIds, final int depth) {
return Observable.from(commentIds)
.concatMap(new Func1<Long, Observable<Comment>>() {
@Override
public Observable<Comment> call(Long aLong) {
return mHackerNewsService.getCommentItem(String.valueOf(aLong));
}
}).concatMap(new Func1<Comment, Observable<Comment>>() {
@Override
public Observable<Comment> call(Comment comment) {
comment.depth = depth;
if (comment.kids == null || comment.kids.isEmpty()) {
return Observable.just(comment);
} else {
return Observable.just(comment)
.mergeWith(getPostComments(comment.kids, depth + 1));
}
}
}).filter(new Func1<Comment, Boolean>() {
@Override
public Boolean call(Comment comment) {
return (comment.by != null && !comment.by.trim().isEmpty()
&& comment.text != null && !comment.text.trim().isEmpty());
}
});
}
}