package yuku.alkitab.base.util;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.os.SystemClock;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.ContextCompat;
import android.util.Log;
import gnu.trove.set.TLongSet;
import gnu.trove.set.hash.TLongHashSet;
import okhttp3.Call;
import okhttp3.FormBody;
import okhttp3.Request;
import yuku.afw.storage.Preferences;
import yuku.alkitab.base.App;
import yuku.alkitab.base.U;
import yuku.alkitab.base.ac.HelpActivity;
import yuku.alkitab.base.storage.Prefkey;
import yuku.alkitab.base.widget.Localized;
import yuku.alkitab.debug.BuildConfig;
import yuku.alkitab.debug.R;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
public abstract class Announce {
static final String TAG = Announce.class.getSimpleName();
public static final int AUTO_CHECK_INTERVAL_SECONDS = BuildConfig.DEBUG ? 60 : 86400 /* 1 days */;
public static void checkAnnouncements() {
final int lastCheck = Preferences.getInt(Prefkey.announce_last_check, 0);
if (lastCheck != 0 && (Sqlitil.nowDateTime() - lastCheck) < AUTO_CHECK_INTERVAL_SECONDS) {
Log.d(TAG, "@@checkAnnouncements exit because it was recently checked");
return;
}
Background.run(() -> {
try {
SystemClock.sleep(10000); // wait 10 seconds
checkAnnouncements_worker();
} catch (Exception e) { // handle all exceptions, because we don't want the main app to crash because of this.
Log.d(TAG, "@@checkAnnouncements", e);
}
});
}
static class Announcement {
public long id;
public String title;
public int createTime;
}
static class AnnounceCheckResult {
public boolean success;
public String message;
public Announcement[] announcements;
}
private static void checkAnnouncements_worker() throws Exception {
final List<Announcement> unreadAnnouncements = new ArrayList<>();
{
final AnnounceCheckResult result = getAnnouncements();
if (!result.success) {
Log.d(TAG, "Announce check returns success=false: " + result.message);
return;
}
if (result.announcements != null) {
final TLongSet read = getReadAnnouncementIds();
for (final Announcement announcement : result.announcements) {
if (!read.contains(announcement.id)) {
unreadAnnouncements.add(announcement);
}
}
}
}
if (unreadAnnouncements.size() == 0) {
// success, but no new announcements
} else {
// sort announcements by createTime desc
Collections.sort(unreadAnnouncements, (lhs, rhs) -> rhs.createTime - lhs.createTime);
final long[] announcementIds = new long[unreadAnnouncements.size()];
for (int i = 0; i < unreadAnnouncements.size(); i++) {
announcementIds[i] = unreadAnnouncements.get(i).id;
}
final NotificationCompat.Builder base = new NotificationCompat.Builder(App.context)
.setContentTitle(Localized.string(R.string.announce_notif_title, Localized.string(R.string.app_name)))
.setContentText(unreadAnnouncements.size() == 1 ? unreadAnnouncements.get(0).title : Localized.string(R.string.announce_notif_number_new_announcements, unreadAnnouncements.size()))
.setSmallIcon(R.drawable.ic_stat_announce)
.setColor(ContextCompat.getColor(App.context, R.color.accent))
.setContentIntent(PendingIntent.getActivity(App.context, Arrays.hashCode(announcementIds), HelpActivity.createViewAnnouncementIntent(announcementIds), PendingIntent.FLAG_UPDATE_CURRENT))
.setAutoCancel(true);
final Notification n;
if (unreadAnnouncements.size() == 1) {
final NotificationCompat.BigTextStyle builder = new NotificationCompat.BigTextStyle(base)
.setBigContentTitle(Localized.string(R.string.announce_notif_title, Localized.string(R.string.app_name)))
.bigText(unreadAnnouncements.get(0).title);
n = builder.build();
} else {
final NotificationCompat.InboxStyle builder = new NotificationCompat.InboxStyle(base)
.setBigContentTitle(Localized.string(R.string.announce_notif_title, Localized.string(R.string.app_name)))
.setSummaryText(Localized.string(R.string.announce_notif_number_new_announcements, unreadAnnouncements.size()));
for (final Announcement announcement : unreadAnnouncements) {
builder.addLine(announcement.title);
}
n = builder.build();
}
final NotificationManager nm = (NotificationManager) App.context.getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(R.id.NOTIF_announce, n);
}
Preferences.setInt(Prefkey.announce_last_check, Sqlitil.nowDateTime());
}
private static AnnounceCheckResult getAnnouncements() throws IOException {
final Call call = App.okhttp().newCall(
new Request.Builder()
.url(BuildConfig.SERVER_HOST + "announce/check")
.post(
new FormBody.Builder()
.add("installation_info", U.getInstallationInfoJson())
.build()
)
.build()
);
return App.getDefaultGson().fromJson(call.execute().body().charStream(), AnnounceCheckResult.class);
}
public static long[] getAnnouncementIds() {
try {
final AnnounceCheckResult result = getAnnouncements();
if (result.announcements == null) {
Log.e(TAG, "@@getAnnouncementIds result.announcements == null");
return null;
}
final long[] res = new long[result.announcements.length];
for (int i = 0; i < result.announcements.length; i++) {
res[i] = result.announcements[i].id;
}
return res;
} catch (IOException e) {
Log.e(TAG, "@@getAnnouncementIds", e);
return null;
}
}
public static TLongSet getReadAnnouncementIds() {
final TLongSet res = new TLongHashSet();
final String s = Preferences.getString(Prefkey.announce_read_ids);
if (s != null) {
final long[] ids = App.getDefaultGson().fromJson(s, long[].class);
for (final long id : ids) {
res.add(id);
}
}
return res;
}
public static void markAsRead(final long[] announcementIds) {
if (announcementIds == null || announcementIds.length == 0) return;
final TLongSet read = getReadAnnouncementIds();
for (final long id : announcementIds) {
read.add(id);
}
Preferences.setString(Prefkey.announce_read_ids, App.getDefaultGson().toJson(announcementIds));
}
}