// 
// Decompiled by Procyon v0.6.0
// 

package io.sentry.internal.modules;

import java.util.regex.Matcher;
import java.util.Enumeration;
import io.sentry.SentryLevel;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.HashMap;
import java.util.Map;
import io.sentry.util.ClassLoaderUtils;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
import io.sentry.ILogger;
import java.util.regex.Pattern;
import org.jetbrains.annotations.ApiStatus;

@ApiStatus.Experimental
@ApiStatus.Internal
public final class ManifestModulesLoader extends ModulesLoader
{
    private final Pattern URL_LIB_PATTERN;
    private final Pattern NAME_AND_VERSION;
    private final ClassLoader classLoader;
    
    public ManifestModulesLoader(@NotNull final ILogger logger) {
        this(ManifestModulesLoader.class.getClassLoader(), logger);
    }
    
    ManifestModulesLoader(@Nullable final ClassLoader classLoader, @NotNull final ILogger logger) {
        super(logger);
        this.URL_LIB_PATTERN = Pattern.compile(".*/(.+)!/META-INF/MANIFEST.MF");
        this.NAME_AND_VERSION = Pattern.compile("(.*?)-(\\d+\\.\\d+.*).jar");
        this.classLoader = ClassLoaderUtils.classLoaderOrDefault(classLoader);
    }
    
    @Override
    protected Map<String, String> loadModules() {
        final Map<String, String> modules = new HashMap<String, String>();
        final List<Module> detectedModules = this.detectModulesViaManifestFiles();
        for (final Module module : detectedModules) {
            modules.put(module.name, module.version);
        }
        return modules;
    }
    
    @NotNull
    private List<Module> detectModulesViaManifestFiles() {
        final List<Module> modules = new ArrayList<Module>();
        try {
            final Enumeration<URL> manifestUrls = this.classLoader.getResources("META-INF/MANIFEST.MF");
            while (manifestUrls.hasMoreElements()) {
                final URL manifestUrl = manifestUrls.nextElement();
                final String originalName = this.extractDependencyNameFromUrl(manifestUrl);
                final Module module = this.convertOriginalNameToModule(originalName);
                if (module != null) {
                    modules.add(module);
                }
            }
        }
        catch (final Throwable e) {
            this.logger.log(SentryLevel.ERROR, "Unable to detect modules via manifest files.", e);
        }
        return modules;
    }
    
    @Nullable
    private Module convertOriginalNameToModule(@Nullable final String originalName) {
        if (originalName == null) {
            return null;
        }
        final Matcher matcher = this.NAME_AND_VERSION.matcher(originalName);
        if (matcher.matches() && matcher.groupCount() == 2) {
            final String moduleName = matcher.group(1);
            final String moduleVersion = matcher.group(2);
            return new Module(moduleName, moduleVersion);
        }
        return null;
    }
    
    @Nullable
    private String extractDependencyNameFromUrl(@NotNull final URL url) {
        final String urlString = url.toString();
        final Matcher matcher = this.URL_LIB_PATTERN.matcher(urlString);
        if (matcher.matches() && matcher.groupCount() == 1) {
            return matcher.group(1);
        }
        return null;
    }
    
    private static final class Module
    {
        @NotNull
        private final String name;
        @NotNull
        private final String version;
        
        public Module(@NotNull final String name, @NotNull final String version) {
            this.name = name;
            this.version = version;
        }
    }
}
