package com.thebluealliance.androidclient.renderers; import com.thebluealliance.androidclient.datafeed.APICache; import com.thebluealliance.androidclient.listitems.MatchListElement; import com.thebluealliance.androidclient.models.Match; import com.thebluealliance.androidclient.types.ModelType; import com.thebluealliance.api.model.IMatchAlliancesContainer; import com.thebluealliance.api.model.IMatchVideo; import android.content.res.Resources; import android.support.annotation.IntDef; import android.support.annotation.VisibleForTesting; import android.support.annotation.WorkerThread; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.List; import javax.annotation.Nullable; import javax.inject.Singleton; @Singleton public class MatchRenderer implements ModelRenderer<Match, Integer> { @Retention(RetentionPolicy.SOURCE) @IntDef({RENDER_DEFAULT, RENDER_MATCH_INFO, RENDER_NOTIFICATION}) public @interface RenderType{} public static final int RENDER_DEFAULT = 0; public static final int RENDER_MATCH_INFO = 1; public static final int RENDER_NOTIFICATION = 2; private final APICache mDatafeed; private final Resources mResources; public MatchRenderer(APICache datafeed, Resources resources) { mDatafeed = datafeed; mResources = resources; } @WorkerThread @Override public @Nullable MatchListElement renderFromKey(String key, ModelType type, Integer args) { Match match = mDatafeed.fetchMatch(key).toBlocking().first(); if (match == null) { return null; } return renderFromModel(match, RENDER_DEFAULT); } /** * Renders a MatchListElement for displaying this match. ASSUMES 3v3 match structure with * red/blue alliances Use different render methods for other structures */ @WorkerThread @Override public @Nullable MatchListElement renderFromModel(Match match, Integer renderMode) { RenderArgs args = argsFromMode(renderMode); @Nullable IMatchAlliancesContainer alliances = match.getAlliances(); @Nullable List<IMatchVideo> videos = match.getVideos(); String key = match.getKey(); if (key.isEmpty()) { return null; } String redScore = (alliances == null) ? "-1" : Integer.toString(alliances.getRed().getScore()); String blueScore = (alliances == null) ? "-1" : Integer.toString(alliances.getBlue().getScore()); if (Integer.parseInt(redScore) < 0) redScore = "?"; if (Integer.parseInt(blueScore) < 0) blueScore = "?"; String youTubeVideoKey = null; if (videos != null) { for (IMatchVideo video : videos) { if ("youtube".equals(video.getType())) { youTubeVideoKey = video.getKey(); break; } } } String[] redAlliance, blueAlliance; // Add teams based on alliance size (or none if there isn't for some reason) List<String> redTeams = (alliances != null) ? alliances.getRed().getTeamKeys() : null; if (redTeams != null && redTeams.size() == 3) { redAlliance = new String[]{ redTeams.get(0).substring(3), redTeams.get(1).substring(3), redTeams.get(2).substring(3)}; } else if (redTeams != null && redTeams.size() == 2) { redAlliance = new String[]{ redTeams.get(0).substring(3), redTeams.get(1).substring(3)}; } else { redAlliance = new String[]{"", "", ""}; } List<String> blueTeams = (alliances != null) ? alliances.getBlue().getTeamKeys() : null; if (blueTeams != null && blueTeams.size() == 3) { blueAlliance = new String[]{ blueTeams.get(0).substring(3), blueTeams.get(1).substring(3), blueTeams.get(2).substring(3)}; } else if (blueTeams != null && blueTeams.size() == 2) { blueAlliance = new String[]{ blueTeams.get(0).substring(3), blueTeams.get(1).substring(3)}; } else { blueAlliance = new String[]{"", "", ""}; } long matchTime = match.getTime() != null ? match.getTime() : -1; return new MatchListElement(youTubeVideoKey, match.getTitle(mResources, true), redAlliance, blueAlliance, redScore, blueScore, match.getWinningAlliance(), key, matchTime, match.getSelectedTeam(), args.showVideo, args.showHeaders, args.showMatchTitle, args.clickable); } @VisibleForTesting public static RenderArgs argsFromMode(@RenderType Integer type) { int nullSafeValue = type == null ? -1 : type; switch (nullSafeValue) { default: case RENDER_DEFAULT: /* Video icon, no header, yes title, yes clickable */ return new RenderArgs(true, false, true, true); case RENDER_MATCH_INFO: /* Only show title (used in MatchInfo activity */ return new RenderArgs(false, true, false, false); case RENDER_NOTIFICATION: /* Only be clickable - used in GameDay ticker notifications */ return new RenderArgs(false, false, false, true); } } public static class RenderArgs { public final boolean showVideo; public final boolean showHeaders; public final boolean showMatchTitle; public final boolean clickable; public RenderArgs( boolean showVideo, boolean showHeaders, boolean showMatchTitle, boolean clickable) { this.showVideo = showVideo; this.showHeaders = showHeaders; this.showMatchTitle = showMatchTitle; this.clickable = clickable; } } }