package api.common.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.TextNode;
import com.fasterxml.jackson.databind.type.TypeFactory;
import lombok.SneakyThrows;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class JsonUtil {

    private static final ObjectMapper mapper = new ObjectMapper();

    /**
     * 获取指定字段的值
     *
     * @param json     json 字符串
     * @param location 定位字符串 xx.xx.xx，数组元素用数字选择
     * @return 指定字段的值
     */
    public static String getString(String json, String location) {
        try {
            ObjectMapper objectMapper = new ObjectMapper();
            JsonNode jsonNode = objectMapper.readTree(json);
            for (String element : location.split("\\.")) {
                if (jsonNode.isArray()) {
                    jsonNode = jsonNode.path(Integer.parseInt(element));
                } else {
                    jsonNode = jsonNode.path(element);
                }
            }
            //此处需使用toString，asText只能在最后一级使用，否则值为null，同时需要注意去掉双引号
            return jsonNode.toString();
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * bean 转成 json
     *
     * @param bean bean 对象
     * @param <T>  声明为泛型方法
     * @return json 字符串
     */
    public static <T> String beanToJson(T bean) {
        try {
            return new ObjectMapper().writeValueAsString(bean);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * json 转成 bean
     *
     * @param json   json 字符串
     * @param tClass 返回值类型
     * @param <T>    声明为泛型方法
     * @return bean 对象
     */
    @SneakyThrows
    public static <T> T jsonToBean(String json, Class<T> tClass) {
        return new ObjectMapper().readValue(json, tClass);
    }

    /**
     * bean 转成 json
     *
     * @param list 列表对象
     * @param <T>  声明为泛型方法
     * @return json 字符串
     * @throws JsonProcessingException 异常
     */
    public static <T> String listToJson(T list) throws JsonProcessingException {
        return new ObjectMapper().writeValueAsString(list);
    }

    public static <T> List<T> jsonToList(String json, Class<T> tClass)  {
        try {
            JavaType javaType = TypeFactory.defaultInstance().constructParametricType(List.class, tClass);
            if (ObjectUtil.isNull(json)) {
                return new ArrayList<>();
            }
            return new ObjectMapper().readValue(json, javaType);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * bean 转成 json
     *
     * @param <T> 声明为泛型方法
     * @return json 字符串
     */
    public static <T> List<T> jsonToCommonList(String json) {
        try {
            return new ObjectMapper().readValue(json, new TypeReference<List<T>>() {
            });
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    public static Map jsonToMap(String json) {
        try {
            return new ObjectMapper().readValue(json, HashMap.class);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new HashMap();
    }

    public static JsonNode readTree(String json) {
        try {
            return mapper.readTree(json);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }
        return new TextNode("");
    }

    //泛化用的，把带下划线的json转换为驼峰jsom
    public static String stringToJson(String ss) {
        Map maps = jsonToMap(ss);
        Map map = new HashMap();
        for (Object obj : maps.keySet()) {
            String value = underlineToHump(obj.toString());
            map.put(value, maps.get(obj));
        }
        return beanToJson(map);
    }

    private static final Pattern UNDERLINE_PATTERN = Pattern.compile("_([a-z])");

    /**
     * 根据传入的带下划线的字符串转化为驼峰格式
     */

    public static String underlineToHump(String str) {
        //正则匹配下划线及后一个字符，删除下划线并将匹配的字符转成大写
        Matcher matcher = UNDERLINE_PATTERN.matcher(str);
        StringBuffer sb = new StringBuffer(str);
        if (matcher.find()) {
            sb = new StringBuffer();
            //将当前匹配的子串替换成指定字符串，并且将替换后的子串及之前到上次匹配的子串之后的字符串添加到StringBuffer对象中
            //正则之前的字符和被替换的字符
            matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
            //把之后的字符串也添加到StringBuffer对象中
            matcher.appendTail(sb);
        } else {
            //去除除字母之外的前面带的下划线
            return sb.toString().replaceAll("_", "");
        }
        return underlineToHump(sb.toString());
    }

}

