package cc.smtweb.system.bpm.util;

import cc.smtweb.framework.core.exception.JsonParseException;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLFactory;
import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator;
import org.apache.commons.lang3.StringUtils;
import org.yaml.snakeyaml.Yaml;
import org.yaml.snakeyaml.introspector.Property;
import org.yaml.snakeyaml.nodes.NodeTuple;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;

import java.io.*;
import java.nio.charset.StandardCharsets;

public class YamlUtil {
    private static final ObjectMapper OBJECT_MAPPER;
    private static final Representer representer;

    static {
        YAMLFactory yamlFactory = new YAMLFactory();

//    yamlFactory.enable(YAMLGenerator.Feature.CANONICAL_OUTPUT);
        yamlFactory.disable(YAMLGenerator.Feature.SPLIT_LINES);
        yamlFactory.enable(YAMLGenerator.Feature.MINIMIZE_QUOTES);

        OBJECT_MAPPER = new ObjectMapper(yamlFactory);
        OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        // 生成yaml时忽略null属性
        representer = new Representer() {
            @Override
            protected NodeTuple representJavaBeanProperty(Object javaBean, Property property, Object propertyValue, Tag customTag) {
                // if value of property is null, ignore it.
                if (propertyValue == null) {
                    return null;
                } else {
                    return super.representJavaBeanProperty(javaBean, property, propertyValue, customTag);
                }
            }
        };
    }

    private YamlUtil() {
    }

    public static <T> T readValue(String str, Class<T> clazz) {
        try {
            if (StringUtils.isBlank(str)) {
                return null;
            } else {
                return OBJECT_MAPPER.readValue(str, clazz);
            }
        } catch (Exception e) {
            throw new JsonParseException("can't convert this json to " + clazz + " type", e);
        }
    }

    public static <T> T readValue(File file, Class<T> clazz) {
        try {
            return OBJECT_MAPPER.readValue(file, clazz);
        } catch (Exception e) {
            throw new JsonParseException("can't convert this json to " + clazz + " type", e);
        }
    }

    public static <T> T readValue(InputStream is, Class<T> clazz) {
        try {
            if (is == null) {
                return null;
            } else {
                return OBJECT_MAPPER.readValue(is, clazz);
            }
        } catch (Exception e) {
            throw new JsonParseException("can't convert this yaml to " + clazz + " type", e);
        }
    }

    public static String writeValue(Object obj) {
        Yaml yaml = buildYaml();
        StringWriter sw = new StringWriter();
        yaml.dump(obj, sw);
        return sw.toString();
    }

    private static Yaml buildYaml() {
        Yaml result = new Yaml(representer);

        return result;
    }

    public static void writeValue(OutputStream outputStream, Object obj) {
        Yaml yaml = buildYaml();
        yaml.dump(obj, new OutputStreamWriter(outputStream, StandardCharsets.UTF_8));
    }

    public static void writeValue(File file, Object obj) {
        Yaml yaml = buildYaml();
        try (OutputStreamWriter out = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8)) {
            yaml.dump(obj, out);
//      OBJECT_MAPPER.writeValue(file, obj);
        } catch (IOException e) {
            throw new JsonParseException(e.getMessage(), e);
        }


//    StringWriter sw = new StringWriter();
//    System.out.println(sw.toString());
    }
}
