package de.dhbwstuttgart.environment;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.nio.file.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

public class DirectoryClassLoader extends URLClassLoader implements IByteArrayClassLoader {
//    public DirectoryClassLoader(File directory, java.lang.ClassLoader parent) {
//        super(generateURLArray(dirToURL(directory)), parent);
//    }

    public DirectoryClassLoader(List<File> directory, java.lang.ClassLoader parent) {
        super(directory.stream().map(DirectoryClassLoader::dirToURL).flatMap(List::stream).collect(Collectors.toList()).toArray(new URL[0]), parent);
    }

    private static URL[] generateURLArray(URL url) {
        return new URL[]{url};
    }

    private static List<URL> dirToURL(File file) {
        //if(!url.isDirectory())throw new RuntimeException(url.toString() + " is not a directory");

        Path dir;
        if (file.isDirectory()) {
            try {
                return List.of(file.toURI().toURL()); // if file is a directory, use it as is
            } catch (MalformedURLException e) {
                e.printStackTrace();
                return List.of();
            }
        }

        dir = file.toPath().getParent(); // if file is not a directory, get its parent directory
        String pattern = file.toPath().getFileName().toString(); // use the file name as a glob pattern

        List<URL> urls = new ArrayList<>();

        try {
            urls = Files.walk(dir)
                    .filter(Files::isRegularFile) // only consider files (not directories)
                    .filter(path -> {
                        PathMatcher matcher = FileSystems.getDefault().getPathMatcher("glob:" + pattern);
                        return matcher.matches(path.getFileName()); // match the file name against the pattern
                    })
                    .map(path -> {
                        try {
                            return path.toUri().toURL();
                        } catch (MalformedURLException e) {
                            throw new RuntimeException(e);
                        }
                    }) // convert the path to a URL
                    .toList(); // print the path of each matching file
        } catch (IOException | RuntimeException e) {
            e.printStackTrace();
        }
        return urls;
    }

    @Override
    public Class<?> _defineClass(String name, byte[] code, int i, int length) throws ClassFormatError {
        return defineClass(name, code, i, length);
    }

    @Override
    public Class<?> findClass(String name) throws ClassNotFoundException {
        return super.findClass(name);
    }

    public Class<?> _findLoadedClass(String name) throws ClassNotFoundException {
        return super.findLoadedClass(name);
    }
}
