package com.simplecity.amp_library.ui.presenters;
import android.content.IntentFilter;
import android.support.annotation.NonNull;
import com.f2prateek.rx.receivers.RxBroadcastReceiver;
import com.simplecity.amp_library.ShuttleApplication;
import com.simplecity.amp_library.playback.MusicService;
import com.simplecity.amp_library.playback.PlaybackMonitor;
import com.simplecity.amp_library.ui.views.PlayerView;
import com.simplecity.amp_library.utils.MusicUtils;
import java.util.concurrent.TimeUnit;
import rx.Observable;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
public class PlayerPresenter extends Presenter<PlayerView> {
private long startSeekPos = 0;
private long lastSeekEventTime;
private long currentPlaybackTime;
private boolean currentPlaybackTimeVisible;
@Override
public void unbindView(@NonNull PlayerView view) {
super.unbindView(view);
}
@Override
public void bindView(@NonNull PlayerView view) {
super.bindView(view);
updateTrackInfo();
updateShuffleMode();
updatePlaystate();
updateRepeatMode();
addSubcscription(PlaybackMonitor.getInstance().getProgressObservable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(progress -> view.setSeekProgress((int) (progress * 1000))));
addSubcscription(PlaybackMonitor.getInstance().getCurrentTimeObservable()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(pos -> refreshCurrentTimeText(pos / 1000)));
addSubcscription(Observable.interval(500, TimeUnit.MILLISECONDS)
.onBackpressureDrop()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(aLong -> setCurrentTimeVisibility(MusicUtils.isPlaying() || !currentPlaybackTimeVisible)));
final IntentFilter filter = new IntentFilter();
filter.addAction(MusicService.InternalIntents.META_CHANGED);
filter.addAction(MusicService.InternalIntents.PLAY_STATE_CHANGED);
filter.addAction(MusicService.InternalIntents.SHUFFLE_CHANGED);
filter.addAction(MusicService.InternalIntents.REPEAT_CHANGED);
filter.addAction(MusicService.InternalIntents.SERVICE_CONNECTED);
addSubcscription(RxBroadcastReceiver.create(ShuttleApplication.getInstance(), filter)
.onBackpressureLatest()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(intent -> {
final String action = intent.getAction();
if (action != null) {
switch (action) {
case MusicService.InternalIntents.META_CHANGED:
updateTrackInfo();
break;
case MusicService.InternalIntents.PLAY_STATE_CHANGED:
updateTrackInfo();
updatePlaystate();
break;
case MusicService.InternalIntents.SHUFFLE_CHANGED:
updateTrackInfo();
updateShuffleMode();
break;
case MusicService.InternalIntents.REPEAT_CHANGED:
updateRepeatMode();
break;
case MusicService.InternalIntents.SERVICE_CONNECTED:
updateTrackInfo();
updatePlaystate();
updateShuffleMode();
updateRepeatMode();
break;
}
}
}));
}
private void refreshCurrentTimeText(long playbackTime) {
PlayerView view = getView();
if (playbackTime != this.currentPlaybackTime) {
if (view != null) {
view.currentTimeChanged(playbackTime);
}
}
this.currentPlaybackTime = playbackTime;
}
private void setCurrentTimeVisibility(boolean visible) {
PlayerView view = getView();
if (visible != currentPlaybackTimeVisible) {
if (view != null) {
view.currentTimeVisibilityChanged(visible);
}
}
currentPlaybackTimeVisible = visible;
}
public void updateTrackInfo() {
PlayerView view = getView();
if (view != null) {
view.favoriteChanged();
view.trackInfoChanged(MusicUtils.getSong());
view.currentTimeChanged(MusicUtils.getPosition() / 1000);
view.queueChanged(MusicUtils.getQueuePosition() + 1, MusicUtils.getQueue().size());
}
}
private void updatePlaystate() {
PlayerView view = getView();
if (view != null) {
view.playbackChanged(MusicUtils.isPlaying());
}
}
private void updateShuffleMode() {
PlayerView view = getView();
if (view != null) {
view.repeatChanged(MusicUtils.getRepeatMode());
view.shuffleChanged(MusicUtils.getShuffleMode());
}
}
private void updateRepeatMode() {
PlayerView view = getView();
if (view != null) {
view.repeatChanged(MusicUtils.getRepeatMode());
}
}
public void togglePlayback() {
MusicUtils.playOrPause();
updatePlaystate();
}
public void skip() {
MusicUtils.next();
}
public void prev(boolean allowTrackRestart) {
MusicUtils.previous(allowTrackRestart);
}
public void toggleShuffle() {
MusicUtils.toggleShuffleMode();
updateShuffleMode();
}
public void toggleRepeat() {
MusicUtils.cycleRepeat();
updateRepeatMode();
}
public void seekTo(int progress) {
MusicUtils.seekTo(MusicUtils.getDuration() * progress / 1000);
}
public void scanForward(final int repeatCount, long delta) {
if (repeatCount == 0) {
startSeekPos = MusicUtils.getPosition();
lastSeekEventTime = 0;
} else {
if (delta < 5000) {
// seek at 10x speed for the first 5 seconds
delta = delta * 10;
} else {
// seek at 40x after that
delta = 50000 + (delta - 5000) * 40;
}
long newpos = startSeekPos + delta;
final long duration = MusicUtils.getDuration();
if (newpos >= duration) {
// move to next track
MusicUtils.next();
startSeekPos -= duration; // is OK to go negative
newpos -= duration;
}
if (delta - lastSeekEventTime > 250 || repeatCount < 0) {
MusicUtils.seekTo(newpos);
lastSeekEventTime = delta;
}
}
}
public void scanBackward(final int repeatCount, long delta) {
if (repeatCount == 0) {
startSeekPos = MusicUtils.getPosition();
lastSeekEventTime = 0;
} else {
if (delta < 5000) {
// seek at 10x speed for the first 5 seconds
delta = delta * 10;
} else {
// seek at 40x after that
delta = 50000 + (delta - 5000) * 40;
}
long newpos = startSeekPos - delta;
if (newpos < 0) {
// move to previous track
MusicUtils.previous(true);
final long duration = MusicUtils.getDuration();
startSeekPos += duration;
newpos += duration;
}
if (delta - lastSeekEventTime > 250 || repeatCount < 0) {
MusicUtils.seekTo(newpos);
lastSeekEventTime = delta;
}
}
}
}