package org.bdware.sc.boundry.utils;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.bdware.sc.compiler.PermissionStub;
import org.bdware.sc.compiler.PermissionStubGenerator;
import org.bdware.sc.engine.YJSClassLoader;
import org.bdware.sc.node.Permission;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class UtilRegistry {
    private static final Logger LOGGER = LogManager.getLogger(UtilRegistry.class);
    public static Map<String, String> stubClzNameMap = new HashMap<>();

    public static List<Class<?>> getUtilClasses() {
        List<String> allName = Permission.allName();
        List<Class<?>> ret = new ArrayList<>();
        try {
            for (String name : allName) {
                Class<?> clz;
                try {
                    clz = Class.forName(String.format("%s.%sUtil", UtilRegistry.class.getPackage().getName(), name));
                    ret.add(clz);
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            }
        } catch (Throwable e) {
            LOGGER.info("Load UtilMet Exception:" + e.getMessage());
            e.printStackTrace();
        }
        return ret;
    }

    public static void defineUtilClass(YJSClassLoader classLoader) {
        List<Class<?>> clzs = UtilRegistry.getUtilClasses();
        for (Class<?> aClass : clzs) {
            PermissionStub stub = aClass.getAnnotation(PermissionStub.class);
            if (stub == null) {
                continue;
            }
            byte[] stubClz = PermissionStubGenerator.generateStub(aClass, stub.permission().name());
            String stubClzName = aClass.getCanonicalName() + "Stub";
            stubClzNameMap.put(stub.permission().name(), stubClzName);
            classLoader.defineStubClass(stubClzName, stubClz);
        }
    }

    public static String getInitStr(String s, boolean open) {
        if (stubClzNameMap.containsKey(s)) {
            String ret =
                    String.format(
                            "%sUtil = %s.%sUtil%s;\n",
                            s, UtilRegistry.class.getPackage().getName(), s, open ? "" : "Stub");
            return ret;
        }
        return "";
    }
}
