/*
This file is part of Subsonic.
Subsonic is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Subsonic is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Subsonic. If not, see .
Copyright 2015 (C) Scott Jackson
*/
package github.daneren2005.dsub.util;
import android.app.Activity;
import android.content.Context;
import android.content.DialogInterface;
import android.support.v7.app.AlertDialog;
import android.util.Log;
import android.view.View;
import android.widget.RatingBar;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import github.daneren2005.dsub.R;
import github.daneren2005.dsub.domain.Artist;
import github.daneren2005.dsub.domain.MusicDirectory;
import github.daneren2005.dsub.domain.MusicDirectory.Entry;
import github.daneren2005.dsub.fragments.SubsonicFragment;
import github.daneren2005.dsub.service.DownloadFile;
import github.daneren2005.dsub.service.DownloadService;
import github.daneren2005.dsub.service.MusicService;
import github.daneren2005.dsub.service.MusicServiceFactory;
import github.daneren2005.dsub.service.OfflineException;
import github.daneren2005.dsub.service.ServerTooOldException;
import github.daneren2005.dsub.view.UpdateView;
public final class UpdateHelper {
private static final String TAG = UpdateHelper.class.getSimpleName();
public static void toggleStarred(Context context, Entry entry) {
toggleStarred(context, entry, null);
}
public static void toggleStarred(final Context context, final Entry entry, final OnStarChange onStarChange) {
toggleStarred(context, Arrays.asList(entry), onStarChange);
}
public static void toggleStarred(Context context, List entries) {
toggleStarred(context, entries, null);
}
public static void toggleStarred(final Context context, final List entries, final OnStarChange onStarChange) {
if(entries.isEmpty()) {
return;
}
final Entry firstEntry = entries.get(0);
final boolean starred = !firstEntry.isStarred();
for(Entry entry: entries) {
entry.setStarred(starred);
}
if(onStarChange != null) {
onStarChange.entries = entries;
onStarChange.starChange(starred);
}
new SilentBackgroundTask(context) {
@Override
protected Void doInBackground() throws Throwable {
MusicService musicService = MusicServiceFactory.getMusicService(context);
List songs = new ArrayList();
List artists = new ArrayList();
List albums = new ArrayList();
for(Entry entry: entries) {
if(entry.isDirectory() && Util.isTagBrowsing(context)) {
if(entry.isAlbum()) {
albums.add(entry);
} else {
artists.add(entry);
}
} else {
songs.add(entry);
}
}
musicService.setStarred(songs, artists, albums, starred, this, context);
for(Entry entry: entries) {
new UpdateHelper.EntryInstanceUpdater(entry) {
@Override
public void update(Entry found) {
found.setStarred(starred);
}
}.execute();
}
return null;
}
@Override
protected void done(Void result) {
// UpdateView
int starMsgId = starred ? R.string.starring_content_starred : R.string.starring_content_unstarred;
String starMsgBody = (entries.size() > 1) ? Integer.toString(entries.size()) : firstEntry.getTitle();
Util.toast(context, context.getResources().getString(starMsgId, starMsgBody));
if(onStarChange != null) {
onStarChange.starCommited(starred);
}
}
@Override
protected void error(Throwable error) {
Log.w(TAG, "Failed to star", error);
for(Entry entry: entries) {
entry.setStarred(!starred);
}
if(onStarChange != null) {
onStarChange.starChange(!starred);
}
String msg;
if (error instanceof OfflineException || error instanceof ServerTooOldException) {
msg = getErrorMessage(error);
} else {
String errorBody = (entries.size() > 1) ? Integer.toString(entries.size()) : firstEntry.getTitle();
msg = context.getResources().getString(R.string.starring_content_error, errorBody) + " " + getErrorMessage(error);
}
Util.toast(context, msg, false);
}
}.execute();
}
public static void toggleStarred(final Context context, final Artist entry) {
final boolean starred = !entry.isStarred();
entry.setStarred(starred);
new SilentBackgroundTask(context) {
@Override
protected Void doInBackground() throws Throwable {
MusicService musicService = MusicServiceFactory.getMusicService(context);
if(Util.isTagBrowsing(context) && !Util.isOffline(context)) {
musicService.setStarred(null, Arrays.asList(new Entry(entry)), null, starred, null, context);
} else {
musicService.setStarred(Arrays.asList(new Entry(entry)), null, null, starred, null, context);
}
return null;
}
@Override
protected void done(Void result) {
// UpdateView
Util.toast(context, context.getResources().getString(starred ? R.string.starring_content_starred : R.string.starring_content_unstarred, entry.getName()));
}
@Override
protected void error(Throwable error) {
Log.w(TAG, "Failed to star", error);
entry.setStarred(!starred);
String msg;
if (error instanceof OfflineException || error instanceof ServerTooOldException) {
msg = getErrorMessage(error);
} else {
msg = context.getResources().getString(R.string.starring_content_error, entry.getName()) + " " + getErrorMessage(error);
}
Util.toast(context, msg, false);
}
}.execute();
}
public static void setRating(Activity context, Entry entry) {
setRating(context, entry, null);
}
public static void setRating(final Activity context, final Entry entry, final OnRatingChange onRatingChange) {
View layout = context.getLayoutInflater().inflate(R.layout.rating, null);
final RatingBar ratingBar = (RatingBar) layout.findViewById(R.id.rating_bar);
ratingBar.setRating((float) entry.getRating());
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(context.getResources().getString(R.string.rating_title, entry.getTitle()))
.setView(layout)
.setPositiveButton(R.string.common_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
int rating = (int) ratingBar.getRating();
setRating(context, entry, rating, onRatingChange);
}
})
.setNegativeButton(R.string.common_cancel, null);
AlertDialog dialog = builder.create();
dialog.show();
}
public static void setRating(Context context, Entry entry, int rating) {
setRating(context, entry, rating, null);
}
public static void setRating(final Context context, final Entry entry, final int rating, final OnRatingChange onRatingChange) {
final int oldRating = entry.getRating();
entry.setRating(rating);
if(onRatingChange != null) {
onRatingChange.ratingChange(rating);
}
new SilentBackgroundTask(context) {
@Override
protected Void doInBackground() throws Throwable {
MusicService musicService = MusicServiceFactory.getMusicService(context);
musicService.setRating(entry, rating, context, null);
new EntryInstanceUpdater(entry) {
@Override
public void update(Entry found) {
found.setRating(rating);
}
}.execute();
return null;
}
@Override
protected void done(Void result) {
Util.toast(context, context.getResources().getString(rating > 0 ? R.string.rating_set_rating : R.string.rating_remove_rating, entry.getTitle()));
}
@Override
protected void error(Throwable error) {
entry.setRating(oldRating);
if(onRatingChange != null) {
onRatingChange.ratingChange(oldRating);
}
String msg;
if (error instanceof OfflineException || error instanceof ServerTooOldException) {
msg = getErrorMessage(error);
} else {
msg = context.getResources().getString(rating > 0 ? R.string.rating_set_rating_failed : R.string.rating_remove_rating_failed, entry.getTitle()) + " " + getErrorMessage(error);
}
Log.e(TAG, "Failed to setRating", error);
Util.toast(context, msg, false);
}
}.execute();
}
public static abstract class EntryInstanceUpdater {
private Entry entry;
protected int metadataUpdate = DownloadService.METADATA_UPDATED_ALL;
public EntryInstanceUpdater(Entry entry) {
this.entry = entry;
}
public EntryInstanceUpdater(Entry entry, int metadataUpdate) {
this.entry = entry;
this.metadataUpdate = metadataUpdate;
}
public abstract void update(Entry found);
public void execute() {
DownloadService downloadService = DownloadService.getInstance();
if(downloadService != null && !entry.isDirectory()) {
boolean serializeChanges = false;
List downloadFiles = downloadService.getDownloads();
DownloadFile currentPlaying = downloadService.getCurrentPlaying();
for(DownloadFile file: downloadFiles) {
Entry check = file.getSong();
if(entry.getId().equals(check.getId())) {
update(check);
serializeChanges = true;
if(currentPlaying != null && currentPlaying.getSong() != null && currentPlaying.getSong().getId().equals(entry.getId())) {
downloadService.onMetadataUpdate(metadataUpdate);
}
}
}
if(serializeChanges) {
downloadService.serializeQueue();
}
}
Entry find = UpdateView.findEntry(entry);
if(find != null) {
update(find);
}
}
}
public static abstract class OnStarChange {
protected List entries;
public abstract void starChange(boolean starred);
public abstract void starCommited(boolean starred);
}
public static abstract class OnRatingChange {
public abstract void ratingChange(int rating);
}
}