package com.cappielloantonio.tempo.viewmodel; import android.app.Application; import androidx.annotation.NonNull; import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; import com.cappielloantonio.tempo.interfaces.StarCallback; import com.cappielloantonio.tempo.model.Chronology; import com.cappielloantonio.tempo.model.Favorite; import com.cappielloantonio.tempo.model.HomeSector; import com.cappielloantonio.tempo.repository.AlbumRepository; import com.cappielloantonio.tempo.repository.ArtistRepository; import com.cappielloantonio.tempo.repository.ChronologyRepository; import com.cappielloantonio.tempo.repository.FavoriteRepository; import com.cappielloantonio.tempo.repository.PlaylistRepository; import com.cappielloantonio.tempo.repository.SharingRepository; import com.cappielloantonio.tempo.repository.SongRepository; import com.cappielloantonio.tempo.subsonic.models.AlbumID3; import com.cappielloantonio.tempo.subsonic.models.ArtistID3; import com.cappielloantonio.tempo.subsonic.models.Child; import com.cappielloantonio.tempo.subsonic.models.Playlist; import com.cappielloantonio.tempo.subsonic.models.Share; import com.cappielloantonio.tempo.util.Preferences; import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import java.util.ArrayList; import java.util.Calendar; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.List; import java.util.stream.Collectors; public class HomeViewModel extends AndroidViewModel { private static final String TAG = "HomeViewModel"; private final SongRepository songRepository; private final AlbumRepository albumRepository; private final ArtistRepository artistRepository; private final ChronologyRepository chronologyRepository; private final FavoriteRepository favoriteRepository; private final PlaylistRepository playlistRepository; private final SharingRepository sharingRepository; private final MutableLiveData> dicoverSongSample = new MutableLiveData<>(null); private final MutableLiveData> newReleasedAlbum = new MutableLiveData<>(null); private final MutableLiveData> starredTracksSample = new MutableLiveData<>(null); private final MutableLiveData> starredArtistsSample = new MutableLiveData<>(null); private final MutableLiveData> bestOfArtists = new MutableLiveData<>(null); private final MutableLiveData> starredTracks = new MutableLiveData<>(null); private final MutableLiveData> starredAlbums = new MutableLiveData<>(null); private final MutableLiveData> starredArtists = new MutableLiveData<>(null); private final MutableLiveData> mostPlayedAlbumSample = new MutableLiveData<>(null); private final MutableLiveData> recentlyPlayedAlbumSample = new MutableLiveData<>(null); private final MutableLiveData> years = new MutableLiveData<>(null); private final MutableLiveData> recentlyAddedAlbumSample = new MutableLiveData<>(null); private final MutableLiveData> thisGridTopSong = new MutableLiveData<>(null); private final MutableLiveData> mediaInstantMix = new MutableLiveData<>(null); private final MutableLiveData> artistInstantMix = new MutableLiveData<>(null); private final MutableLiveData> artistBestOf = new MutableLiveData<>(null); private final MutableLiveData> pinnedPlaylists = new MutableLiveData<>(null); private final MutableLiveData> shares = new MutableLiveData<>(null); private List sectors; public HomeViewModel(@NonNull Application application) { super(application); setHomeSectorList(); songRepository = new SongRepository(); albumRepository = new AlbumRepository(); artistRepository = new ArtistRepository(); chronologyRepository = new ChronologyRepository(); favoriteRepository = new FavoriteRepository(); playlistRepository = new PlaylistRepository(); sharingRepository = new SharingRepository(); setOfflineFavorite(); } public LiveData> getDiscoverSongSample(LifecycleOwner owner) { if (dicoverSongSample.getValue() == null) { songRepository.getRandomSample(10, null, null).observe(owner, dicoverSongSample::postValue); } return dicoverSongSample; } public LiveData> getRandomShuffleSample() { return songRepository.getRandomSample(100, null, null); } public LiveData> getChronologySample(LifecycleOwner owner) { Calendar cal = Calendar.getInstance(); String server = Preferences.getServerId(); int currentWeek = cal.get(Calendar.WEEK_OF_YEAR); long start = cal.getTimeInMillis(); cal.set(Calendar.WEEK_OF_YEAR, currentWeek - 1); long end = cal.getTimeInMillis(); chronologyRepository.getChronology(server, start, end).observe(owner, thisGridTopSong::postValue); return thisGridTopSong; } public LiveData> getRecentlyReleasedAlbums(LifecycleOwner owner) { if (newReleasedAlbum.getValue() == null) { int currentYear = Calendar.getInstance().get(Calendar.YEAR); albumRepository.getAlbums("byYear", 500, currentYear, currentYear).observe(owner, albums -> { if (albums != null) { albums.sort(Comparator.comparing(AlbumID3::getCreated).reversed()); newReleasedAlbum.postValue(albums.subList(0, Math.min(20, albums.size()))); } }); } return newReleasedAlbum; } public LiveData> getStarredTracksSample(LifecycleOwner owner) { if (starredTracksSample.getValue() == null) { songRepository.getStarredSongs(true, 10).observe(owner, starredTracksSample::postValue); } return starredTracksSample; } public LiveData> getStarredArtistsSample(LifecycleOwner owner) { if (starredArtistsSample.getValue() == null) { artistRepository.getStarredArtists(true, 10).observe(owner, starredArtistsSample::postValue); } return starredArtistsSample; } public LiveData> getBestOfArtists(LifecycleOwner owner) { if (bestOfArtists.getValue() == null) { artistRepository.getStarredArtists(true, 20).observe(owner, bestOfArtists::postValue); } return bestOfArtists; } public LiveData> getStarredTracks(LifecycleOwner owner) { if (starredTracks.getValue() == null) { songRepository.getStarredSongs(true, 20).observe(owner, starredTracks::postValue); } return starredTracks; } public LiveData> getStarredAlbums(LifecycleOwner owner) { if (starredAlbums.getValue() == null) { albumRepository.getStarredAlbums(true, 20).observe(owner, starredAlbums::postValue); } return starredAlbums; } public LiveData> getStarredArtists(LifecycleOwner owner) { if (starredArtists.getValue() == null) { artistRepository.getStarredArtists(true, 20).observe(owner, starredArtists::postValue); } return starredArtists; } public LiveData> getYearList(LifecycleOwner owner) { if (years.getValue() == null) { albumRepository.getDecades().observe(owner, years::postValue); } return years; } public LiveData> getMostPlayedAlbums(LifecycleOwner owner) { if (mostPlayedAlbumSample.getValue() == null) { albumRepository.getAlbums("frequent", 20, null, null).observe(owner, mostPlayedAlbumSample::postValue); } return mostPlayedAlbumSample; } public LiveData> getMostRecentlyAddedAlbums(LifecycleOwner owner) { if (recentlyAddedAlbumSample.getValue() == null) { albumRepository.getAlbums("newest", 20, null, null).observe(owner, recentlyAddedAlbumSample::postValue); } return recentlyAddedAlbumSample; } public LiveData> getRecentlyPlayedAlbumList(LifecycleOwner owner) { if (recentlyPlayedAlbumSample.getValue() == null) { albumRepository.getAlbums("recent", 20, null, null).observe(owner, recentlyPlayedAlbumSample::postValue); } return recentlyPlayedAlbumSample; } public LiveData> getMediaInstantMix(LifecycleOwner owner, Child media) { mediaInstantMix.setValue(Collections.emptyList()); songRepository.getInstantMix(media.getId(), 20).observe(owner, mediaInstantMix::postValue); return mediaInstantMix; } public LiveData> getArtistInstantMix(LifecycleOwner owner, ArtistID3 artist) { artistInstantMix.setValue(Collections.emptyList()); artistRepository.getTopSongs(artist.getName(), 10).observe(owner, artistInstantMix::postValue); return artistInstantMix; } public LiveData> getArtistBestOf(LifecycleOwner owner, ArtistID3 artist) { artistBestOf.setValue(Collections.emptyList()); artistRepository.getTopSongs(artist.getName(), 10).observe(owner, artistBestOf::postValue); return artistBestOf; } public LiveData> getPinnedPlaylists(LifecycleOwner owner) { pinnedPlaylists.setValue(Collections.emptyList()); playlistRepository.getPlaylists(false, -1).observe(owner, remotes -> { playlistRepository.getPinnedPlaylists().observe(owner, locals -> { if (remotes != null && locals != null) { List toReturn = remotes.stream() .filter(remote -> locals.stream().anyMatch(local -> local.getId().equals(remote.getId()))) .collect(Collectors.toList()); pinnedPlaylists.setValue(toReturn); } }); }); return pinnedPlaylists; } public LiveData> getShares(LifecycleOwner owner) { if (shares.getValue() == null) { sharingRepository.getShares().observe(owner, shares::postValue); } return shares; } public LiveData> getAllStarredTracks() { return songRepository.getStarredSongs(false, -1); } public void changeChronologyPeriod(LifecycleOwner owner, int period) { Calendar cal = Calendar.getInstance(); String server = Preferences.getServerId(); int currentWeek = cal.get(Calendar.WEEK_OF_YEAR); long start = 0; long end = 0; if (period == 0) { start = cal.getTimeInMillis(); cal.set(Calendar.WEEK_OF_YEAR, currentWeek - 1); end = cal.getTimeInMillis(); } else if (period == 1) { start = cal.getTimeInMillis(); cal.set(Calendar.WEEK_OF_YEAR, currentWeek - 4); end = cal.getTimeInMillis(); } else if (period == 2) { start = cal.getTimeInMillis(); cal.set(Calendar.WEEK_OF_YEAR, currentWeek - 52); end = cal.getTimeInMillis(); } chronologyRepository.getChronology(server, start, end).observe(owner, thisGridTopSong::postValue); } public void refreshDiscoverySongSample(LifecycleOwner owner) { songRepository.getRandomSample(10, null, null).observe(owner, dicoverSongSample::postValue); } public void refreshSimilarSongSample(LifecycleOwner owner) { songRepository.getStarredSongs(true, 10).observe(owner, starredTracksSample::postValue); } public void refreshRadioArtistSample(LifecycleOwner owner) { artistRepository.getStarredArtists(true, 10).observe(owner, starredArtistsSample::postValue); } public void refreshBestOfArtist(LifecycleOwner owner) { artistRepository.getStarredArtists(true, 20).observe(owner, bestOfArtists::postValue); } public void refreshStarredTracks(LifecycleOwner owner) { songRepository.getStarredSongs(true, 20).observe(owner, starredTracks::postValue); } public void refreshStarredAlbums(LifecycleOwner owner) { albumRepository.getStarredAlbums(true, 20).observe(owner, starredAlbums::postValue); } public void refreshStarredArtists(LifecycleOwner owner) { artistRepository.getStarredArtists(true, 20).observe(owner, starredArtists::postValue); } public void refreshMostPlayedAlbums(LifecycleOwner owner) { albumRepository.getAlbums("frequent", 20, null, null).observe(owner, mostPlayedAlbumSample::postValue); } public void refreshMostRecentlyAddedAlbums(LifecycleOwner owner) { albumRepository.getAlbums("newest", 20, null, null).observe(owner, recentlyAddedAlbumSample::postValue); } public void refreshRecentlyPlayedAlbumList(LifecycleOwner owner) { albumRepository.getAlbums("recent", 20, null, null).observe(owner, recentlyPlayedAlbumSample::postValue); } public void refreshShares(LifecycleOwner owner) { sharingRepository.getShares().observe(owner, this.shares::postValue); } private void setHomeSectorList() { if (Preferences.getHomeSectorList() != null && !Preferences.getHomeSectorList().equals("null")) { sectors = new Gson().fromJson( Preferences.getHomeSectorList(), new TypeToken>() { }.getType() ); } } public List getHomeSectorList() { return sectors; } public boolean checkHomeSectorVisibility(String sectorId) { return sectors != null && sectors.stream().filter(sector -> sector.getId().equals(sectorId)) .findAny() .orElse(null) == null; } public void setOfflineFavorite() { ArrayList favorites = getFavorites(); ArrayList favoritesToSave = getFavoritesToSave(favorites); ArrayList favoritesToDelete = getFavoritesToDelete(favorites, favoritesToSave); manageFavoriteToSave(favoritesToSave); manageFavoriteToDelete(favoritesToDelete); } private ArrayList getFavorites() { return new ArrayList<>(favoriteRepository.getFavorites()); } private ArrayList getFavoritesToSave(ArrayList favorites) { HashMap filteredMap = new HashMap<>(); for (Favorite favorite : favorites) { String key = favorite.toString(); if (!filteredMap.containsKey(key) || favorite.getTimestamp() > filteredMap.get(key).getTimestamp()) { filteredMap.put(key, favorite); } } return new ArrayList<>(filteredMap.values()); } private ArrayList getFavoritesToDelete(ArrayList favorites, ArrayList favoritesToSave) { ArrayList favoritesToDelete = new ArrayList<>(); for (Favorite favorite : favorites) { if (!favoritesToSave.contains(favorite)) { favoritesToDelete.add(favorite); } } return favoritesToDelete; } private void manageFavoriteToSave(ArrayList favoritesToSave) { for (Favorite favorite : favoritesToSave) { if (favorite.getToStar()) { favoriteToStar(favorite); } else { favoriteToUnstar(favorite); } } } private void manageFavoriteToDelete(ArrayList favoritesToDelete) { for (Favorite favorite : favoritesToDelete) { favoriteRepository.delete(favorite); } } private void favoriteToStar(Favorite favorite) { if (favorite.getSongId() != null) { favoriteRepository.star(favorite.getSongId(), null, null, new StarCallback() { @Override public void onSuccess() { favoriteRepository.delete(favorite); } }); } else if (favorite.getAlbumId() != null) { favoriteRepository.star(null, favorite.getAlbumId(), null, new StarCallback() { @Override public void onSuccess() { favoriteRepository.delete(favorite); } }); } else if (favorite.getArtistId() != null) { favoriteRepository.star(null, null, favorite.getArtistId(), new StarCallback() { @Override public void onSuccess() { favoriteRepository.delete(favorite); } }); } } private void favoriteToUnstar(Favorite favorite) { if (favorite.getSongId() != null) { favoriteRepository.unstar(favorite.getSongId(), null, null, new StarCallback() { @Override public void onSuccess() { favoriteRepository.delete(favorite); } }); } else if (favorite.getAlbumId() != null) { favoriteRepository.unstar(null, favorite.getAlbumId(), null, new StarCallback() { @Override public void onSuccess() { favoriteRepository.delete(favorite); } }); } else if (favorite.getArtistId() != null) { favoriteRepository.unstar(null, null, favorite.getArtistId(), new StarCallback() { @Override public void onSuccess() { favoriteRepository.delete(favorite); } }); } } }