package com.marverenic.music.activity.instance;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.NinePatchDrawable;
import android.os.Bundle;
import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.RecyclerView;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import com.marverenic.adapter.DragDropAdapter;
import com.marverenic.adapter.DragDropDecoration;
import com.marverenic.music.JockeyApplication;
import com.marverenic.music.R;
import com.marverenic.music.activity.BaseLibraryActivity;
import com.marverenic.music.adapter.LibraryEmptyState;
import com.marverenic.music.adapter.PlaylistSongSection;
import com.marverenic.music.adapter.ShuffleAllSection;
import com.marverenic.music.data.store.PlayCountStore;
import com.marverenic.music.data.store.PlaylistStore;
import com.marverenic.music.model.Playlist;
import com.marverenic.music.model.Song;
import com.marverenic.music.view.DragBackgroundDecoration;
import com.marverenic.music.view.DragDividerDecoration;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.inject.Inject;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
import timber.log.Timber;
public class PlaylistActivity extends BaseLibraryActivity
implements PopupMenu.OnMenuItemClickListener {
private static final String PLAYLIST_EXTRA = "PlaylistActivity.PLAYLIST";
@Inject PlaylistStore mPlaylistStore;
@Inject PlayCountStore mPlayCountStore;
private List<Song> mSongs;
private Playlist mReference;
private RecyclerView mRecyclerView;
private DragDropAdapter mAdapter;
private ShuffleAllSection mShuffleAllSection;
private PlaylistSongSection mSongSection;
public static Intent newIntent(Context context, Playlist playlist) {
Intent intent = new Intent(context, PlaylistActivity.class);
intent.putExtra(PLAYLIST_EXTRA, playlist);
return intent;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
JockeyApplication.getComponent(this).inject(this);
mRecyclerView = (RecyclerView) findViewById(R.id.list);
setupRecyclerView();
mReference = getIntent().getParcelableExtra(PLAYLIST_EXTRA);
mPlaylistStore.getSongs(mReference)
.compose(bindToLifecycle())
.map(ArrayList::new)
.subscribe(
songs -> {
if (mSongs == null || !mSongs.equals(songs)) {
mSongs = songs;
setupAdapter();
}
}, throwable -> {
Timber.e(throwable, "Failed to get playlist contents");
});
getSupportActionBar().setTitle(mReference.getPlaylistName());
}
@Override
protected int getContentLayoutResource() {
return R.layout.activity_instance;
}
private void setupAdapter() {
if (mRecyclerView == null) {
return;
}
if (mAdapter == null) {
mAdapter = new DragDropAdapter();
mAdapter.setHasStableIds(true);
mAdapter.attach(mRecyclerView);
mAdapter.setEmptyState(new LibraryEmptyState(this) {
@Override
public String getEmptyMessage() {
return getString(R.string.empty_playlist);
}
@Override
public String getEmptyMessageDetail() {
return getString(R.string.empty_playlist_detail);
}
@Override
public String getEmptyAction1Label() {
return "";
}
});
}
if (mSongs == null) {
mSongs = Collections.emptyList();
}
if (mSongSection == null || mShuffleAllSection == null) {
mSongSection = new PlaylistSongSection(this, mPlaylistStore, mSongs, mReference);
mShuffleAllSection = new ShuffleAllSection(this, mSongs);
mAdapter.addSection(mShuffleAllSection);
mAdapter.setDragSection(mSongSection);
} else {
mShuffleAllSection.setData(mSongs);
mSongSection.setData(mSongs);
mAdapter.notifyDataSetChanged();
}
}
private void setupRecyclerView() {
mRecyclerView.addItemDecoration(new DragBackgroundDecoration(R.id.song_drag_root));
mRecyclerView.addItemDecoration(new DragDividerDecoration(
R.id.song_drag_root, this, R.id.empty_layout));
mRecyclerView.addItemDecoration(new DragDropDecoration(
(NinePatchDrawable) ContextCompat.getDrawable(this, R.drawable.list_drag_shadow)));
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRecyclerView.setLayoutManager(layoutManager);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_playlist, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
if (mReference == null) {
return super.onOptionsItemSelected(item);
}
if (item.getItemId() == R.id.menu_playlist_sort) {
PopupMenu sortMenu = new PopupMenu(this, findViewById(R.id.menu_playlist_sort), Gravity.END);
sortMenu.inflate(R.menu.sort_options);
sortMenu.setOnMenuItemClickListener(this);
sortMenu.show();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
public boolean onMenuItemClick(MenuItem item) {
final List<Song> unsortedData = new ArrayList<>(mSongs);
String result;
Comparator<Song> sortComparator;
switch (item.getItemId()) {
case R.id.menu_sort_random:
sortComparator = null;
result = getResources().getString(R.string.message_sorted_playlist_random);
break;
case R.id.menu_sort_name:
sortComparator = Song::compareTo;
result = getResources().getString(R.string.message_sorted_playlist_name);
break;
case R.id.menu_sort_artist:
sortComparator = Song.ARTIST_COMPARATOR;
result = getResources().getString(R.string.message_sorted_playlist_artist);
break;
case R.id.menu_sort_album:
sortComparator = Song.ALBUM_COMPARATOR;
result = getResources().getString(R.string.message_sorted_playlist_album);
break;
case R.id.menu_sort_play:
sortComparator = Song.playCountComparator(mPlayCountStore);
result = getResources().getString(R.string.message_sorted_playlist_play);
break;
case R.id.menu_sort_skip:
sortComparator = Song.skipCountComparator(mPlayCountStore);
result = getResources().getString(R.string.message_sorted_playlist_skip);
break;
case R.id.menu_sort_date_added:
sortComparator = Song.DATE_ADDED_COMPARATOR;
result = getResources().getString(R.string.message_sorted_playlist_date_added);
break;
case R.id.menu_sort_date_played:
sortComparator = Song.playCountComparator(mPlayCountStore);
result = getResources().getString(R.string.message_sorted_playlist_date_played);
break;
default:
return false;
}
mPlayCountStore.refresh()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.map(ignoredValue -> {
if (sortComparator == null) {
Collections.shuffle(mSongs);
} else {
Collections.sort(mSongs, sortComparator);
}
mPlaylistStore.editPlaylist(mReference, mSongs);
return ignoredValue;
})
.subscribe(
ignoredValue -> {
mAdapter.notifyDataSetChanged();
showUndoSortSnackbar(result, unsortedData);
}, throwable -> {
Timber.e(throwable, "onMenuItemClick: Failed to sort playlist");
});
return true;
}
private void showUndoSortSnackbar(String unformattedMessage, List<Song> unsortedData) {
String message = String.format(unformattedMessage, mReference);
Snackbar.make(mRecyclerView, message, Snackbar.LENGTH_LONG)
.setAction(
getResources().getString(R.string.action_undo),
v -> {
mSongs.clear();
mSongs.addAll(unsortedData);
mPlaylistStore.editPlaylist(mReference, unsortedData);
mAdapter.notifyDataSetChanged();
})
.show();
}
}