package io.kaif.mobile.view.daemon; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.UUID; import javax.inject.Inject; import javax.inject.Singleton; import android.support.v4.util.Pair; import io.kaif.mobile.event.EventPublishSubject; import io.kaif.mobile.event.debate.CreateDebateFailedEvent; import io.kaif.mobile.event.debate.CreateDebateSuccessEvent; import io.kaif.mobile.event.debate.CreateLocalDebateEvent; import io.kaif.mobile.event.debate.DebateEvent; import io.kaif.mobile.model.Debate; import io.kaif.mobile.model.DebateNode; import io.kaif.mobile.model.Vote; import io.kaif.mobile.service.CommaSeparatedParam; import io.kaif.mobile.service.DebateService; import io.kaif.mobile.service.VoteService; import io.kaif.mobile.view.viewmodel.DebateViewModel; import rx.Observable; @Singleton public class DebateDaemon { private final EventPublishSubject<DebateEvent> subject; public EventPublishSubject<DebateEvent> subject() { return subject; } private final DebateService debateService; private final VoteService voteService; public Observable<DebateEvent> getSubject(Class<?>... classes) { return subject.getSubject(classes); } public <T extends DebateEvent> Observable<T> getSubject(Class<T> clazz) { return subject.getSubject(clazz); } @Inject DebateDaemon(DebateService debateService, VoteService voteService) { this.debateService = debateService; this.voteService = voteService; subject = new EventPublishSubject<>(); } public Observable<List<DebateViewModel>> listLatestDebates(String startDebateId) { return debateService.listLatestDebates(startDebateId).flatMap(debates -> { final List<String> ids = mapDebatesToIds(debates); return voteService.listDebateVotes(CommaSeparatedParam.of(ids)) .onErrorReturn(throwable -> Collections.emptyList()) .map(votes -> new Pair<>(debates, votes)) .map(this::mapToDebateViewModel); }); } public Observable<List<DebateViewModel>> listDebates(String articleId) { return debateService.getDebateTree(articleId) .map(this::mapDebateTreeToList) .flatMap(debates -> { final List<String> ids = mapDebatesToIds(debates); return voteService.listDebateVotes(CommaSeparatedParam.of(ids)) .onErrorReturn(throwable -> Collections.emptyList()) .map(votes -> new Pair<>(debates, votes)) .map(this::mapToDebateViewModel); }); } private List<DebateViewModel> mapToDebateViewModel(Pair<List<Debate>, List<Vote>> debatesAndVotes) { final List<Debate> debates = debatesAndVotes.first; final List<Vote> votes = debatesAndVotes.second; List<DebateViewModel> viewModels = new ArrayList<>(); for (Debate debate : debates) { viewModels.add(new DebateViewModel(debate, loadVote(votes, debate.getDebateId()))); } return viewModels; } private Vote loadVote(List<Vote> votes, String targetId) { for (Vote vote : votes) { if (vote.matches(targetId)) { return vote; } } return Vote.abstain(targetId); } private List<String> mapDebatesToIds(List<Debate> debates) { List<String> ids = new ArrayList<>(); for (Debate debate : debates) { ids.add(debate.getDebateId()); } return ids; } private List<Debate> mapDebateTreeToList(DebateNode debateNode) { List<Debate> debates = new ArrayList<>(); if (debateNode.getDebate() != null) { debates.add(debateNode.getDebate()); } for (DebateNode child : debateNode.getChildren()) { debates.addAll(mapDebateTreeToList(child)); } return debates; } public void debate(String articleId, String parentDebateId, int level, String content) { final String localId = UUID.randomUUID().toString(); subject.onNext(new CreateLocalDebateEvent(articleId, localId, parentDebateId, level, content)); debateService.debate(new DebateService.CreateDebateEntry(articleId, parentDebateId, content)) .subscribe(debate -> subject.onNext(new CreateDebateSuccessEvent(localId, debate)), throwable -> subject.onNext(new CreateDebateFailedEvent(localId))); } }