package yuku.alkitab.base.util; import android.app.Activity; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.content.res.ResourcesCompat; import android.text.Html; import android.text.SpannableStringBuilder; import android.text.TextUtils; import android.text.style.ForegroundColorSpan; import android.text.style.RelativeSizeSpan; import android.view.Menu; import android.view.View; import android.widget.PopupMenu; import com.afollestad.materialdialogs.MaterialDialog; import okhttp3.Call; import okhttp3.Response; import yuku.alkitab.base.App; import yuku.alkitab.base.S; import yuku.alkitab.base.storage.SongDb; import yuku.alkitab.debug.BuildConfig; import yuku.alkitab.debug.R; import yuku.alkitab.io.OptionalGzipInputStream; import yuku.kpri.model.Song; import java.io.IOException; import java.io.InputStream; import java.io.ObjectInputStream; import java.util.List; import java.util.concurrent.atomic.AtomicBoolean; public class SongBookUtil { public static final String TAG = SongBookUtil.class.getSimpleName(); private static final int POPUP_ID_ALL = -1; private static final int POPUP_ID_MORE = -2; public interface OnSongBookSelectedListener { void onAllSelected(); void onSongBookSelected(String name); void onMoreSelected(); } public static abstract class DefaultOnSongBookSelectedListener implements OnSongBookSelectedListener { @Override public void onAllSelected() {} @Override public void onSongBookSelected(final String name) {} @Override public void onMoreSelected() {} } public interface OnDownloadSongBookListener { void onDownloadedAndInserted(SongBookInfo songBookInfo); void onFailedOrCancelled(SongBookInfo songBookInfo, Exception e); } public static class SongBookInfo { public String name; public String title; public String copyright; } public static boolean isSupportedDataFormatVersion(final int dataFormatVersion) { return dataFormatVersion == 3; } /** * For migration */ @Nullable public static SongBookInfo getSongBookInfo(@NonNull SQLiteDatabase db, @NonNull final String bookName) { final SongBookInfo info = SongDb.getSongBookInfo(db, bookName); return fallbackSongBookInfo(bookName, info); } @Nullable public static SongBookInfo getSongBookInfo(@NonNull final String bookName) { final SongBookInfo info = S.getSongDb().getSongBookInfo(bookName); return fallbackSongBookInfo(bookName, info); } @Nullable static SongBookInfo fallbackSongBookInfo(final @NonNull String bookName, final SongBookInfo info) { if (info != null) { return info; } final String title; switch (bookName) { case "BE": title = "Buku Ende"; break; case "KJ": title = "Kidung Jemaat"; break; case "KPKA": title = "Kidung Pasamuan Kristen Anyar"; break; case "KPKL": title = "Kidung Pasamuan Kristen Lawas"; break; case "KPPK": title = "Kidung Puji-Pujian Kristen"; break; case "KPRI": title = "Kidung Persekutuan Reformed Injili"; break; case "NKB": title = "Nyanyikanlah Kidung Baru"; break; case "NKI": title = "Nyanyian Kemenangan Iman"; break; case "NP": title = "Nyanyian Pujian"; break; case "NR": title = "Nafiri Rohani"; break; case "PKJ": title = "Pelengkap Kidung Jemaat"; break; case "PPK": title = "Puji-pujian Kristen"; break; default: title = null; } if (title == null) { return null; } else { final SongBookInfo fallback = new SongBookInfo(); fallback.name = bookName; fallback.title = title; fallback.copyright = null; return fallback; } } public static PopupMenu getSongBookPopupMenu(Context context, boolean withAll, boolean withMore, View anchor) { final PopupMenu res = new PopupMenu(context, anchor); final Menu menu = res.getMenu(); if (withAll) { final SpannableStringBuilder sb = new SpannableStringBuilder(context.getString(R.string.sn_bookselector_all) + '\n'); int sb_len = sb.length(); sb.append(context.getString(R.string.sn_bookselector_all_desc)); sb.setSpan(new RelativeSizeSpan(0.7f), sb_len, sb.length(), 0); sb.setSpan(new ForegroundColorSpan(0xffa0a0a0), sb_len, sb.length(), 0); menu.add(0, POPUP_ID_ALL, 0, sb); } final List<SongBookInfo> infos = S.getSongDb().listSongBookInfos(); for (int i = 0; i < infos.size(); i++) { final SongBookInfo info = infos.get(i); final SpannableStringBuilder sb = new SpannableStringBuilder(escapeSongBookName(info.name)); sb.append("\n"); int sb_len = sb.length(); if (!TextUtils.isEmpty(info.title)) { sb.append(Html.fromHtml(info.title)); } sb.setSpan(new RelativeSizeSpan(0.7f), sb_len, sb.length(), 0); sb.setSpan(new ForegroundColorSpan(0xffa0a0a0), sb_len, sb.length(), 0); menu.add(0, i + 1, 0, sb); } if (withMore) { final SpannableStringBuilder sb = new SpannableStringBuilder(context.getText(R.string.sn_bookselector_more)); sb.setSpan(new ForegroundColorSpan(ResourcesCompat.getColor(context.getResources(), R.color.escape, context.getTheme())), 0, sb.length(), 0); menu.add(0, POPUP_ID_MORE, 0, sb); } return res; } public static String getCopyright(final String bookName) { final SongBookInfo info = getSongBookInfo(bookName); if (info == null) return null; return info.copyright; } public static PopupMenu.OnMenuItemClickListener getSongBookOnMenuItemClickListener(final OnSongBookSelectedListener listener) { return item -> { final int itemId = item.getItemId(); switch (itemId) { case POPUP_ID_ALL: listener.onAllSelected(); break; case POPUP_ID_MORE: listener.onMoreSelected(); break; default: listener.onSongBookSelected(S.getSongDb().listSongBookInfos().get(itemId - 1).name); break; } return true; }; } public static class NotOkException extends IOException { public int code; public NotOkException(final int code) { this.code = code; } } public static void downloadSongBook(final Activity activity, final SongBookInfo songBookInfo, final int dataFormatVersion, final OnDownloadSongBookListener listener) { final AtomicBoolean cancelled = new AtomicBoolean(); final MaterialDialog pd = new MaterialDialog.Builder(activity) .content(R.string.sn_downloading_ellipsis) .progress(true, 0) .dismissListener(dialog -> cancelled.set(true)) .show(); Background.run(() -> { try { final Call call = App.downloadCall(BuildConfig.SERVER_HOST + "addon/songs/get_songs?name=" + songBookInfo.name + "&dataFormatVersion=" + dataFormatVersion); final Response response = call.execute(); if (response.code() != 200) { throw new NotOkException(response.code()); } final InputStream ogis = new OptionalGzipInputStream(response.body().byteStream()); final ObjectInputStream ois = new ObjectInputStream(ogis); @SuppressWarnings("unchecked") final List<Song> songs = (List<Song>) ois.readObject(); ois.close(); if (cancelled.get()) { listener.onFailedOrCancelled(songBookInfo, null); return; } // insert songs to db S.getSongDb().insertSongBookInfo(songBookInfo); S.getSongDb().storeSongs(songBookInfo.name, songs, dataFormatVersion); Foreground.run(() -> listener.onDownloadedAndInserted(songBookInfo)); } catch (IOException | ClassNotFoundException e) { Foreground.run(() -> listener.onFailedOrCancelled(songBookInfo, e)); } finally { pd.dismiss(); } }); } public static CharSequence escapeSongBookName(final String name) { if (name != null && name.startsWith("_")) { final int color = ResourcesCompat.getColor(App.context.getResources(), R.color.escape, App.context.getTheme()); final SpannableStringBuilder res = new SpannableStringBuilder(name.substring(1)); res.setSpan(new ForegroundColorSpan(color), 0, res.length(), 0); return res; } return name; } }