package com.ag.secp.platform.microkernel;

import cn.hutool.core.convert.Convert;
import com.ag.log.RequestLog;
import com.ag.psamathe.api.Module;
import com.ag.psamathe.api.ModuleConfig;
import com.ag.psamathe.api.ModuleLoader;
import com.ag.psamathe.api.ModuleManager;
import com.ag.psamathe.api.impl.SpringModule;
import com.ag.util.ResourceUtil;
import com.ag.util.StrUtil;
import com.wb.common.Base;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;
import org.springframework.util.ReflectionUtils;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;

@Component
public class ModuleManageProcess {

    @Autowired
    private ModuleLoader moduleLoader;
    @Autowired
    private ModuleManager moduleManager;

    /**
     * 部署模式
     * @param
     */
    @RequestLog
    public Object deployModule(JSONObject jsonObject, HttpServletResponse response, HttpServletRequest request, String beanName, String methodName) throws Exception {
        Module module = moduleManager.find(ResourceUtil.getString("system", "userName"));
        ApplicationContext context = ((SpringModule) module).getApplicationContext();
        //doAction执行了Action接口的execute方法
        return runBeanMethod(jsonObject, response, request, context, beanName, methodName);
    }

    /**
     * 读取jar包的开发者模式
     *
     * @param
     */
    private long lastModifid = 0;
    @RequestLog
    public synchronized Object developerForJar(JSONObject jsonObject, HttpServletResponse response, HttpServletRequest request, String beanName, String methodName) throws Exception {
        long on = System.currentTimeMillis();
        ModuleConfig config = buildModuleConfig();
        Module module;
        try {
            if (Long.parseLong(config.getVersion()) > lastModifid)//add by liaw 2021-3-4 重新打包修改时间变化后再加载
            {

                lastModifid = Long.parseLong(config.getVersion());
                module = moduleLoader.load(config);
                Module removed = moduleManager.register(module);//add by liaw 2021-3-4 记录加载的模块
                if (removed != null){
                    removed.destroy();
                }

                System.out.println("module load times::" + ((System.currentTimeMillis() - on)));

            } else {
                module = moduleManager.find(config.getName());//已经加载过，直接使用上次加载的模块
                System.out.println("module find times::" + ((System.currentTimeMillis() - on)));
            }
        }catch (Exception ex){
            ex.printStackTrace();
            throw new RuntimeException("jar包读取失败，请检查jar包路径!");
        }
        ApplicationContext context = ((SpringModule) module).getApplicationContext();
        //doAction执行了Action接口的execute方法
        return runBeanMethod(jsonObject, response, request, context, beanName, methodName);
    }

    private Object runBeanMethod(JSONObject jsonObject, HttpServletResponse response, HttpServletRequest request, ApplicationContext context, String beanName, String methodName){
        Object result;
        Method method;
        try {
            String springName = StrUtil.firstToLower(beanName);
            if (context.containsBean(springName)) {
                result = context.getBean(springName);
            } else {
                result = context.getBean(StrUtil.firstToUpper(beanName));
            }
        } catch (Exception ex) {
            throw new RuntimeException("beanName不正确, 请检查![" + beanName + "]");
        }
        try {
            method = result.getClass().getMethod(methodName, JSONObject.class, HttpServletResponse.class, HttpServletRequest.class);
        }catch (Exception ex){
            throw new RuntimeException("方法名不正确, 请检查![" + methodName + "]");
        }
        return ReflectionUtils.invokeMethod(method, result, jsonObject, response, request);
    }

    public ModuleConfig buildModuleConfig() {

        List<URL> urls = new ArrayList<>();
        List<String> scanPackages = new ArrayList<>();
        ModuleConfig moduleConfig = new ModuleConfig();
        long lastModify = 0;
        try {
            ResourceBundle resource = ResourceUtil.getResourceBundle("system");
            String[] arrs = resource.getString("dynamicJarPath").split(",");
            for (String arr : arrs) {
                if (com.ag.util.StrUtil.isEmpty(arr)) {
                    continue;
                }
                String path = arr;
                File file = new File(arr);
                if (!file.isAbsolute()) {
                    file = new File(Base.path, arr);
                    path = file.getCanonicalPath();
                }
                if (file.lastModified() > lastModify) {//判断修改时间，大于上次修改时间，则记录新的修改时间
                    lastModify = file.lastModified();
                }
                urls.add(new URL("file:" + path));
            }
            String[] scans = resource.getString("scanPackages").split(",");
            for (String arr : scans) {
                if (com.ag.util.StrUtil.isEmpty(arr)) {
                    continue;
                }
                scanPackages.add(arr);
            }
            moduleConfig.setName("demo");
            moduleConfig.setVersion(Convert.toStr(lastModify));//将修改时间做为版本号记录，供管理开发模式热加载使用
        } catch (Exception e) {
            e.printStackTrace();
        }
        moduleConfig.setModuleUrl(urls);
        moduleConfig.setOverridePackages(scanPackages);

        return moduleConfig;
    }


}
