package cd.casic.plugin.pf4j;

import cd.casic.plugin.PluginDescriptorCache;
import cd.casic.plugin.PluginDescriptorStorage;
import cd.casic.plugin.PluginYamlProcessor;
import cd.casic.plugin.utils.PluginDescriptorUtils;
import cd.casic.plugin.utils.YamlUtils;
import lombok.extern.slf4j.Slf4j;
import org.pf4j.PluginDescriptor;
import org.pf4j.PluginDescriptorFinder;
import org.pf4j.PluginRuntimeException;
import org.pf4j.util.FileUtils;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;

import java.nio.file.Files;
import java.nio.file.Path;

@Slf4j
public class OpsYamlPluginDescriptorFinder implements PluginDescriptorFinder {
    public static final String DEFAULT_YAML_FILE_NAME = "plugin.yaml";

    private final String yamlFileName;

    public OpsYamlPluginDescriptorFinder() {
        this(DEFAULT_YAML_FILE_NAME);
    }

    public OpsYamlPluginDescriptorFinder(String yamlFileName) {
        this.yamlFileName = yamlFileName;
    }

    @Override
    public boolean isApplicable(Path pluginPath) {
        return Files.exists(pluginPath)
                && (Files.isDirectory(pluginPath)
                || FileUtils.isJarFile(pluginPath));
    }

    @Override
    public PluginDescriptor find(Path pluginPath) {
        Path yamlPath = null;
        try {
            yamlPath = YamlUtils.getYamlPath(pluginPath, yamlFileName);
            if (yamlPath == null) {
                throw new PluginRuntimeException("Cannot find the plugin manifest path");
            }
            log.debug("Lookup plugin descriptor in '{}'", yamlPath);
            if (Files.notExists(yamlPath)) {
                throw new PluginRuntimeException("Cannot find '{}' path", yamlPath);
            }

            Resource yamlResource = new FileSystemResource(yamlPath);
            PluginYamlProcessor pluginYamlProcessor = new PluginYamlProcessor(yamlResource);
            PluginDescriptorStorage pluginDescriptor = pluginYamlProcessor.loadYaml();
            PluginDescriptorCache.put(pluginDescriptor.getPluginId(), pluginDescriptor);
            OpsPluginDescriptor defaultPluginDescriptor = PluginDescriptorUtils.storageToDescriptor(pluginDescriptor);
            pluginDescriptor.getDependencies().forEach(defaultPluginDescriptor::addDependency);
            return defaultPluginDescriptor;
        } finally {
            FileUtils.closePath(yamlPath);
        }
    }
}
