package com.axis.innovators.box.plugins;

import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassWriter;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;

public class BoxClassLoader extends URLClassLoader {
    private static final List<IClassTransformer> CLASS_TRANSFORMS = new ArrayList<>();
    private static final List<String> CLASS_BLACKLIST = new ArrayList<>();
    private static final List<String> CLASS_LOADING_LIST = new ArrayList<>();
    private static final List<Class<?>> CLASS_LOADING_LIST_OBJECT = new ArrayList<>();

    static {
        // 添加黑名单，避免加载核心类
        CLASS_BLACKLIST.add("java.");
        CLASS_BLACKLIST.add("javax.");
        CLASS_BLACKLIST.add("sun.");
    }

    public BoxClassLoader(ClassLoader parent) {
        super(new URL[]{}, parent);
    }

    public BoxClassLoader(URL[] urls, ClassLoader parent) {
        super(urls, parent);
    }

    @Override
    public void addURL(URL url) {
        super.addURL(url);
    }

    //@Override
    //protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
    //    synchronized (getClassLoadingLock(name)) {
    //        // 1. 检查类是否已加载
    //        Class<?> c = findLoadedClass(name);
    //        if (c != null) {
    //            return c;
    //        }
//
    //        // 2. 检查黑名单
    //        if (isBlacklisted(name)) {
    //            return super.loadClass(name, resolve);
    //        }
//
    //        // 3. 尝试自定义加载
    //        try {
    //            c = findClass(name);
    //        } catch (ClassNotFoundException e) {
    //            // 4. 自定义加载失败则委托给父加载器
    //            c = super.loadClass(name, resolve);
    //        }
//
    //        if (resolve) {
    //            resolveClass(c);
    //        }
    //        return c;
    //    }
    //}

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        // 检查是否在黑名单中
        if (isBlacklisted(name)) {
            throw new ClassNotFoundException("Class is blacklisted: " + name);
        }

        // 检查是否正在加载
        if (CLASS_LOADING_LIST.contains(name)) {
            throw new ClassNotFoundException("Class is already loading: " + name);
        }

        // 读取类字节码
        byte[] clazzByte;
        try {
            clazzByte = getClassBytes(name);
        } catch (IOException e) {
            throw new ClassNotFoundException("Failed to load class bytes: " + name, e);
        }

        // 应用类转换器
        for (IClassTransformer transformer : CLASS_TRANSFORMS) {
            byte[] transformed = transformer.transform(name, transformer.getClass().getName(), clazzByte);
            if (transformed != null) {
                clazzByte = transformed;
            }
        }

        // 定义类
        CLASS_LOADING_LIST.add(name);
        Class<?> clazz = defineClass(name, clazzByte, 0, clazzByte.length);
        CLASS_LOADING_LIST_OBJECT.add(clazz);
        return clazz;
    }

    private byte[] getClassBytes(String className) throws IOException, ClassNotFoundException {
        String path = className.replace('.', '/') + ".class";
        URL classUrl = getResource(path);
        if (classUrl == null) {
            throw new ClassNotFoundException("Class not found: " + className);
        }
        try (InputStream is = classUrl.openStream()) {
            return is.readAllBytes();
        }
    }

    private boolean isBlacklisted(String className) {
        return CLASS_BLACKLIST.stream().anyMatch(className::startsWith);
    }

    public static void addClassTransformer(IClassTransformer transformer) {
        CLASS_TRANSFORMS.add(transformer);
    }

    public static List<Class<?>> getClassList() {
        return CLASS_LOADING_LIST_OBJECT;
    }
}