package fr.tvbarthel.cheerleader.sampleapp;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.StringRes;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.View;
import android.view.ViewTreeObserver;
import android.widget.ProgressBar;
import android.widget.TextView;
import com.netcosports.recyclergesture.library.swipe.SwipeToDismissDirection;
import com.netcosports.recyclergesture.library.swipe.SwipeToDismissGesture;
import com.netcosports.recyclergesture.library.swipe.SwipeToDismissStrategy;
import java.util.ArrayList;
import de.keyboardsurfer.android.widget.crouton.Crouton;
import fr.tvbarthel.cheerleader.library.client.CheerleaderClient;
import fr.tvbarthel.cheerleader.library.client.SoundCloudTrack;
import fr.tvbarthel.cheerleader.library.client.SoundCloudUser;
import fr.tvbarthel.cheerleader.library.player.CheerleaderPlayer;
import fr.tvbarthel.cheerleader.library.player.CheerleaderPlaylistListener;
import fr.tvbarthel.cheerleader.sampleapp.adapter.TracksAdapter;
import fr.tvbarthel.cheerleader.sampleapp.ui.ArtistView;
import fr.tvbarthel.cheerleader.sampleapp.ui.CroutonView;
import fr.tvbarthel.cheerleader.sampleapp.ui.PlaybackView;
import fr.tvbarthel.cheerleader.sampleapp.ui.TrackView;
import rx.Subscriber;
import rx.Subscription;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
public class ArtistActivity extends ActionBarActivity implements
PlaybackView.Listener, CheerleaderPlaylistListener, TracksAdapter.Listener {
// bundle keys
private static final String BUNDLE_KEY_ARTIST_NAME = "artist_activity_bundle_key_artist_name";
// sound cloud
private CheerleaderClient mCheerleaderClient;
private CheerleaderPlayer mCheerleaderPlayer;
// tracks widget
private ProgressBar mProgress;
private TextView mCallback;
private RecyclerView mRetrieveTracksRecyclerView;
private TrackView.Listener mRetrieveTracksListener;
private ArrayList<SoundCloudTrack> mRetrievedTracks;
private TracksAdapter mAdapter;
private ArtistView mArtistView;
private RecyclerView.OnScrollListener mRetrieveTracksScrollListener;
private int mScrollY;
private int mRetrieveTrackListPaddingBottom;
private int mRetrieveTrackListPaddingTop;
// player widget
private RecyclerView mPlaylistRecyclerView;
private PlaybackView mPlaybackView;
private TracksAdapter mPlaylistAdapter;
private ArrayList<SoundCloudTrack> mPlaylistTracks;
private TrackView.Listener mPlaylistTracksListener;
// banner
private View mBanner;
//Crouton, contextual toast.
private Crouton mCrouton;
private CroutonView mCroutonView;
// Subscription
private Subscription mTracksSubscription;
private Subscription mProfileSubscription;
/**
* Start an ArtistActivity for a given artist name.
* Start activity pattern.
*
* @param context context used to start the activity.
* @param artistName name of the artist.
*/
public static void startActivity(Context context, String artistName) {
Intent i = new Intent(context, ArtistActivity.class);
i.putExtra(BUNDLE_KEY_ARTIST_NAME, artistName);
context.startActivity(i);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_artist);
String artistName = getExtraArtistName();
mCheerleaderClient = new CheerleaderClient.Builder()
.from(this)
.with(R.string.sound_cloud_client_id)
.supports(artistName)
.build();
mCheerleaderPlayer = new CheerleaderPlayer.Builder()
.from(this)
.with(R.string.sound_cloud_client_id)
.notificationActivity(ArtistActivity.class)
.notificationIcon(R.drawable.ic_notification)
.build();
mProgress = ((ProgressBar) findViewById(R.id.activity_artist_progress));
mCallback = ((TextView) findViewById(R.id.activity_artist_callback));
mBanner = findViewById(R.id.activity_artist_banner);
mRetrieveTracksRecyclerView = ((RecyclerView) findViewById(R.id.activity_artist_list));
initRetrieveTracksRecyclerView();
mPlaylistRecyclerView = ((RecyclerView) findViewById(R.id.activity_artist_playlist));
initPlaylistTracksRecyclerView();
setTrackListPadding();
// check if tracks are already loaded into the player.
ArrayList<SoundCloudTrack> currentsTracks = mCheerleaderPlayer.getTracks();
if (currentsTracks != null) {
mPlaylistTracks.addAll(currentsTracks);
}
// synchronize the player view with the current player (loaded track, playing state, etc.)
mPlaybackView.synchronize(mCheerleaderPlayer);
getArtistData();
}
@Override
protected void onResume() {
super.onResume();
mCheerleaderPlayer.registerPlayerListener(mPlaybackView);
mCheerleaderPlayer.registerPlayerListener(mPlaylistAdapter);
mCheerleaderPlayer.registerPlaylistListener(this);
}
@Override
protected void onPause() {
super.onPause();
mCheerleaderPlayer.unregisterPlayerListener(mPlaybackView);
mCheerleaderPlayer.unregisterPlayerListener(mPlaylistAdapter);
mCheerleaderPlayer.unregisterPlaylistListener(this);
}
@Override
protected void onDestroy() {
super.onDestroy();
mCheerleaderClient.close();
mCheerleaderPlayer.destroy();
releaseSubscription(mProfileSubscription);
releaseSubscription(mTracksSubscription);
}
@Override
public void onBackPressed() {
if (mPlaybackView.getTop() < mPlaylistRecyclerView.getHeight() - mPlaybackView.getHeight()) {
mPlaylistRecyclerView.getLayoutManager().smoothScrollToPosition(mPlaylistRecyclerView, null, 0);
} else {
super.onBackPressed();
}
}
@Override
public void onTogglePlayPressed() {
mCheerleaderPlayer.togglePlayback();
}
@Override
public void onPreviousPressed() {
mCheerleaderPlayer.previous();
}
@Override
public void onNextPressed() {
mCheerleaderPlayer.next();
}
@Override
public void onSeekToRequested(int milli) {
mCheerleaderPlayer.seekTo(milli);
}
@Override
public void onTrackAdded(SoundCloudTrack track) {
if (mPlaylistTracks.isEmpty()) {
mPlaylistRecyclerView.animate().translationY(0);
mRetrieveTracksRecyclerView.setPadding(0,
mRetrieveTrackListPaddingTop, 0, mRetrieveTrackListPaddingBottom);
}
mPlaylistTracks.add(track);
mPlaylistAdapter.notifyDataSetChanged();
}
@Override
public void onTrackRemoved(SoundCloudTrack track, boolean isEmpty) {
if (mPlaylistTracks.remove(track)) {
mPlaylistAdapter.notifyDataSetChanged();
}
if (isEmpty) {
mPlaylistRecyclerView.animate().translationY(mPlaybackView.getHeight());
mRetrieveTracksRecyclerView.setPadding(0, mRetrieveTrackListPaddingTop, 0, 0);
}
}
// Adapter callbacks.
@Override
public void onTrackDismissed(int i) {
mCheerleaderPlayer.removeTrack(i);
}
/**
* Used to position the track list at the bottom of the screen.
*/
private void setTrackListPadding() {
mPlaylistRecyclerView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() {
@Override
public boolean onPreDraw() {
mPlaylistRecyclerView.getViewTreeObserver().removeOnPreDrawListener(this);
int headerListHeight = getResources().getDimensionPixelOffset(R.dimen.playback_view_height);
mPlaylistRecyclerView.setPadding(0, mPlaylistRecyclerView.getHeight() - headerListHeight, 0, 0);
mPlaylistRecyclerView.setAdapter(mPlaylistAdapter);
// attach the dismiss gesture.
new SwipeToDismissGesture.Builder(SwipeToDismissDirection.HORIZONTAL)
.on(mPlaylistRecyclerView)
.apply(new DismissStrategy())
.backgroundColor(getResources().getColor(R.color.grey))
.build();
// hide if current play playlist is empty.
if (mPlaylistTracks.isEmpty()) {
mPlaybackView.setTranslationY(headerListHeight);
}
return true;
}
});
}
/**
* Used to retrieved the tracks of the artist as well as artist details.
*/
private void getArtistData() {
mRetrievedTracks.clear();
mAdapter.notifyDataSetChanged();
mTracksSubscription =
mCheerleaderClient.getArtistTracks()
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(displayTracks());
mProfileSubscription =
mCheerleaderClient.getArtistProfile()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(displayArtist());
}
/**
* Used to retrieve the artist name for the bundle.
*
* @return artist name.
*/
private String getExtraArtistName() {
Bundle extras = getIntent().getExtras();
if (extras == null || !extras.containsKey(BUNDLE_KEY_ARTIST_NAME)) {
return ""; // activity started through the notification pending intent
}
return extras.getString(BUNDLE_KEY_ARTIST_NAME);
}
private Subscriber<SoundCloudUser> displayArtist() {
return new Subscriber<SoundCloudUser>() {
@Override
public void onCompleted() {
releaseSubscription(mProfileSubscription);
}
@Override
public void onError(Throwable e) {
releaseSubscription(mProfileSubscription);
}
@Override
public void onNext(SoundCloudUser soundCloudUser) {
mArtistView.setModel(soundCloudUser);
}
};
}
private Subscriber<ArrayList<SoundCloudTrack>> displayTracks() {
return new Subscriber<ArrayList<SoundCloudTrack>>() {
@Override
public void onCompleted() {
releaseSubscription(mTracksSubscription);
}
@Override
public void onError(Throwable e) {
releaseSubscription(mTracksSubscription);
mProgress.setVisibility(View.INVISIBLE);
mCallback.setVisibility(View.VISIBLE);
}
@Override
public void onNext(ArrayList<SoundCloudTrack> soundCloudTracks) {
mProgress.setVisibility(View.INVISIBLE);
mRetrievedTracks.clear();
mRetrievedTracks.addAll(soundCloudTracks);
mAdapter.notifyDataSetChanged();
}
};
}
private void initRetrieveTracksRecyclerView() {
mArtistView = new ArtistView(this);
mRetrieveTracksListener = new TrackView.Listener() {
@Override
public void onTrackClicked(SoundCloudTrack track) {
if (mCheerleaderPlayer.getTracks().contains(track)) {
mCheerleaderPlayer.play(track);
} else {
boolean playNow = !mCheerleaderPlayer.isPlaying();
mCheerleaderPlayer.addTrack(track, playNow);
mPlaylistAdapter.notifyDataSetChanged();
if (!playNow) {
toast(R.string.toast_track_added);
}
}
}
};
mRetrievedTracks = new ArrayList<>();
mRetrieveTracksRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
mAdapter = new TracksAdapter(mRetrieveTracksListener, mRetrievedTracks);
mAdapter.setHeaderView(mArtistView);
mRetrieveTracksRecyclerView.setAdapter(mAdapter);
mScrollY = 0;
mRetrieveTracksScrollListener = new RecyclerView.OnScrollListener() {
@Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy);
mScrollY += dy;
mBanner.setTranslationY(-mScrollY / 2f);
}
};
mRetrieveTracksRecyclerView.setOnScrollListener(mRetrieveTracksScrollListener);
mRetrieveTrackListPaddingTop = getResources().getDimensionPixelSize(R.dimen.track_list_padding_top);
mRetrieveTrackListPaddingBottom = getResources().getDimensionPixelSize(R.dimen.playback_view_height);
mRetrieveTracksRecyclerView.setPadding(0, mRetrieveTrackListPaddingTop, 0, 0);
}
private void initPlaylistTracksRecyclerView() {
mPlaylistTracksListener = new TrackView.Listener() {
@Override
public void onTrackClicked(SoundCloudTrack track) {
mCheerleaderPlayer.play(track);
}
};
mPlaybackView = new PlaybackView(this);
mPlaybackView.setListener(this);
mPlaylistTracks = new ArrayList<>();
mPlaylistAdapter = new TracksAdapter(mPlaylistTracksListener, mPlaylistTracks);
mPlaylistAdapter.setHeaderView(mPlaybackView);
mPlaylistRecyclerView.setLayoutManager(new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false));
mPlaylistAdapter.setAdapterListener(this);
}
/**
* Used to display crouton toast.
*
* @param message text to be displayed.
*/
private void toast(@StringRes int message) {
if (mCrouton != null) {
mCrouton.cancel();
mCrouton = null;
}
mCroutonView = new CroutonView(this, getString(message));
mCrouton = Crouton.make(this, mCroutonView, R.id.activity_artist_main_container);
mCrouton.show();
}
/**
* Swipe to dismiss strategy used to disable swipe to dismiss on the header.
*/
private static class DismissStrategy extends SwipeToDismissStrategy {
@Override
public SwipeToDismissDirection getDismissDirection(int position) {
if (position == 0) {
return SwipeToDismissDirection.NONE;
} else {
return SwipeToDismissDirection.HORIZONTAL;
}
}
}
/**
* Release a subscription.
*
* @param subscription subscription to release.
*/
private void releaseSubscription(Subscription subscription) {
if (subscription != null && !subscription.isUnsubscribed()) {
subscription.unsubscribe();
}
}
}