package de.dhbwstuttgart.environment;

import java.net.URL;
import java.util.*;

import org.reflections.Reflections;
import org.reflections.scanners.ResourcesScanner;
import org.reflections.scanners.SubTypesScanner;
import org.reflections.util.ConfigurationBuilder;
import org.reflections.util.FilterBuilder;

import de.dhbwstuttgart.parser.scope.JavaClassName;
import org.reflections.vfs.SystemDir;

/**
 * Hilft beim Durchsuchen von Packages
 * Benutzt die Reflections-Library (https://github.com/ronmamo/reflections)
 * Hilfe dazu: http://stackoverflow.com/a/9571146
 */
public class PackageCrawler {

	final URL[] urls;
	public PackageCrawler(List<URL> urlList) {
		urls = urlList.toArray(new URL[0]);
	}
	
    public Set<Class<?>> getClassesInPackage(String packageName){
    	/*
        List<ClassLoader> classLoadersList = new LinkedList<ClassLoader>();
        classLoadersList.add(Thread.currentThread().getContextClassLoader());
        classLoadersList.add(ClasspathHelper.staticClassLoader());
        classLoadersList.add(Thread.currentThread().getContextClassLoader().getParent());
        classLoadersList.add(ClassLoader.getSystemClassLoader());
        String bootClassPath = System.getProperty("sun.boot.class.path");
        ArrayList<URL> urlList = new ArrayList<>();
        for(String path : bootClassPath.split(";")) {
        	try {
				urlList.add(new URL("file:"+path));
			} catch (MalformedURLException e) {
				new DebugException("Fehler im Classpath auf diesem System");
			}
        }
        URL[] urls = urlList.toArray(new URL[0]);
        classLoadersList.add(new URLClassLoader(urls, ClassLoader.getSystemClassLoader()));
        */
        Reflections reflections = new Reflections(new ConfigurationBuilder()
                .setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner())
                .setUrls(urls)
                .filterInputsBy(new FilterBuilder().include(FilterBuilder.prefix(packageName))));

        Set<Class<?>> classes = reflections.getSubTypesOf(Object.class);

        return classes;
    }

    public Set<Class<?>> getAllAvailableClasses(){
        Reflections reflections = new Reflections(new ConfigurationBuilder()
                .setScanners(new SubTypesScanner(false /* don't exclude Object.class */), new ResourcesScanner())
                .setUrls(urls));

        Set<Class<?>> classes = reflections.getSubTypesOf(Object.class);

        return classes;
    }

  public Map<String, Integer> getClassNames(String packageName){
      Map<String, Integer> nameList = new HashMap<>();
    Set<Class<?>> classes = getClassesInPackage(packageName);
      if(packageName.equals("java.lang") && ! classes.contains(Object.class)) {
        classes.add(Object.class);
      }
    for(Class c : classes){
      nameList.put(c.getName(), c.getTypeParameters().length);
    }
    return nameList;
  }
}
