package com.marverenic.music.viewmodel; import android.app.Activity; import android.content.Context; import android.databinding.BaseObservable; import android.databinding.Bindable; import android.support.v4.app.FragmentManager; import android.support.v7.widget.PopupMenu; import android.view.Gravity; import android.view.View; import com.marverenic.music.BR; import com.marverenic.music.JockeyApplication; import com.marverenic.music.R; import com.marverenic.music.activity.BaseActivity; import com.marverenic.music.activity.BaseLibraryActivity; import com.marverenic.music.activity.instance.AlbumActivity; import com.marverenic.music.activity.instance.ArtistActivity; import com.marverenic.music.data.store.MusicStore; import com.marverenic.music.data.store.PreferenceStore; import com.marverenic.music.dialog.AppendPlaylistDialogFragment; import com.marverenic.music.fragments.BaseFragment; import com.marverenic.music.model.Song; import com.marverenic.music.player.PlayerController; import com.trello.rxlifecycle.ActivityEvent; import com.trello.rxlifecycle.FragmentEvent; import com.trello.rxlifecycle.LifecycleTransformer; import java.util.List; import javax.inject.Inject; import rx.Observable; import rx.Subscription; import timber.log.Timber; public class SongViewModel extends BaseObservable { private static final String TAG_PLAYLIST_DIALOG = "SongViewModel.PlaylistDialog"; @Inject MusicStore mMusicStore; @Inject PreferenceStore mPrefStore; @Inject PlayerController mPlayerController; private Context mContext; private Activity mActivity; private FragmentManager mFragmentManager; private LifecycleTransformer<?> mLifecycleTransformer; private Subscription mNowPlayingSubscription; private List<Song> mSongList; private int mIndex; private boolean mIsPlaying; private Song mReference; public SongViewModel(BaseActivity activity, List<Song> songs) { this(activity, activity.getSupportFragmentManager(), activity.bindUntilEvent(ActivityEvent.DESTROY), songs); } public SongViewModel(BaseFragment fragment, List<Song> songs) { this(fragment.getActivity(), fragment.getFragmentManager(), fragment.bindUntilEvent(FragmentEvent.DESTROY), songs); } public SongViewModel(Activity activity, FragmentManager fragmentManager, LifecycleTransformer<?> lifecycleTransformer, List<Song> songs) { mContext = activity; mActivity = activity; mFragmentManager = fragmentManager; mLifecycleTransformer = lifecycleTransformer; mSongList = songs; JockeyApplication.getComponent(mContext).inject(this); } public void setIndex(int index) { setSong(mSongList, index); } protected int getIndex() { return mIndex; } protected Song getReference() { return mReference; } protected List<Song> getSongs() { return mSongList; } private <T> LifecycleTransformer<T> bindToLifecycle() { //noinspection unchecked return (LifecycleTransformer<T>) mLifecycleTransformer; } protected Observable<Boolean> isPlaying() { return mPlayerController.getNowPlaying() .map(playing -> playing != null && playing.equals(getReference())); } public void setSong(List<Song> songList, int index) { mSongList = songList; mIndex = index; mReference = songList.get(index); if (mNowPlayingSubscription != null) { mNowPlayingSubscription.unsubscribe(); } mIsPlaying = false; mNowPlayingSubscription = isPlaying() .compose(bindToLifecycle()) .subscribe(isPlaying -> { mIsPlaying = isPlaying; notifyPropertyChanged(BR.nowPlayingIndicatorVisibility); }, throwable -> { Timber.e(throwable, "Failed to update playing indicator"); }); notifyPropertyChanged(BR.title); notifyPropertyChanged(BR.detail); } @Bindable public int getNowPlayingIndicatorVisibility() { if (mIsPlaying) { return View.VISIBLE; } else { return View.GONE; } } @Bindable public String getTitle() { return mReference.getSongName(); } @Bindable public String getDetail() { return mContext.getString(R.string.format_compact_song_info, mReference.getArtistName(), mReference.getAlbumName()); } public View.OnClickListener onClickSong() { return v -> { mPlayerController.setQueue(mSongList, mIndex); mPlayerController.play(); if (mPrefStore.openNowPlayingOnNewQueue() && mActivity instanceof BaseLibraryActivity) { ((BaseLibraryActivity) mActivity).expandBottomSheet(); } }; } public View.OnClickListener onClickMenu() { return v -> { final PopupMenu menu = new PopupMenu(mContext, v, Gravity.END); menu.inflate(R.menu.instance_song); menu.setOnMenuItemClickListener(onMenuItemClick()); menu.show(); }; } private PopupMenu.OnMenuItemClickListener onMenuItemClick() { return menuItem -> { switch (menuItem.getItemId()) { case R.id.menu_item_queue_item_next: mPlayerController.queueNext(mReference); return true; case R.id.menu_item_queue_item_last: mPlayerController.queueLast(mReference); return true; case R.id.menu_item_navigate_to_artist: mMusicStore.findArtistById(mReference.getArtistId()).subscribe( artist -> { mContext.startActivity(ArtistActivity.newIntent(mContext, artist)); }, throwable -> { Timber.e(throwable, "Failed to find artist"); }); return true; case R.id.menu_item_navigate_to_album: mMusicStore.findAlbumById(mReference.getAlbumId()).subscribe( album -> { mContext.startActivity(AlbumActivity.newIntent(mContext, album)); }, throwable -> { Timber.e(throwable, "Failed to find album", throwable); }); return true; case R.id.menu_item_add_to_playlist: new AppendPlaylistDialogFragment.Builder(mContext, mFragmentManager) .setSongs(mReference) .showSnackbarIn(R.id.list) .show(TAG_PLAYLIST_DIALOG); return true; } return false; }; } }