package org.gcube.application.cms.plugins;

import lombok.extern.slf4j.Slf4j;
import org.reflections.Reflections;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder;

import java.lang.reflect.Modifier;
import java.util.HashMap;
import java.util.Map;

@Slf4j
public class PluginsReflections {

    /** Loads Plugin implementation classes. It should only be accessed once by Plugin Manager
     *  Plugins shouldn't access this class unless for testing purposes.
     * @return
     */
    public static Map<String,Plugin> load(){
        Map<String,Plugin> toReturn=new HashMap<>();
        log.warn("WARNING!! LOADING PLUGIN CLASSES : THIS SHOULD HAPPEN ONLY ONCE");
        Reflections reflections = new Reflections(
                new ConfigurationBuilder()
                        .forPackage("org.gcube.application.cms")
                        .filterInputsBy(new FilterBuilder().includePackage("org.gcube.application.cms")));

        reflections.getSubTypesOf(Plugin.class).iterator().forEachRemaining(pluginClass->{
                log.trace("Evaluating class {}",pluginClass);
                if(!pluginClass.isInterface() && !Modifier.isAbstract(pluginClass.getModifiers())){
                try {
                    log.debug("Found implementation {} ",pluginClass);
                    Plugin plugin = pluginClass.newInstance();
                    log.debug("Loading {} description : {}", plugin, plugin.getDescriptor());

                    toReturn.put(plugin.getDescriptor().getId(), plugin);


                }catch (Throwable t){
                    log.warn("Unable to instantiate Plugin "+pluginClass,t);
                }
            }

        });
        return toReturn;
    }
}
