package cd.casic.plugin.utils;

import cd.casic.plugin.PluginCache;
import cd.casic.plugin.PluginDescriptorCache;
import cd.casic.plugin.PluginDescriptorStorage;
import cd.casic.plugin.PluginInfo;
import cn.hutool.core.util.StrUtil;
import cn.hutool.setting.dialect.Props;
import org.pf4j.PluginState;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * @Author：mianbin
 * @Package：cd.casic.plugin.utils
 * @Project：ops
 * @name：PluginsUtils
 * @Date：2024/03/18 10:19
 * @Filename：PluginsUtils
 * @description：插件工具类
 */
public class PluginsUtils {
    /**
     * param jarFile jarFile
     * @description 加载插件配置文件
     * @author dolphin
     */
    public static Props getSetting(String pluginId){
        // TODO 这个地方如果按照原来的写法，既要区分file是jar还是目录，又要区分是properties还是yaml，而且还要重复读取
        // TODO 目前暂时是弄了个PluginDescriptorCache，在两个DescriptorFinder中读取配置时就写Cache
        // TODO 上面的做法有待完善
//        Enumeration<JarEntry> entries = new JarFile(jarFile).entries();
//        while (entries.hasMoreElements()) {
//            JarEntry jarEntry = entries.nextElement();
//            String entryName = jarEntry.getName();
//            if (entryName.equals("plugin.properties")) {
//                URL url = new URL("jar:file:" + jarFile.getPath() + "!/" + entryName);
//                JarURLConnection jarConnection = (JarURLConnection) url.openConnection();
//                InputStream in = jarConnection.getInputStream();
//                String read = IoUtil.read(in, CharsetUtil.UTF_8);
//                in.close();
//                JarFile currJarFile = jarConnection.getJarFile();
//                currJarFile.close();
//                File file = new File("resources/temp");
//                File tempFile = new File(file.getAbsolutePath() + "/plugin.properties");
//                FileWriter writer = new FileWriter(tempFile);
//                writer.write(read);
//                return new Props(tempFile, CharsetUtil.CHARSET_UTF_8);
//            }else if(entryName.equals("plugin.yaml")){
//                Path path = FileUtils.getPath(Paths.get(jarFile.getPath()), "plugin.yaml");
//                FileSystemResource resource = new FileSystemResource(path);
//                PluginDescriptorStorage pluginDescriptorStorage = new PluginYamlProcessor(resource).loadYaml();
//                Props props = new Props();
//                props.put("mybatis.mapper.location", pluginDescriptorStorage.getMapperXmlDir());
//                props.put("static.locations", pluginDescriptorStorage.getStaticDir());
//                return props;
//
//            }
//        }
        PluginDescriptorStorage descriptor = PluginDescriptorCache.getPlugin(pluginId);
        if(descriptor == null){
//            throw new Exception("加载插件:读取配置文件失败");
        }else{
            Props props = new Props();
            if(!StrUtil.isEmptyIfStr(descriptor.getMapperXmlDir())){
                props.put("mybatis.mapper.location", descriptor.getMapperXmlDir());
            }
            if(!StrUtil.isEmptyIfStr(descriptor.getStaticDir())){
                props.put("static.locations", descriptor.getStaticDir());
            }

            return props;
        }
        return null;
    }

    /**
     * @description 强制删除
     * @author dolphin
     */
    public static void forceDelete(File file) {
        if (!file.exists()) {
            return;
        }
        boolean result = file.delete();
        if (result) {
            return;
        }
        int tryCount = 0;
        while (!result && tryCount++ < 5) {
            System.gc();
            try {
                Thread.sleep(150);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            result = file.delete();
        }
    }

    public static <T> List<T> getAllPluginProxyClass(Class<T> clazz) {
        List<T> result = new ArrayList<>();
        Map<String, PluginInfo> allPlugin = PluginCache.getAllPlugin();
        for (String key : allPlugin.keySet()) {
            PluginInfo pluginInfo = allPlugin.get(key);
            if (!pluginInfo.getPluginWrapper().getPluginState().equals(PluginState.STARTED)) {
                continue;
            }
            T pluginBean = pluginInfo.getPluginApplicationContext().getBean(clazz);
            if (pluginBean != null) {
                result.add(pluginBean);
            }
            Optional.of(pluginBean).ifPresent(result::add);
        }
        return result;
    }
}
