package pasta.music.adapters;
import android.animation.ArgbEvaluator;
import android.animation.ValueAnimator;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.app.Fragment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.graphics.Palette;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.afollestad.async.Action;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.drawable.GlideDrawable;
import com.bumptech.glide.request.animation.GlideAnimation;
import com.bumptech.glide.request.target.BitmapImageViewTarget;
import com.bumptech.glide.request.target.GlideDrawableImageViewTarget;
import com.google.android.flexbox.FlexboxLayout;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import pasta.music.Pasta;
import pasta.music.R;
import pasta.music.activities.PlayerActivity;
import pasta.music.data.AlbumListData;
import pasta.music.data.ArtistListData;
import pasta.music.data.PlaylistListData;
import pasta.music.data.TrackListData;
import pasta.music.dialogs.AddToPlaylistDialog;
import pasta.music.fragments.AlbumFragment;
import pasta.music.fragments.ArtistFragment;
import pasta.music.utils.ImageUtils;
import pasta.music.utils.PreferenceUtils;
import pasta.music.utils.StaticUtils;
import pasta.music.views.CustomImageView;
public class TrackAdapter extends RecyclerView.Adapter<TrackAdapter.ViewHolder> {
private List<TrackListData> original;
private List<TrackListData> list;
private AppCompatActivity activity;
private Pasta pasta;
private int menuRes = R.menu.menu_track;
private PlaylistListData playlistdata;
private boolean thumbnails, cards, trackList, palette, dark;
public TrackAdapter(AppCompatActivity activity, List<TrackListData> list) {
original = list;
if (list != null) {
this.list = new ArrayList<>();
try {
this.list.addAll(original);
} catch (Exception e) {
e.printStackTrace();
}
}
this.activity = activity;
pasta = (Pasta) activity.getApplicationContext();
thumbnails = PreferenceUtils.isThumbnails(activity);
cards = PreferenceUtils.isCards(activity);
trackList = PreferenceUtils.isListTracks(activity);
palette = PreferenceUtils.isPalette(activity);
dark = PreferenceUtils.isDarkTheme(activity);
}
public void setPlaylistBehavior(PlaylistListData data) {
menuRes = R.menu.menu_playlist_track;
playlistdata = data;
}
public void setAlbumBehavior() {
menuRes = R.menu.menu_album_track;
}
public void swapData(List<TrackListData> list) {
original = list;
this.list = new ArrayList<>();
this.list.addAll(list);
notifyDataSetChanged();
}
public void removeData(int position) {
if (position < 0 || position > original.size()) return;
original.remove(original.indexOf(list.get(position)));
list.remove(position);
notifyItemRemoved(position);
}
public void removeData(TrackListData data) {
original.remove(original.indexOf(data));
int pos = list.indexOf(data);
list.remove(pos);
notifyItemRemoved(pos);
}
public void sort(int order) {
switch (order) {
case PreferenceUtils.ORDER_ADDED:
list = new ArrayList<>();
list.addAll(original);
break;
case PreferenceUtils.ORDER_NAME:
Collections.sort(list, new Comparator<TrackListData>() {
public int compare(TrackListData first, TrackListData second) {
return first.trackName.compareTo(second.trackName);
}
});
break;
case PreferenceUtils.ORDER_ARTIST:
Collections.sort(list, new Comparator<TrackListData>() {
public int compare(TrackListData first, TrackListData second) {
if (first.artists.size() > 0 && second.artists.size() > 0)
return first.artists.get(0).artistName.compareTo(second.artists.get(0).artistName);
else return 0;
}
});
break;
case PreferenceUtils.ORDER_ALBUM:
Collections.sort(list, new Comparator<TrackListData>() {
public int compare(TrackListData first, TrackListData second) {
return first.albumName.compareTo(second.albumName);
}
});
break;
case PreferenceUtils.ORDER_LENGTH:
Collections.sort(list, new Comparator<TrackListData>() {
public int compare(TrackListData first, TrackListData second) {
return first.trackDuration.compareTo(second.trackDuration);
}
});
break;
case PreferenceUtils.ORDER_RANDOM:
Collections.shuffle(list);
break;
}
notifyDataSetChanged();
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == 0) {
return new ArtistsViewHolder(LayoutInflater.from(activity).inflate(cards ? R.layout.artists_item_card : R.layout.artists_item_tile, null));
} else {
return new TrackViewHolder(LayoutInflater.from(activity).inflate(trackList ? R.layout.track_item : (cards ? R.layout.track_item_card : R.layout.track_item_tile), null));
}
}
@Override
public void onBindViewHolder(final ViewHolder holder, int position) {
if (holder instanceof ArtistsViewHolder) {
FlexboxLayout layout = (FlexboxLayout) holder.v.findViewById(R.id.artists);
layout.removeAllViewsInLayout();
holder.v.findViewById(R.id.progress).setAlpha(1f);
new Action<ArrayList<ArtistListData>>() {
@NonNull
@Override
public String id() {
return "getCommonArtists";
}
@Nullable
@Override
protected ArrayList<ArtistListData> run() throws InterruptedException {
ArrayList<ArtistListData> allArtists = new ArrayList<>();
for (TrackListData track : list) {
allArtists.addAll(track.artists);
}
HashMap<String, Integer> frequencies = new HashMap<>();
for (int i = 0; i < allArtists.size(); i++) {
int frequency = 0;
ArtistListData artist1 = allArtists.get(i);
for (ArtistListData artist2 : allArtists) {
if (artist1.artistId.matches(artist2.artistId)) frequency++;
}
frequencies.put(artist1.artistId, frequency);
}
List<Map.Entry<String, Integer>> entries = new ArrayList<>(frequencies.entrySet());
Collections.sort(entries, new Comparator<Map.Entry<String, Integer>>() {
public int compare(Map.Entry<String, Integer> lhs, Map.Entry<String, Integer> rhs) {
return lhs.getValue() < rhs.getValue() ? -1 : (lhs.getValue().equals(rhs.getValue()) ? 0 : 1);
}
});
ArrayList<ArtistListData> commonArtists = new ArrayList<>();
for (int i = 0; i < 5 && i < entries.size(); i++) {
ArtistListData artist = pasta.getArtist(entries.get(i).getKey());
if (artist != null) commonArtists.add(artist);
}
return commonArtists;
}
@Override
protected void done(@Nullable ArrayList<ArtistListData> result) {
if (result != null && result.size() > 0) {
FlexboxLayout layout = (FlexboxLayout) holder.v.findViewById(R.id.artists);
layout.removeAllViewsInLayout();
for (ArtistListData artist : result) {
View v = LayoutInflater.from(activity).inflate(R.layout.artist_item_chip, null);
((TextView) v.findViewById(R.id.title)).setText(artist.artistName);
Glide.with(activity).load(artist.artistImage).into(new GlideDrawableImageViewTarget((ImageView) v.findViewById(R.id.image)) {
@Override
public void onResourceReady(GlideDrawable resource, GlideAnimation<? super GlideDrawable> animation) {
((CustomImageView) getView()).transition(resource);
}
});
v.setTag(artist);
v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Bundle args = new Bundle();
args.putParcelable("artist", (ArtistListData) v.getTag());
Fragment f = new ArtistFragment();
f.setArguments(args);
activity.getSupportFragmentManager().beginTransaction().replace(R.id.fragment, f).addToBackStack(null).commit();
}
});
layout.addView(v);
}
layout.setVisibility(View.VISIBLE);
} else holder.v.findViewById(R.id.artists).setVisibility(View.GONE);
ValueAnimator animator = ValueAnimator.ofFloat(1f, 0f);
animator.setDuration(150);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
holder.v.findViewById(R.id.progress).setAlpha((float) valueAnimator.getAnimatedValue());
}
});
animator.start();
}
}.execute();
} else if (holder instanceof TrackViewHolder) {
position -= 1;
View trackMenu = holder.v.findViewById(R.id.menu);
if (trackMenu.getVisibility() == View.GONE) {
trackMenu.setVisibility(View.VISIBLE);
}
trackMenu.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
PopupMenu popup = new PopupMenu(v.getContext(), v);
MenuInflater inflater = popup.getMenuInflater();
inflater.inflate(menuRes, popup.getMenu());
final MenuItem fav = popup.getMenu().findItem(R.id.action_fav);
new Action<Boolean>() {
@NonNull
@Override
public String id() {
return "isTrackFav";
}
@Nullable
@Override
protected Boolean run() throws InterruptedException {
return pasta.isFavorite(list.get(holder.getAdapterPosition() - 1));
}
@Override
protected void done(@Nullable Boolean result) {
if (result == null) return;
if (result) {
fav.setTitle(R.string.unfav);
} else {
fav.setTitle(R.string.fav);
}
}
}.execute();
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(final MenuItem item) {
switch (item.getItemId()) {
case R.id.action_fav:
new Action<Boolean>() {
@NonNull
@Override
public String id() {
return "favTrack";
}
@Nullable
@Override
protected Boolean run() throws InterruptedException {
if (!pasta.toggleFavorite(list.get(holder.getAdapterPosition() - 1))) {
return null;
} else
return pasta.isFavorite(list.get(holder.getAdapterPosition() - 1));
}
@Override
protected void done(@Nullable Boolean result) {
if (result == null) {
pasta.onError(activity, "favorite track menu action");
return;
}
if (result) item.setTitle(R.string.unfav);
else {
item.setTitle(R.string.fav);
}
}
}.execute();
break;
case R.id.action_add:
new AddToPlaylistDialog(activity, list.get(holder.getAdapterPosition() - 1)).show();
break;
case R.id.action_album:
new Action<AlbumListData>() {
@NonNull
@Override
public String id() {
return "gotoAlbum";
}
@Nullable
@Override
protected AlbumListData run() throws InterruptedException {
return pasta.getAlbum(list.get(holder.getAdapterPosition() - 1).albumId);
}
@Override
protected void done(@Nullable AlbumListData result) {
Bundle args = new Bundle();
args.putParcelable("album", result);
Fragment f = new AlbumFragment();
f.setArguments(args);
activity.getSupportFragmentManager().beginTransaction().replace(R.id.fragment, f).addToBackStack(null).commit();
}
}.execute();
break;
case R.id.action_artist:
TrackListData track = list.get(holder.getAdapterPosition() - 1);
if (track.artists.size() > 0) {
new Action<ArtistListData>() {
@NonNull
@Override
public String id() {
return "gotoArtist";
}
@Nullable
@Override
protected ArtistListData run() throws InterruptedException {
return pasta.getArtist(list.get(holder.getAdapterPosition() - 1).artists.get(0).artistId);
}
@Override
protected void done(@Nullable ArtistListData result) {
if (result == null) {
pasta.onError(activity, "artist menu action");
return;
}
Bundle args = new Bundle();
args.putParcelable("artist", result);
Fragment f = new ArtistFragment();
f.setArguments(args);
activity.getSupportFragmentManager().beginTransaction().replace(R.id.fragment, f).addToBackStack(null).commit();
}
}.execute();
}
break;
case R.id.action_playlist_remove:
new Action<Boolean>() {
@NonNull
@Override
public String id() {
return "removeFromPlaylist";
}
@Nullable
@Override
protected Boolean run() throws InterruptedException {
//TODO: remove tracks
return false;
}
@Override
protected void done(@Nullable Boolean result) {
if (result == null || !result) {
pasta.onError(activity, "remove (from playlist) track action");
return;
}
pasta.showToast(activity.getString(R.string.playlist_removed));
removeData(list.get(holder.getAdapterPosition() - 1));
}
}.execute();
break;
}
return false;
}
});
popup.show();
}
});
TrackListData trackData = list.get(position);
((TextView) holder.v.findViewById(R.id.name)).setText(trackData.trackName);
TextView extra = (TextView) holder.v.findViewById(R.id.extra);
if (trackData.artists.size() > 0) extra.setText(trackData.artists.get(0).artistName);
holder.v.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
ArrayList<TrackListData> trackList = new ArrayList<>();
trackList.addAll(list);
StaticUtils.play(holder.getAdapterPosition() - 1, trackList, activity);
ActivityOptionsCompat options = ActivityOptionsCompat.makeCustomAnimation(activity, R.anim.slide_up, R.anim.blank);
activity.startActivity(new Intent(activity, PlayerActivity.class), options.toBundle());
}
});
View bg = holder.v.findViewById(R.id.bg);
if (bg != null) bg.setBackgroundColor(dark ? Color.DKGRAY : Color.WHITE);
Glide.with(activity).load(list.get(position).trackImage).asBitmap().placeholder(ImageUtils.getVectorDrawable(activity, R.drawable.preload)).into(new BitmapImageViewTarget((ImageView) holder.v.findViewById(R.id.image)) {
@Override
public void onResourceReady(Bitmap resource, GlideAnimation<? super Bitmap> glideAnimation) {
((CustomImageView) getView()).transition(resource);
View bg = holder.v.findViewById(R.id.bg);
if (!thumbnails || !palette || bg == null) return;
Palette.from(resource).generate(new Palette.PaletteAsyncListener() {
@Override
public void onGenerated(Palette palette) {
int defaultColor = dark ? Color.DKGRAY : Color.WHITE;
int color = palette.getLightVibrantColor(defaultColor);
if (dark) color = palette.getDarkVibrantColor(defaultColor);
ValueAnimator animator = ValueAnimator.ofObject(new ArgbEvaluator(), defaultColor, color);
animator.setDuration(250);
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int color = (int) animation.getAnimatedValue();
holder.v.findViewById(R.id.bg).setBackgroundColor(color);
View artist = holder.v.findViewById(R.id.artist);
if (artist != null)
artist.setBackgroundColor(Color.argb(255, Math.max(Color.red(color) - 10, 0), Math.max(Color.green(color) - 10, 0), Math.max(Color.blue(color) - 10, 0)));
}
});
animator.start();
}
});
}
});
}
}
@Override
public int getItemCount() {
return list == null ? 0 : list.size() + 1;
}
@Override
public int getItemViewType(int position) {
return position == 0 ? 0 : 1;
}
public static class TrackViewHolder extends ViewHolder {
public View v;
public TrackViewHolder(View v) {
super(v);
this.v = v;
}
}
public static class ArtistsViewHolder extends ViewHolder {
public View v;
public ArtistsViewHolder(View v) {
super(v);
this.v = v;
}
}
public static class ViewHolder extends RecyclerView.ViewHolder {
public View v;
public ViewHolder(View v) {
super(v);
this.v = v;
}
}
}