package games.strategy.engine.framework.map.download; import java.io.File; import java.util.ArrayList; import java.util.Calendar; import java.util.Collection; import java.util.List; import java.util.Optional; import com.google.common.annotations.VisibleForTesting; import games.strategy.debug.ClientLogger; import games.strategy.engine.ClientFileSystemHelper; import games.strategy.triplea.settings.SystemPreferenceKey; import games.strategy.triplea.settings.SystemPreferences; import games.strategy.ui.SwingComponents; /** Controller for in-game map download actions. */ public class MapDownloadController { private final MapListingSource mapDownloadProperties; public MapDownloadController(final MapListingSource mapSource) { mapDownloadProperties = mapSource; } /** * Return true if all locally downloaded maps are latest versions, false if any can are out of date or their version * not recognized. */ public boolean checkDownloadedMapsAreLatest() { try { // check at most once per month final Calendar calendar = Calendar.getInstance(); final int year = calendar.get(Calendar.YEAR); final int month = calendar.get(Calendar.MONTH); // format year:month final String lastCheckTime = SystemPreferences.get(SystemPreferenceKey.TRIPLEA_LAST_CHECK_FOR_MAP_UPDATES, ""); if (lastCheckTime != null && lastCheckTime.trim().length() > 0) { final String[] yearMonth = lastCheckTime.split(":"); if (Integer.parseInt(yearMonth[0]) >= year && Integer.parseInt(yearMonth[1]) >= month) { return false; } } SystemPreferences.put(SystemPreferenceKey.TRIPLEA_LAST_CHECK_FOR_MAP_UPDATES, year + ":" + month); final List<DownloadFileDescription> downloads = new DownloadRunnable(mapDownloadProperties.getMapListDownloadSite()).getDownloads(); final Collection<String> outOfDateMaps = populateOutOfDateMapsListing(downloads); if (!outOfDateMaps.isEmpty()) { final StringBuilder text = new StringBuilder("<html>Some of the maps you have are out of date, and newer versions of those maps exist." + "<br>Would you like to update (re-download) the following maps now?:<br><ul>"); for (final String map : outOfDateMaps) { text.append("<li> ").append(map).append("</li>"); } text.append("</ul></html>"); SwingComponents.promptUser("Update Your Maps?", text.toString(), DownloadMapsWindow::showDownloadMapsWindow); return true; } } catch (final Exception e) { ClientLogger.logError("Error while checking for map updates", e); } return false; } private static Collection<String> populateOutOfDateMapsListing( final Collection<DownloadFileDescription> gamesDownloadFileDescriptions) { final Collection<String> listingToBeAddedTo = new ArrayList<>(); for (final DownloadFileDescription d : gamesDownloadFileDescriptions) { if (d != null) { final File installed = new File(ClientFileSystemHelper.getUserMapsFolder(), d.getMapName() + ".zip"); if (installed.exists()) { if (d.getVersion() != null && d.getVersion().isGreaterThan(DownloadMapsWindow.getVersion(installed), true)) { listingToBeAddedTo.add(d.getMapName()); } } } } return listingToBeAddedTo; } /** * Indicates the user should be prompted to download the tutorial map. * * @return {@code true} if the user should be prompted to download the tutorial map; otherwise {@code false}. */ public boolean shouldPromptToDownloadTutorialMap() { return shouldPromptToDownloadTutorialMap(getTutorialMapPreferences(), getUserMaps()); } @VisibleForTesting static boolean shouldPromptToDownloadTutorialMap( final TutorialMapPreferences tutorialMapPreferences, final UserMaps userMaps) { return tutorialMapPreferences.canPromptToDownload() && userMaps.isEmpty(); } @VisibleForTesting interface TutorialMapPreferences { boolean canPromptToDownload(); void preventPromptToDownload(); } private static TutorialMapPreferences getTutorialMapPreferences() { return new TutorialMapPreferences() { @Override public void preventPromptToDownload() { SystemPreferences.put(SystemPreferenceKey.TRIPLEA_PROMPT_TO_DOWNLOAD_TUTORIAL_MAP, false); } @Override public boolean canPromptToDownload() { return SystemPreferences.get(SystemPreferenceKey.TRIPLEA_PROMPT_TO_DOWNLOAD_TUTORIAL_MAP, true); } }; } @VisibleForTesting interface UserMaps { boolean isEmpty(); } private static UserMaps getUserMaps() { return new UserMaps() { @Override public boolean isEmpty() { final String[] entries = ClientFileSystemHelper.getUserMapsFolder().list(); final int entryCount = Optional.ofNullable(entries).map(it -> it.length).orElse(0); return entryCount == 0; } }; } /** * Prevents the user from being prompted to download the tutorial map. */ public void preventPromptToDownloadTutorialMap() { preventPromptToDownloadTutorialMap(getTutorialMapPreferences()); } @VisibleForTesting static void preventPromptToDownloadTutorialMap(final TutorialMapPreferences tutorialMapPreferences) { tutorialMapPreferences.preventPromptToDownload(); } }