package io.nextop.demo.flip;
import android.net.Uri;
import io.nextop.Id;
import io.nextop.Message;
import io.nextop.Nextop;
import io.nextop.WireValue;
import io.nextop.vm.ImageViewModel;
import rx.android.schedulers.AndroidSchedulers;
import rx.functions.Action0;
import rx.functions.Action1;
import rx.functions.Func2;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
public class FlipViewModelManager extends ThinViewModelManager<FlipViewModel> {
FlipViewModelManager(Nextop nextop) {
super(nextop);
}
// CONTROLLER
void addFrame(Id flipId, final FrameViewModel frameVm) {
if (null != frameVm.imageVm.bitmap) {
// TODO vms should be treated as immutable
// upload the image
Message update = Message.newBuilder()
.setRoute("PUT http://" + Flip.REMOTE + "/flip/$flip-id/frame/$frame-id")
.set("flip-id", flipId)
.set("frame-id", frameVm.id)
.build();
Id localId = nextop.send(Nextop.Layer.bitmap(update, frameVm.imageVm.bitmap), null).getId();
frameVm.imageVm = ImageViewModel.local(localId);
}
update(flipId, new Func2<FlipViewModel, RxState, FlipViewModel>() {
@Override
public FlipViewModel call(FlipViewModel flipVm, RxState rxState) {
flipVm.add(new FlipViewModel.FrameState(frameVm, -1L));
return flipVm;
}
});
}
private void add(Id flipId, final Message results) {
final List<WireValue> values = results.getContent().asList();
if (!values.isEmpty()) {
update(flipId, new Func2<FlipViewModel, RxState, FlipViewModel>() {
@Override
public FlipViewModel call(FlipViewModel flipVm, RxState rxState) {
for (WireValue value : values) {
Map<WireValue, WireValue> m = value.asMap();
// FIXME asId
Id frameId = Id.valueOf(m.get(WireValue.of("frame_id")).asString());
long creationTime = m.get(WireValue.of("creation_time")).asLong();
String imageUrl = m.get(WireValue.of("image_url")).asString();
long updateIndex = m.get(WireValue.of("most_recent_update_index")).asLong();
FrameViewModel frameVm = new FrameViewModel(frameId);
frameVm.creationTime = creationTime;
frameVm.imageVm = ImageViewModel.remote(Uri.parse(imageUrl));
flipVm.add(new FlipViewModel.FrameState(frameVm, updateIndex));
}
return flipVm;
}
});
}
}
// VMM
@Override
protected void startUpdates(final FlipViewModel flipVm, final RxState state) {
// sync
// get updates. updates are (frame id, creation time)
// in flipvm sort by creation time to get the final ordering
Message sync = Message.newBuilder()
.setRoute("GET http://" + Flip.REMOTE + "/flip/$flip-id/frame")
.set("flip-id", flipVm.id)
.build();
// FIXME remove
String uriString = sync.toUriString();
state.bind(nextop.send(sync))
.doOnNext(new Action1<Message>() {
@Override
public void call(Message message) {
add(flipVm.id, message);
state.sync();
}
}).doOnCompleted(new Action0() {
@Override
public void call() {
// start the poller
Action0 poller = new Action0() {
@Override
public void call() {
Message poll = Message.newBuilder()
.setRoute("GET http://" + Flip.REMOTE + "/flip/$flip-id/frame")
.set("flip-id", flipVm.id)
.set("after", flipVm.getMaxUpdateIndex())
.build();
state.bind(nextop.send(poll))
.doOnNext(new Action1<Message>() {
@Override
public void call(final Message message) {
add(flipVm.id, message);
}
}).subscribe();
}
};
state.bind(AndroidSchedulers.mainThread().createWorker().schedulePeriodically(poller,
pollTimeoutMs, pollTimeoutMs, TimeUnit.MILLISECONDS));
}
}).subscribe();
}
@Override
protected FlipViewModel create(Id id) {
return new FlipViewModel(id);
}
}