package cgeo.geocaching.connector.gc; import android.os.Bundle; import android.support.v4.app.LoaderManager; import android.support.v4.content.Loader; import android.widget.CheckBox; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.tuple.ImmutablePair; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import java.util.Calendar; import java.util.Collections; import java.util.List; import cgeo.geocaching.R; import cgeo.geocaching.activity.ActivityMixin; import cgeo.geocaching.connector.AbstractLoggingManager; import cgeo.geocaching.connector.ImageResult; import cgeo.geocaching.connector.LogResult; import cgeo.geocaching.enumerations.Loaders; import cgeo.geocaching.enumerations.StatusCode; import cgeo.geocaching.loaders.UrlLoader; import cgeo.geocaching.log.LogCacheActivity; import cgeo.geocaching.log.LogType; import cgeo.geocaching.log.TrackableLog; import cgeo.geocaching.models.Geocache; import cgeo.geocaching.models.Image; import cgeo.geocaching.network.Parameters; import cgeo.geocaching.settings.Settings; import cgeo.geocaching.storage.DataStore; import cgeo.geocaching.utils.Log; import cgeo.geocaching.utils.TextUtils; class GCLoggingManager extends AbstractLoggingManager implements LoaderManager.LoaderCallbacks<String> { private final LogCacheActivity activity; private final Geocache cache; private String[] viewstates; @NonNull private List<TrackableLog> trackables = Collections.emptyList(); private List<LogType> possibleLogTypes; private boolean hasLoaderError = true; private int premFavcount; GCLoggingManager(final LogCacheActivity activity, final Geocache cache) { this.activity = activity; this.cache = cache; } @Nullable @Override public Loader<String> onCreateLoader(final int arg0, final Bundle arg1) { if (!Settings.hasGCCredentials()) { // allow offline logging ActivityMixin.showToast(activity, activity.getString(R.string.err_login)); return null; } activity.onLoadStarted(); return new UrlLoader(activity.getBaseContext(), "https://www.geocaching.com/seek/log.aspx", new Parameters("ID", cache.getCacheId())); } @Override public void onLoadFinished(final Loader<String> arg0, final String page) { if (page == null) { hasLoaderError = true; } else { viewstates = GCLogin.getViewstates(page); trackables = GCParser.parseTrackableLog(page); possibleLogTypes = GCParser.parseTypes(page); if (StringUtils.isBlank(cache.getGuid())) { // Acquire the cache GUID from the log page. This will not only complete the information in the database, // but also allow the user to post a rating using GCVote since it requires the GUID to do so. final String guid = TextUtils.getMatch(page, GCConstants.PATTERN_LOG_GUID, null); if (StringUtils.isNotBlank(guid)) { cache.setGuid(guid); DataStore.saveChangedCache(cache); } else { Log.w("Could not acquire GUID from log page for " + cache.getGeocode()); } } premFavcount = GCParser.getFavoritePoints(page); hasLoaderError = possibleLogTypes.isEmpty(); } activity.onLoadFinished(); } @Override public void onLoaderReset(final Loader<String> arg0) { // nothing to do } @Override public void init() { activity.getSupportLoaderManager().initLoader(Loaders.LOGGING_GEOCHACHING.getLoaderId(), null, this); } @Override @NonNull public LogResult postLog(@NonNull final LogType logType, @NonNull final Calendar date, @NonNull final String log, @Nullable final String logPassword, @NonNull final List<TrackableLog> trackableLogs) { try { final CheckBox favCheck = (CheckBox) activity.findViewById(R.id.favorite_check); final ImmutablePair<StatusCode, String> postResult = GCParser.postLog(cache.getGeocode(), cache.getCacheId(), viewstates, logType, date.get(Calendar.YEAR), date.get(Calendar.MONTH) + 1, date.get(Calendar.DATE), log, trackableLogs, favCheck.isChecked()); if (postResult.left == StatusCode.NO_ERROR) { if (logType == LogType.TEMP_DISABLE_LISTING) { cache.setDisabled(true); } else if (logType == LogType.ENABLE_LISTING) { cache.setDisabled(false); } if (favCheck.isChecked()) { cache.setFavorite(true); cache.setFavoritePoints(cache.getFavoritePoints() + 1); } } return new LogResult(postResult.left, postResult.right); } catch (final Exception e) { Log.e("GCLoggingManager.postLog", e); } return new LogResult(StatusCode.LOG_POST_ERROR, ""); } @Override @NonNull public ImageResult postLogImage(final String logId, final Image image) { if (!image.isEmpty()) { final ImmutablePair<StatusCode, String> imageResult = GCParser.uploadLogImage(logId, image); return new ImageResult(imageResult.left, imageResult.right); } return new ImageResult(StatusCode.LOGIMAGE_POST_ERROR, ""); } @Override public boolean hasLoaderError() { return hasLoaderError; } @Override @NonNull public List<TrackableLog> getTrackables() { if (hasLoaderError) { return Collections.emptyList(); } return trackables; } @Override @NonNull public List<LogType> getPossibleLogTypes() { if (hasLoaderError) { return Collections.emptyList(); } return possibleLogTypes; } @Override public int getPremFavoritePoints() { return hasLoaderError ? 0 : premFavcount; } }