package net.ranides.assira.reflection.impl;

import lombok.experimental.UtilityClass;

import net.ranides.assira.reflection.*;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * This is internal factory used by IClassLoader static methods.
 *
 * It stores all named classloaders inside concurrent hash map.
 */
@UtilityClass
public class FClassLoader {

    private static final Map<String, IClassLoader> LOADERS = new ConcurrentHashMap<>();

    private static final IClassLoader SYSTEM = new AClassLoader("system");

    static {
        LOADERS.put(SYSTEM.name(), SYSTEM);
    }

    /**
     * Internal method used by IClassLoader
     *
     * @return IClassLoader
     */
    public static IClassLoader getSystem() {
        return SYSTEM;
    }

    /**
     * Internal method used by IClassLoader
     *
     * @param name name
     * @param parent parent
     * @return IClassLoader
     */
    public static IClassLoader getInstance(String name, ClassLoader parent) {
        return LOADERS.computeIfAbsent(name, k -> new AClassLoader(name, parent));
    }

    /**
     * Internal method used by IClassLoader
     *
     * @param name name
     * @return IClassLoader
     */
    public static IClassLoader getInstance(String name) {
        IClassLoader ic = LOADERS.get(name);
        if(ic == null) {
            throw new IReflectiveException("ClassLoader not found: " + name);
        }
        return ic;
    }

    /**
     * Internal method used by IClassLoader
     *
     * @param name name
     */
    public static void dispose(String name) {
        LOADERS.remove(name);
    }

}
