package com.thebluealliance.androidclient.gcm.notifications; import com.google.common.base.Predicate; import com.google.gson.JsonArray; import com.google.gson.JsonElement; import com.google.gson.JsonNull; import com.google.gson.JsonObject; import com.google.gson.JsonParseException; import com.google.gson.JsonParser; import com.google.gson.reflect.TypeToken; import com.thebluealliance.androidclient.R; import com.thebluealliance.androidclient.Utilities; import com.thebluealliance.androidclient.activities.ViewMatchActivity; import com.thebluealliance.androidclient.gcm.FollowsChecker; import com.thebluealliance.androidclient.helpers.EventHelper; import com.thebluealliance.androidclient.helpers.JSONHelper; import com.thebluealliance.androidclient.helpers.MatchHelper; import com.thebluealliance.androidclient.helpers.MyTBAHelper; import com.thebluealliance.androidclient.helpers.WebcastHelper; import com.thebluealliance.androidclient.listeners.GamedayTickerClickListener; import com.thebluealliance.androidclient.listitems.MatchListElement; import com.thebluealliance.androidclient.models.StoredNotification; import com.thebluealliance.androidclient.types.WebcastType; import com.thebluealliance.androidclient.viewmodels.UpcomingMatchNotificationViewModel; import com.thebluealliance.androidclient.views.MatchView; import android.app.Notification; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.support.annotation.Nullable; import android.support.v4.app.NotificationCompat; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; import android.widget.TextView; import java.util.ArrayList; import java.util.Arrays; import java.util.Calendar; import java.util.Date; import java.util.List; public class UpcomingMatchNotification extends BaseNotification<UpcomingMatchNotificationViewModel> { private String eventName, eventKey, matchKey; private String[] redTeams, blueTeams; private JsonElement matchTime; private JsonArray teamKeys; private JsonElement webcast; public UpcomingMatchNotification(String messageData) { super("upcoming_match", messageData); } public String getEventName() { return eventName; } public String getEventKey() { return eventKey; } public String getMatchKey() { return matchKey; } public String[] getRedTeams() { return redTeams; } public String[] getBlueTeams() { return blueTeams; } public JsonElement getMatchTime() { return matchTime; } public JsonArray getTeamKeys() { return teamKeys; } public JsonElement getWebcast() { return webcast; } @Override public void parseMessageData() throws JsonParseException { JsonObject jsonData = new JsonParser().parse(messageData).getAsJsonObject(); if (!jsonData.has("match_key")) { throw new JsonParseException("Notification data does not contain 'match_key'"); } matchKey = jsonData.get("match_key").getAsString(); if (!jsonData.has("event_name")) { throw new JsonParseException("Notification data does not contain 'event_name'"); } eventName = jsonData.get("event_name").getAsString(); if (!jsonData.has("team_keys")) { throw new JsonParseException("Notification data does not contain 'team_keys"); } eventKey = MatchHelper.getEventKeyFromMatchKey(matchKey); teamKeys = jsonData.get("team_keys").getAsJsonArray(); ArrayList<String> teamKeyList = gson.fromJson(teamKeys, new TypeToken<List<String>>(){}.getType()); int allianceSize = teamKeyList.size() / 2; redTeams = new String[allianceSize]; blueTeams = new String[allianceSize]; for (int i = 0; i < allianceSize; ++i) { redTeams[i] = teamKeyList.get(i).substring(3); blueTeams[i] = teamKeyList.get(i + allianceSize).substring(3); } if (jsonData.has("scheduled_time")) { matchTime = jsonData.get("scheduled_time"); } else { matchTime = JsonNull.INSTANCE; } if (jsonData.has("webcast")) { webcast = jsonData.get("webcast").getAsJsonObject(); } else { webcast = JsonNull.INSTANCE; } } /** * @param context a Context object for use by the notification builder * @param followsChecker for checking which teams the user follows * @return A constructed notification */ @Override public Notification buildNotification(Context context, FollowsChecker followsChecker) { String scheduledStartTimeString; if (JSONHelper.isNull(matchTime)) { scheduledStartTimeString = ""; } else { long scheduledStartTimeUNIX = matchTime.getAsLong(); // We multiply by 1000 because the Date constructor expects ms Date scheduledStartTime = new Date(scheduledStartTimeUNIX * 1000); java.text.DateFormat format = android.text.format.DateFormat.getTimeFormat(context); scheduledStartTimeString = format.format(scheduledStartTime); } // Boldify the team numbers that the user is following. Predicate<String> isFollowing = teamNumber -> followsChecker.followsTeam(context, teamNumber, matchKey, NotificationTypes.UPCOMING_MATCH); CharSequence redTeamNumbers = Utilities.boldNameList(Arrays.asList(redTeams), isFollowing); CharSequence blueTeamNumbers = Utilities.boldNameList(Arrays.asList(blueTeams), isFollowing); String matchTitle = MatchHelper.getMatchTitleFromMatchKey(context, matchKey); String matchAbbrevTitle = MatchHelper.getAbbrevMatchTitleFromMatchKey(context, matchKey); String eventShortName = EventHelper.shortName(eventName); String template = scheduledStartTimeString.isEmpty() ? context.getString(R.string.notification_upcoming_match_no_time) : context.getString(R.string.notification_upcoming_match); CharSequence contentText = TextUtils.expandTemplate(template, eventShortName, matchTitle, redTeamNumbers, blueTeamNumbers, scheduledStartTimeString); Intent instance = getIntent(context); stored = new StoredNotification(); stored.setType(getNotificationType()); String eventCode = EventHelper.getEventCode(matchKey); String notificationTitle = context.getString(R.string.notification_upcoming_match_title, eventCode, matchAbbrevTitle); stored.setTitle(notificationTitle); stored.setBody(contentText.toString()); stored.setMessageData(messageData); stored.setIntent(MyTBAHelper.serializeIntent(instance)); stored.setTime(Calendar.getInstance().getTime()); PendingIntent watchIntent = null; String watchTitle = null; if (webcast != null && webcast.isJsonObject()) { JsonObject webcastJson = webcast.getAsJsonObject(); WebcastType webcastType = WebcastHelper.getType(webcastJson.get("type").getAsString()); if (webcastType != WebcastType.NONE) { watchTitle = webcastType.render(context); Intent webcastIntent = WebcastHelper.getIntentForWebcast(context, matchKey, webcastType, webcastJson, 0); watchIntent = PendingIntent.getActivity(context, (int)System.currentTimeMillis(), webcastIntent, 0); } } NotificationCompat.Builder builder = getBaseBuilder(context, instance) .setContentTitle(notificationTitle) .setContentText(contentText); // Add Watch button if (watchIntent != null) { builder.addAction(R.drawable.ic_videocam_black_24dp, watchTitle, watchIntent); } NotificationCompat.BigTextStyle style = new NotificationCompat.BigTextStyle().bigText(contentText); builder.setStyle(style); return builder.build(); } @Override public void updateDataLocally() { /* This notification has no data that we can store locally */ } @Override public Intent getIntent(Context c) { return ViewMatchActivity.newInstance(c, matchKey); } @Override public int getNotificationId() { return (new Date().getTime() + ":" + getNotificationType() + ":" + matchKey).hashCode(); } @Override public View getView(Context c, LayoutInflater inflater, View convertView) { ViewHolder holder; if (convertView == null || !(convertView.getTag() instanceof ViewHolder)) { convertView = inflater.inflate(R.layout.list_item_notification_upcoming_match, null, false); holder = new ViewHolder(); holder.header = (TextView) convertView.findViewById(R.id.card_header); holder.title = (TextView) convertView.findViewById(R.id.title); holder.matchView = (MatchView) convertView.findViewById(R.id.match_details); holder.time = (TextView) convertView.findViewById(R.id.notification_time); holder.summaryContainer = convertView.findViewById(R.id.summary_container); convertView.setTag(holder); } else { holder = (ViewHolder) convertView.getTag(); } holder.header.setText(c.getString(R.string.gameday_ticker_event_title_format, EventHelper.shortName(eventName), EventHelper.getShortCodeForEventKey(eventKey).toUpperCase())); holder.title.setText(c.getString(R.string.notification_upcoming_match_gameday_title, MatchHelper.getMatchTitleFromMatchKey(c, matchKey))); holder.time.setText(getNotificationTimeString(c)); holder.summaryContainer.setOnClickListener(new GamedayTickerClickListener(c, this)); new MatchListElement(redTeams, blueTeams, matchKey, JSONHelper.isNull(matchTime) ? -1 : matchTime.getAsLong(), null).getView(c, inflater, holder.matchView); return convertView; } @Nullable @Override public UpcomingMatchNotificationViewModel renderToViewModel(Context context, @Nullable Void aVoid) { String header = getNotificationCardHeader(context, EventHelper.shortName(eventName), eventKey); String title = context.getString(R.string.notification_upcoming_match_gameday_title, MatchHelper.getMatchTitleFromMatchKey(context, matchKey)); long time = (JSONHelper.isNull(matchTime) ? -1 : matchTime.getAsLong()); return new UpcomingMatchNotificationViewModel(header, title, getNotificationTimeString(context), getIntent(context), matchKey, redTeams, blueTeams, time); } private static class ViewHolder { public TextView header; public TextView title; public MatchView matchView; public TextView time; private View summaryContainer; } }