package com.muyu.rule.common.utils;

import com.muyu.etl.domain.DataValue;
import com.muyu.rule.common.basic.BasicEngine;
import com.muyu.rule.common.domain.DataValueFie;
import com.muyu.rule.common.domain.DataValueRow;
import com.muyu.rule.common.domain.DataValueRows;
import com.muyu.rule.common.load.ExternalClassLoader;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static com.muyu.rule.common.constant.SuffixClass.Suffix_CLASS;




@Log4j2
@Component
public class LoadEngineClass {
    public static Map<String, BasicEngine<DataValueFie>> engineMap = new ConcurrentHashMap<>();
    public static Map<String, BasicEngine<DataValueRow>> engineRowMap = new ConcurrentHashMap<>();
    public static Map<String, BasicEngine<DataValueRows>> engineDataSetMap = new ConcurrentHashMap<>();
    /**
     * 服务器的存放java源代码的位置
     */
    public static final String engineWorkSourcePath = "/home/source/";


    /**
     * 引擎加载需要引入类和包文件的位置
     */
    public static final String importClassAndPackPath = "home/lib/";

    /**
     * 规则引擎的包的路径
     */
    public static final String className_prefix = "com.muyu.rule.common.engine.";

    /**
     * 服务器存放引擎的class文件的位置
     *
     * @param className 类名
     * @param versionClazz 源代码
     */

    public static final String serverClassPath = "com/muyu/rule/common/engine/";
    public void loadValueEngineClass(String className) {
        for (String s : engineMap.keySet()) {
            log.info("======"+s);
        }
        //查询类是否已加载,避免重复加载规则引擎
        if (!engineMap.containsKey(className)) {
            log.info("引擎map集合下没有该实例的规则,进行自定义类加载");
            try {
                // 假设这是你的外部类文件路径
                String externalClassFilePath =
                        importClassAndPackPath + serverClassPath + className +Suffix_CLASS;
                Path classFilePath = Paths.get(externalClassFilePath);
                String externalClassDir = externalClassFilePath.substring(0, externalClassFilePath.lastIndexOf('/'));
                URL[] urls = new URL[]{new File(externalClassDir).toURI().toURL()};

                //创建自定义类加载器
                ExternalClassLoader externalClassLoader = new ExternalClassLoader(urls);
                //加载类
                //注意类名必须是完全限定名(包括包名)
                Class<?> clazz = null;
                clazz = externalClassLoader.loadClassFromPath(classFilePath, className_prefix + className);
                //创建类的实例
                Object instance = clazz.getDeclaredConstructor().newInstance();
                //将加载出来引擎实例存入map集合中

                engineMap.put(className,(BasicEngine<DataValueFie>) instance);

            } catch (IOException | InvocationTargetException | InstantiationException | IllegalAccessException |
                     NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
        }
    }
    public void loadRowEngineClass(String className) {

        //查询类是否已加载,避免重复加载规则引擎
        if (!engineRowMap.containsKey(className)) {
            log.info("引擎map集合下没有该实例的规则,进行自定义类加载");
            try {
                // 假设这是你的外部类文件路径
                String externalClassFilePath =
                        importClassAndPackPath + serverClassPath + className + Suffix_CLASS;
                Path classFilePath = Paths.get(externalClassFilePath);
                String externalClassDir = externalClassFilePath.substring(0, externalClassFilePath.lastIndexOf('/'));
                URL[] urls = new URL[]{new File(externalClassDir).toURI().toURL()};

                //创建自定义类加载器
                ExternalClassLoader externalClassLoader = new ExternalClassLoader(urls);

                //加载类
                //注意类名必须是完全限定名(包括包名)
                Class<?> clazz = null;

                clazz = externalClassLoader.loadClassFromPath(classFilePath, className_prefix + className);
                //创建类的实例
                Object instance = clazz.getDeclaredConstructor().newInstance();
                //将加载出来引擎实例存入map集合中

                engineRowMap.put(className,(BasicEngine<DataValueRow>) instance);

            } catch (IOException | InvocationTargetException | InstantiationException | IllegalAccessException |
                     NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
        }
    }
    public void loadDataSetEngineClass(String className) {

        //查询类是否已加载,避免重复加载规则引擎
        if (!engineDataSetMap.containsKey(className)) {
            log.info("引擎map集合下没有该实例的规则,进行自定义类加载");
            try {
                // 设置外部类文件路径
                String externalClassFilePath =
                        importClassAndPackPath + serverClassPath + className + Suffix_CLASS;
                Path classFilePath = Paths.get(externalClassFilePath);
                String externalClassDir = externalClassFilePath.substring(0, externalClassFilePath.lastIndexOf('/'));
                URL[] urls = new URL[]{new File(externalClassDir).toURI().toURL()};

                //创建自定义类加载器
                ExternalClassLoader externalClassLoader = new ExternalClassLoader(urls);

                //加载类
                //注意类名必须是完全限定名(包括包名)
                Class<?> clazz = null;

                clazz = externalClassLoader.loadClassFromPath(classFilePath, className_prefix + className);
                //创建类的实例
                Object instance = clazz.getDeclaredConstructor().newInstance();
                //将加载出来引擎实例存入map集合中

                engineDataSetMap.put(className,(BasicEngine<DataValueRows>) instance);

            } catch (IOException | InvocationTargetException | InstantiationException | IllegalAccessException |
                     NoSuchMethodException e) {
                throw new RuntimeException(e);
            }
        }

    }

    public DataValue testEngine(String className, DataValueFie dataValue) {
        log.info("测试的数据[]{}:" + dataValue);
        loadValueEngineClass(className);
        BasicEngine<DataValueFie> valueBasicEngine = engineMap.get(className);

        valueBasicEngine.set(dataValue);

        valueBasicEngine.execution();
        DataValueFie value = valueBasicEngine.get();
        return value.getDataValue();
    }

    public DataValue[] testEngine(String className, DataValueRow dataValue) {
        log.info("测试的数据[]{}:" + dataValue);
        loadRowEngineClass(className);
        BasicEngine<DataValueRow> basicEngine = engineRowMap.get(className);

        basicEngine.set(dataValue);

        basicEngine.execution();
        DataValueRow dataValues = basicEngine.get();
        return dataValues.getDataValue();
    }


    public DataValue[][] testEngine(String className, DataValueRows dataValues) {
        loadDataSetEngineClass(className);
        BasicEngine<DataValueRows> basicEngine = engineDataSetMap.get(className);

        basicEngine.set(dataValues);

        basicEngine.execution();

        DataValueRows dataValues1 = basicEngine.get();

        return dataValues1.getDataValue();
    }
}

