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

package com.hypixel.hytale.server.core.plugin;

import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
import java.util.Enumeration;
import java.net.URL;
import javax.annotation.Nullable;
import javax.annotation.Nonnull;
import java.net.URLClassLoader;

public class PluginClassLoader extends URLClassLoader
{
    public static final String THIRD_PARTY_LOADER_NAME = "ThirdPartyPlugin";
    @Nonnull
    private final PluginManager pluginManager;
    private final boolean inServerClassPath;
    @Nullable
    private JavaPlugin plugin;
    
    public PluginClassLoader(@Nonnull final PluginManager pluginManager, final boolean inServerClassPath, @Nonnull final URL... urls) {
        super(inServerClassPath ? "BuiltinPlugin" : "ThirdPartyPlugin", urls, null);
        this.inServerClassPath = inServerClassPath;
        this.pluginManager = pluginManager;
    }
    
    public boolean isInServerClassPath() {
        return this.inServerClassPath;
    }
    
    void setPlugin(@Nonnull final JavaPlugin plugin) {
        this.plugin = plugin;
    }
    
    @Nonnull
    @Override
    protected Class<?> loadClass(@Nonnull final String name, final boolean resolve) throws ClassNotFoundException {
        return this.loadClass0(name, true);
    }
    
    @Nonnull
    private Class<?> loadClass0(@Nonnull final String name, final boolean useBridge) throws ClassNotFoundException {
        try {
            final Class<?> loadClass = PluginManager.class.getClassLoader().loadClass(name);
            if (loadClass != null) {
                return loadClass;
            }
        }
        catch (final ClassNotFoundException ex) {}
        try {
            final Class<?> loadClass = super.loadClass(name, false);
            if (loadClass != null) {
                return loadClass;
            }
        }
        catch (final ClassNotFoundException ex2) {}
        if (useBridge) {
            if (this.plugin != null) {
                try {
                    final Class<?> loadClass = this.pluginManager.getBridgeClassLoader().loadClass0(name, this, this.plugin.getManifest());
                    if (loadClass != null) {
                        return loadClass;
                    }
                }
                catch (final ClassNotFoundException ex3) {}
            }
            else {
                try {
                    final Class<?> loadClass = this.pluginManager.getBridgeClassLoader().loadClass0(name, this);
                    if (loadClass != null) {
                        return loadClass;
                    }
                }
                catch (final ClassNotFoundException ex4) {}
            }
        }
        throw new ClassNotFoundException(name);
    }
    
    @Nonnull
    public Class<?> loadLocalClass(@Nonnull final String name) throws ClassNotFoundException {
        synchronized (this.getClassLoadingLock(name)) {
            Class<?> loadedClass = this.findLoadedClass(name);
            if (loadedClass == null) {
                try {
                    final ClassLoader parent = this.getParent();
                    if (parent != null) {
                        loadedClass = parent.loadClass(name);
                    }
                }
                catch (final ClassNotFoundException ex) {}
                if (loadedClass == null) {
                    loadedClass = this.loadClass0(name, false);
                }
            }
            return loadedClass;
        }
    }
    
    @Nullable
    @Override
    public URL getResource(@Nonnull final String name) {
        URL resource = PluginManager.class.getClassLoader().getResource(name);
        if (resource != null) {
            return resource;
        }
        resource = super.getResource(name);
        if (resource != null) {
            return resource;
        }
        final PluginManager.PluginBridgeClassLoader bridge = this.pluginManager.getBridgeClassLoader();
        if (this.plugin != null) {
            resource = bridge.getResource0(name, this, this.plugin.getManifest());
        }
        else {
            resource = bridge.getResource0(name, this);
        }
        return resource;
    }
    
    @Nonnull
    @Override
    public Enumeration<URL> getResources(@Nonnull final String name) throws IOException {
        final ObjectArrayList<URL> results = new ObjectArrayList<URL>();
        final Enumeration<URL> serverResources = PluginManager.class.getClassLoader().getResources(name);
        while (serverResources.hasMoreElements()) {
            results.add(serverResources.nextElement());
        }
        final Enumeration<URL> pluginResources = super.getResources(name);
        while (pluginResources.hasMoreElements()) {
            results.add(pluginResources.nextElement());
        }
        final PluginManager.PluginBridgeClassLoader bridge = this.pluginManager.getBridgeClassLoader();
        Enumeration<URL> bridgeResources;
        if (this.plugin != null) {
            bridgeResources = bridge.getResources0(name, this, this.plugin.getManifest());
        }
        else {
            bridgeResources = bridge.getResources0(name, this);
        }
        while (bridgeResources.hasMoreElements()) {
            results.add(bridgeResources.nextElement());
        }
        return Collections.enumeration(results);
    }
    
    public static boolean isFromThirdPartyPlugin(@Nullable Throwable throwable) {
        while (throwable != null) {
            for (final StackTraceElement element : throwable.getStackTrace()) {
                if ("ThirdPartyPlugin".equals(element.getClassLoaderName())) {
                    return true;
                }
            }
            if (throwable.getCause() == throwable) {
                break;
            }
            throwable = throwable.getCause();
        }
        return false;
    }
    
    static {
        registerAsParallelCapable();
    }
}
