package com.marverenic.music.dialog; import android.app.Dialog; import android.content.res.Resources; import android.os.Bundle; import android.support.annotation.IdRes; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.design.widget.Snackbar; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentManager; import android.support.v7.app.AlertDialog; import android.view.View; import com.marverenic.music.JockeyApplication; import com.marverenic.music.R; import com.marverenic.music.data.store.PlaylistStore; import com.marverenic.music.model.Playlist; import com.marverenic.music.model.Song; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Set; import javax.inject.Inject; import timber.log.Timber; public class PlaylistCollisionDialogFragment extends DialogFragment { private static final String KEY_PLAYLIST = "PlaylistCollisionDialogFragment.Playlist"; private static final String KEY_SONG = "PlaylistCollisionDialogFragment.Song"; private static final String KEY_SONGS = "PlaylistCollisionDialogFragment.Songs"; private static final String KEY_SNACKBAR_VIEW = "PlaylistCollisionDialogFragment.Snackbar"; @Inject PlaylistStore mPlaylistStore; private Dialog mDialog; private Playlist mPlaylist; private List<Song> mPlaylistContents; private Song mSong; private List<Song> mSongs; private boolean mSingle; @IdRes private int mSnackbarView; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); JockeyApplication.getComponent(this).inject(this); mSnackbarView = getArguments().getInt(KEY_SNACKBAR_VIEW); mPlaylist = getArguments().getParcelable(KEY_PLAYLIST); if (getArguments().containsKey(KEY_SONG)) { mSong = getArguments().getParcelable(KEY_SONG); mSingle = true; } else if (getArguments().containsKey(KEY_SONGS)) { mSongs = getArguments().getParcelableArrayList(KEY_SONGS); mSingle = false; } mPlaylistStore.getSongs(mPlaylist) .take(1) .subscribe(songs -> { mPlaylistContents = songs; showDialog(); }, throwable -> { Timber.e(throwable, "Failed to get playlists"); }); } @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { if (mDialog == null) { return super.onCreateDialog(savedInstanceState); } else { return mDialog; } } private void showDialog() { if (getDialog() != null) { getDialog().hide(); } if (mSingle) { showSingleSongDialog(); } else { showMultiSongDialog(); } } private void showSingleSongDialog() { String title = getResources().getQuantityString(R.plurals.alert_confirm_duplicates, 1); String songName = mSong.getSongName(); String playlistName = mPlaylist.getPlaylistName(); String message = getString(R.string.playlist_confirm_duplicate, playlistName, songName); mDialog = new AlertDialog.Builder(getContext()) .setTitle(title) .setMessage(message) .setPositiveButton(R.string.action_add, (dialogInterface, which) -> { addAllSongs(); }) .setNegativeButton(R.string.action_cancel, null) .setOnDismissListener(dialog -> getDialog().dismiss()) .show(); } private int getDuplicateSongCount() { Set<Song> originalEntrySet = new HashSet<>(mPlaylistContents); originalEntrySet.retainAll(mSongs); return originalEntrySet.size(); } private void showMultiSongDialog() { int count = getDuplicateSongCount(); Resources res = getResources(); String title = res.getQuantityString(R.plurals.alert_confirm_duplicates, count); String addAll = res.getQuantityString(R.plurals.playlist_positive_add_duplicates, count); String addNew = getString(R.string.action_add_new); AlertDialog.Builder builder = new AlertDialog.Builder(getContext()) .setTitle(title) .setOnDismissListener(dialog -> getDialog().dismiss()); if (mSongs.size() == count) { String message = getString(R.string.playlist_confirm_all_duplicates, count); builder.setMessage(message) .setPositiveButton(addAll, (dialogInterface, which) -> { addAllSongs(); }) .setNegativeButton(R.string.action_cancel, null); } else { String message = res.getQuantityString(R.plurals.playlist_confirm_some_duplicates, count, count); builder.setMessage(message) .setPositiveButton(addAll, (dialogInterface, which) -> { addAllSongs(); }) .setNegativeButton(addNew, (dialogInterface, which) -> { addNewSongs(); }) .setNeutralButton(R.string.action_cancel, null); } mDialog = builder.show(); } private void addAllSongs() { List<Song> updatedContents = new ArrayList<>(mPlaylistContents); String message; if (mSingle) { updatedContents.add(mSong); String songName = mSong.getSongName(); String playlistName = mPlaylist.getPlaylistName(); message = getString(R.string.message_added_song, songName, playlistName); } else { updatedContents.addAll(mSongs); int count = mSongs.size(); String playlistName = mPlaylist.getPlaylistName(); message = getString(R.string.confirm_add_songs, count, playlistName); } mPlaylistStore.editPlaylist(mPlaylist, updatedContents); showSnackbar(message); } private void addNewSongs() { List<Song> updatedContents = new ArrayList<>(mPlaylistContents); int count = 0; for (Song s : mSongs) { if (!mPlaylistContents.contains(s)) { count++; updatedContents.add(s); } } mPlaylistStore.editPlaylist(mPlaylist, updatedContents); String message = getString(R.string.confirm_add_songs, count, mPlaylist.getPlaylistName()); showSnackbar(message); } private void showSnackbar(String message) { View container = getActivity().findViewById(mSnackbarView); if (container != null) { Snackbar.make(container, message, Snackbar.LENGTH_LONG) .setAction(R.string.action_undo, view -> { mPlaylistStore.editPlaylist(mPlaylist, mPlaylistContents); }) .show(); } } public static class Builder { private Bundle mArgs; private FragmentManager mFragmentManager; public Builder(FragmentManager fragmentManager) { mFragmentManager = fragmentManager; mArgs = new Bundle(); } public Builder setPlaylist(Playlist playlist) { mArgs.putParcelable(KEY_PLAYLIST, playlist); return this; } public Builder setSongs(Song song) { mArgs.putParcelable(KEY_SONG, song); mArgs.remove(KEY_SONGS); return this; } public Builder setSongs(List<Song> songs) { mArgs.putParcelableArrayList(KEY_SONGS, new ArrayList<>(songs)); mArgs.remove(KEY_SONG); return this; } public Builder showSnackbarIn(@IdRes int snackbarContainerId) { mArgs.putInt(KEY_SNACKBAR_VIEW, snackbarContainerId); return this; } public void show(String tag) { PlaylistCollisionDialogFragment dialogFragment = new PlaylistCollisionDialogFragment(); dialogFragment.setArguments(mArgs); dialogFragment.show(mFragmentManager, tag); } } }