// License: WTFPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.imagery_offset_db;

import java.util.Arrays;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

import org.openstreetmap.josm.data.imagery.ImageryInfo.ImageryType;

/**
 * Generate unique imagery identifier based on its type and URL.
 *
 * @author Zverik
 * @license WTFPL
 */
public final class ImageryIdGenerator {

    private ImageryIdGenerator() {
        // Hide default constructor for utilities classes
    }

    public static String getImageryID(String url, ImageryType type) {
        if (url == null)
            return null;

        // predefined layers
        if (ImageryType.BING.equals(type) || url.contains("tiles.virtualearth.net"))
            return "bing";

        if (ImageryType.SCANEX.equals(type) && url.toLowerCase().equals("irs"))
            return "scanex_irs";

        if (ImageryType.TMS.equals(type) && url.toLowerCase().matches(".+tiles\\.mapbox\\.com/v[3-9]/openstreetmap\\.map.*"))
            return "mapbox";

        boolean isWMS = ImageryType.WMS.equals(type);

        //        System.out.println(url);

        // Remove protocol
        int i = url.indexOf("://");
        if (i > 0) {
            url = url.substring(i + 3);
        }

        // Split URL into address and query string
        i = url.indexOf('?');
        String query = "";
        if (i > 0) {
            query = url.substring(i);
            url = url.substring(0, i);
        }

        // Parse query parameters into a sorted map
        final Set<String> removeWMSParams = new TreeSet<>(Arrays.asList(new String[] {
                "srs", "width", "height", "bbox", "service", "request", "version", "format", "styles", "transparent"
        }));
        Map<String, String> qparams = new TreeMap<>();
        String[] qparamsStr = query.length() > 1 ? query.substring(1).split("&") : new String[0];
        for (String param : qparamsStr) {
            String[] kv = param.split("=");
            kv[0] = kv[0].toLowerCase();
            // WMS: if this is WMS, remove all parameters except map and layers
            if (isWMS && removeWMSParams.contains(kv[0]))
                continue;
            // TMS: skip parameters with variable values and Mapbox's access token
            if ((kv.length > 1 && kv[1].indexOf('{') >= 0 && kv[1].indexOf('}') > 0) || kv[0].equals("access_token"))
                continue;
            qparams.put(kv[0].toLowerCase(), kv.length > 1 ? kv[1] : null);
        }

        // Reconstruct query parameters
        StringBuilder sb = new StringBuilder();
        for (String qk : qparams.keySet()) {
            if (sb.length() > 0)
                sb.append('&');
            else if (query.length() > 0)
                sb.append('?');
            sb.append(qk).append('=').append(qparams.get(qk));
        }
        query = sb.toString();

        // TMS: remove /{zoom} and /{y}.png parts
        url = url.replaceAll("\\/\\{[^}]+\\}(?:\\.\\w+)?", "");
        // TMS: remove variable parts
        url = url.replaceAll("\\{[^}]+\\}", "");
        while (url.contains("..")) {
            url = url.replace("..", ".");
        }
        if (url.startsWith("."))
            url = url.substring(1);

        return url + query;
    }
}
