package cgeo.geocaching.downloader;

import cgeo.geocaching.R;
import cgeo.geocaching.models.Download;
import cgeo.geocaching.utils.CalendarUtils;
import cgeo.geocaching.utils.Formatter;
import cgeo.geocaching.utils.MatcherWrapper;

import android.app.Activity;
import android.net.Uri;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import java.util.List;
import java.util.regex.Pattern;

public class MapDownloaderOpenAndroMaps extends AbstractMapDownloader {
    private static final Pattern PATTERN_MAP = Pattern.compile("<a href=\"([A-Za-z0-9_-]+\\.zip)\">([A-Za-z0-9_-]+)\\.zip<\\/a>[ ]*([0-9]{2}-[A-Za-z]{3}-[0-9]{4}) [0-9]{2}:[0-9]{2}[ ]*([0-9]+)"); // 1:file name, 2:display name, 3:date DD-MMM-YYYY, 4:size (bytes)
    private static final Pattern PATTERN_DIR = Pattern.compile("<a href=\"([A-Z-a-z0-9]+\\/)\">([A-Za-z0-9]+)\\/<\\/a>");  // 1:file name, 2:display name
    private static final Pattern PATTERN_UP = Pattern.compile("<a href=\"(\\.\\.\\/)\">(\\.\\.)\\/<\\/a>"); // 1:relative dir, 2:..
    private static final String[] THEME_FILES = {"Elevate.zip"};
    private static final MapDownloaderOpenAndroMaps INSTANCE = new MapDownloaderOpenAndroMaps();

    private MapDownloaderOpenAndroMaps() {
        super (Download.DownloadType.DOWNLOADTYPE_MAP_OPENANDROMAPS, R.string.mapserver_openandromaps_downloadurl, R.string.mapserver_openandromaps_name, R.string.mapserver_openandromaps_info, R.string.mapserver_openandromaps_projecturl, R.string.mapserver_openandromaps_likeiturl);
        companionType = Download.DownloadType.DOWNLOADTYPE_THEME_OPENANDROMAPS;
    }

    @Override
    protected void analyzePage(final Uri uri, final List<Download> list, final @NonNull String page) {
        basicUpMatcher(uri, list, page, PATTERN_UP);

        final MatcherWrapper matchDir = new MatcherWrapper(PATTERN_DIR, page);
        while (matchDir.find()) {
            final Download offlineMap = new Download(matchDir.group(2), Uri.parse(uri + matchDir.group(1)), true, "", "", offlineMapType, ICONRES_FOLDER);
            list.add(offlineMap);
        }

        final MatcherWrapper matchMap = new MatcherWrapper(PATTERN_MAP, page);
        while (matchMap.find()) {
            final Download offlineMap = new Download(matchMap.group(2), Uri.parse(uri + matchMap.group(1)), false, CalendarUtils.yearMonthDay(CalendarUtils.parseDayMonthYearUS(matchMap.group(3))), Formatter.formatBytes(Long.parseLong(matchMap.group(4))), offlineMapType, iconRes);
            list.add(offlineMap);
        }
    }

    @Nullable
    @Override
    protected Download checkUpdateFor(final @NonNull String page, final String remoteUrl, final String remoteFilename) {
        final MatcherWrapper matchMap = new MatcherWrapper(PATTERN_MAP, page);
        while (matchMap.find()) {
            final String filename = matchMap.group(1);
            if (filename.equals(remoteFilename)) {
                return new Download(matchMap.group(2), Uri.parse(remoteUrl + "/" + filename), false, CalendarUtils.yearMonthDay(CalendarUtils.parseDayMonthYearUS(matchMap.group(3))), Formatter.formatBytes(Long.parseLong(matchMap.group(4))), offlineMapType, iconRes);
            }
        }
        return null;
    }

    @Override
    protected String toVisibleFilename(final String filename) {
        final int posInfix = filename.indexOf("_oam.osm.");
        return toInfixedString(posInfix == -1 ? filename : filename.substring(0, posInfix) + filename.substring(posInfix + 8), " (OAM)");
    }

    @Override
    public DownloaderUtils.DownloadDescriptor getExtrafile(final Activity activity) {
        return getExtrafile(THEME_FILES, activity.getString(R.string.mapserver_openandromaps_themes_downloadurl), Download.DownloadType.DOWNLOADTYPE_THEME_OPENANDROMAPS);
    }

    @NonNull
    public static MapDownloaderOpenAndroMaps getInstance() {
        return INSTANCE;
    }
}

@@ -2677,32 +2677,193 @@
 moteFilename) %7B%0A
+        // another change between v4 and v5 OAM: %22_%22 in filenames got replaced by %22-%22%0A        final String remoteFilenameNew = remoteFilename.replace(%22_%22, %22-%22);%0A
         final Ma
@@ -3060,16 +3060,19 @@
 Filename
+New
 )) %7B%0A   
@@ -3133,16 +3133,31 @@
 i.parse(
+getUpdatedPath(
 remoteUr
@@ -3157,16 +3157,17 @@
 emoteUrl
+)
  + %22/%22 +
@@ -3960,24 +3960,751 @@
 PS);%0A    %7D%0A%0A
+    @Override%0A    protected String getUpdatePageUrl(final String downloadPageUrl) %7B%0A        return getUpdatedPath(downloadPageUrl);%0A    %7D%0A%0A    /**%0A     * Return an updated path string, reflecting folder structure changes between%0A     * OAM v4 maps and OAM v5 maps%0A     * - last segment in path is now completely lower-case%0A     * - %22mapsV4%22 part has changed to %22mapsV5%22%0A     *%0A     * @param oldPath folder name (without trailing '/', and without filename)%0A     */%0A    private String getUpdatedPath(final String oldPath) %7B%0A        final int lastSegmentStart = oldPath.lastIndexOf('/');%0A        return oldPath.substring(0, lastSegmentStart).replace(%22mapsV4%22, %22mapsV5%22) + oldPath.substring(lastSegmentStart).toLowerCase();%0A    %7D%0A%0A
     @NonNull

enable upgrading from OAM v4 to v5 maps (fix #12344)