package cd.casic.plugin;

import cd.casic.plugin.utils.YamlUtils;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.TreeTraversingParser;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLParser;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;

import java.io.InputStream;
import java.nio.file.Path;

public class PluginYamlConfigurationParser {
    private final ObjectMapper objectMapper;
    private final YAMLFactory yamlFactory;

    public PluginYamlConfigurationParser(){
        this.objectMapper = new ObjectMapper();
        this.yamlFactory = new YAMLFactory();
    }

    public Object parse(PluginInfo pluginInfo, PluginConfigWrapper pluginConfigWrapper) throws Exception {
        Class<?> configClass = pluginConfigWrapper.getConfigClass();
        if(configClass == null){
            throw new IllegalArgumentException("pluginConfigDefinition : " + pluginConfigWrapper + " " +
                    "configClass can not be null");
        }
        String yamlFileName = pluginConfigWrapper.getFileName();
        if(StrUtil.isEmpty(yamlFileName)){
            throw new IllegalArgumentException("pluginConfigDefinition : " + pluginConfigWrapper + " " +
                    "fileName can not be empty");
        }

        Path yamlPath = YamlUtils.getYamlPath(pluginInfo.getPluginWrapper().getPluginPath(), yamlFileName);
        Resource resource = new FileSystemResource(yamlPath);
        Object o = convert(resource, configClass);
        if(o == null){
            return configClass.getConstructor().newInstance();
        }
        return o;
    }


    private Object convert(Resource resource, Class<?> configClass) throws Exception {
        InputStream inputStream = null;
        YAMLParser yamlParser = null;
        TreeTraversingParser treeTraversingParser = null;
        try {
            inputStream = resource.getInputStream();
            yamlParser = yamlFactory.createParser(inputStream);
            final JsonNode node = objectMapper.readTree(yamlParser);
            if(node == null){
                return configClass.getConstructor().newInstance();
            }
            treeTraversingParser = new TreeTraversingParser(node);
            return objectMapper.readValue(treeTraversingParser, configClass);
        } finally {
            if(treeTraversingParser != null){
                treeTraversingParser.close();
            }
            if(yamlParser != null){
                yamlParser.close();
            }
            if(inputStream != null){
                inputStream.close();
            }
        }
    }
}
