package io.metersphere.api.util;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.fasterxml.jackson.databind.jsontype.impl.StdSubtypeResolver;
import com.fasterxml.jackson.databind.type.CollectionType;
import io.metersphere.api.dto.jmeter.processors.MSJSR223Processor;
import io.metersphere.api.dto.jmeter.sampler.MSDebugSampler;

import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedList;
import java.util.List;

public class JSONUtils {
    private static final ObjectMapper objectMapper = new ObjectMapper();
    private static StdSubtypeResolver resolver = new StdSubtypeResolver();

    static {
        // 添加处理资源文件的类
        final List<NamedType> namedTypes = new LinkedList<>();
        namedTypes.add(new NamedType(MSJSR223Processor.class, MSJSR223Processor.class.getSimpleName()));
        namedTypes.add(new NamedType(MSDebugSampler.class, MSDebugSampler.class.getSimpleName()));

        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        // 自动检测所有类的全部属性
        objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
        // 如果一个对象中没有任何的属性，那么在序列化的时候就会报错
        objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
        objectMapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
        namedTypes.forEach(namedType -> resolver.registerSubtypes(namedType));
        objectMapper.setSubtypeResolver(resolver);
    }

    public static String toJSONString(Object value) {
        try {
            return objectMapper.writeValueAsString(value);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static Object parseObject(String content) {
        return parseObject(content, Object.class);
    }

    public static <T> T parseObject(String content, Class<T> valueType) {
        try {
            return objectMapper.readValue(content, valueType);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T parseObject(InputStream src, Class<T> valueType) {
        try {
            return objectMapper.readValue(src, valueType);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static <T> T parseObject(String content, TypeReference<T> valueType) {
        try {
            return objectMapper.readValue(content, valueType);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static List parseArray(String content) {
        return parseArray(content, Object.class);
    }

    public static <T> List<T> parseArray(String content, Class<T> valueType) {
        CollectionType javaType = objectMapper.getTypeFactory().constructCollectionType(List.class, valueType);
        try {
            return objectMapper.readValue(content, javaType);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 设置动态加载的jar的Resolver
     *
     * @param namedTypes
     */
    public static void setResolver(List<NamedType> namedTypes) {
        namedTypes.forEach(namedType -> resolver.registerSubtypes(namedType));
        objectMapper.setSubtypeResolver(resolver);
    }
}
