package com.wigwamlabs.spotify;
public class PlaylistQueue implements Queue, Playlist.Callback {
private final Track[] mTracks = new Track[2];
private final int[] mTrackIds = new int[mTracks.length];
private final boolean mRandom;
private Playlist mPlaylist;
private int mPlaylistIndex = 0;
public PlaylistQueue(Playlist playlist, int initialIndex, boolean random) {
mRandom = random;
mPlaylist = playlist.clone();
mPlaylist.setCallback(this, false);
mPlaylistIndex = initialIndex;
}
@Override
public void destroy() {
for (int i = 0; i < mTracks.length; i++) {
final Track track = mTracks[i];
if (track != null) {
track.destroy();
mTracks[i] = null;
}
}
if (mPlaylist != null) {
mPlaylist.setCallback(null, false);
mPlaylist.destroy();
mPlaylist = null;
}
}
@Override
public Track getTrack(int index) {
if (mTracks[index] == null) {
final Track track = getTrackUncached(index);
if (track != null) {
mTracks[index] = track.clone();
mTrackIds[index] = track.getId();
}
}
return mTracks[index];
}
private Track getTrackUncached(int index) {
final int count = mPlaylist.getCount();
if (mRandom) {
// special case for first track which can be at a specific index
if (index == 0 && mPlaylistIndex >= 0) {
return mPlaylist.getItem((mPlaylistIndex + index) % count);
}
return mPlaylist.getItem((int) (count * Math.random()));
}
return mPlaylist.getItem((mPlaylistIndex + index) % count);
}
@Override
public void next() {
if (mRandom) {
mPlaylistIndex = -1;
} else {
mPlaylistIndex = calculateIndexOfNext();
if (mPlaylistIndex >= mPlaylist.getCount()) {
mPlaylistIndex = 0;
}
}
// remove item 0 in array
if (mTracks[0] != null) {
mTracks[0].destroy();
mTracks[0] = null;
}
for (int i = 0; i < mTracks.length - 1; i++) {
mTracks[i] = mTracks[i + 1];
mTrackIds[i] = mTrackIds[i + 1];
}
mTracks[mTracks.length - 1] = null;
mTrackIds[mTracks.length - 1] = -1;
// check that current is still valid
if (!mRandom) {
for (int i = 0; i < mTracks.length; i++) {
final Track track = mTracks[i];
if (track != null && !trackIsWhereItShould(i)) {
Debug.logQueue("Queue next: removing invalid track '" + track.getName() + "' at " + i);
track.destroy();
mTracks[i] = null;
mTrackIds[i] = -1;
}
}
}
}
private int calculateIndexOfNext() {
if (trackIsWhereItShould(0)) {
Debug.logQueue("Queue next: current track is still at same position " + mPlaylistIndex);
return mPlaylistIndex + 1;
}
// -> current track has moved or been removed
// check if current track has moved
final int currentIndex = findTrack(0);
if (currentIndex >= 0) { // -> moved
Debug.logQueue(String.format("Queue next: current track has moved (%d -> %d), adjusting", mPlaylistIndex, currentIndex));
return currentIndex + 1;
}
// -> current track has been removed
// check if any of the next tracks have been moved
for (int i = 1; i < mTracks.length; i++) {
final int playlistIndex = findTrack(i);
if (playlistIndex >= 0) { // track has moved
Debug.logQueue("Queue next: current track no longer exists in playlist, but the next track exists at pos: " + playlistIndex);
return playlistIndex;
}
}
// -> all known tracks are removed
Debug.logQueue("Queue next: neither current nor next tracks exist in playlist, use same index as before: " + mPlaylistIndex);
return mPlaylistIndex;
}
private int findTrack(int index) {
if (mTracks[index] == null) {
return -1;
}
final int id = mTrackIds[index];
final int count = mPlaylist.getCount();
for (int i = 0; i < count; i++) {
final Track track = mPlaylist.getItem(i);
if (track != null && track.getId() == id) {
return i;
}
}
return -1;
}
private boolean trackIsWhereItShould(int index) {
if (mTracks[index] == null) {
return false;
}
final int id = mTrackIds[index];
final Track track = getTrackUncached(index);
return (track != null && track.getId() == id);
}
@Override
public void onPlaylistUpdateInProgress(boolean done) {
if (done) {
Debug.logQueue("Queue: playlist updated");
//TODO update queue
}
}
@Override
public void onPlaylistRenamed() {
}
@Override
public void onPlaylistStateChanged() {
}
}