package com.gci.boot.common.util;

import cn.hutool.json.JSONNull;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalDateTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.deser.LocalTimeDeserializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer;
import com.fasterxml.jackson.datatype.jsr310.ser.LocalTimeSerializer;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
import org.apache.poi.ss.formula.functions.T;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;

/**
 * JSON转换工具
 *
 * @author chenzw
 * @date 2021/12/9
 */
public class JsonUtil {

	/** 默认日期时间格式 */
	public static final String DEFAULT_DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";

	/** 默认日期格式 */
	public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd";

	/** 默认时间格式 */
	public static final String DEFAULT_TIME_FORMAT = "HH:mm:ss";

	public static class JsonNullSerizlizer extends JsonSerializer<JSONNull> {

		@Override
		public void serialize(JSONNull jsonNull, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
				throws IOException {
			jsonGenerator.writeNull();
		}

	}

	private static final ObjectMapper MAPPER;
	private static final ObjectMapper ALL_MAPPER;
	static {
		MAPPER = initMapper();
		ALL_MAPPER = initMapper();
		ALL_MAPPER.setSerializationInclusion(JsonInclude.Include.ALWAYS);
	}

	private static ObjectMapper initMapper(){
		ObjectMapper mapper = new ObjectMapper().setSerializationInclusion(JsonInclude.Include.NON_NULL);
		mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
		mapper.disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE);
		mapper.setDateFormat(new SimpleDateFormat(DEFAULT_DATE_TIME_FORMAT));
		mapper.enable(SerializationFeature.WRITE_SELF_REFERENCES_AS_NULL);
		mapper.disable(SerializationFeature.FAIL_ON_SELF_REFERENCES);
		JavaTimeModule javaTimeModule = new JavaTimeModule();
		javaTimeModule.addSerializer(LocalDateTime.class,
				new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
		javaTimeModule.addSerializer(LocalDate.class,
				new LocalDateSerializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
		javaTimeModule.addSerializer(LocalTime.class,
				new LocalTimeSerializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
		javaTimeModule.addDeserializer(LocalDateTime.class,
				new LocalDateTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_TIME_FORMAT)));
		javaTimeModule.addDeserializer(LocalDate.class,
				new LocalDateDeserializer(DateTimeFormatter.ofPattern(DEFAULT_DATE_FORMAT)));
		javaTimeModule.addDeserializer(LocalTime.class,
				new LocalTimeDeserializer(DateTimeFormatter.ofPattern(DEFAULT_TIME_FORMAT)));
		mapper.registerModule(javaTimeModule).registerModule(new ParameterNamesModule());

		SimpleModule simpleModule = new SimpleModule();
		simpleModule.addSerializer(JSONNull.class, new JsonNullSerizlizer());
		mapper.registerModule(simpleModule);

		mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
		return mapper;
	}
	public static byte[] object2JsonBytes(Object obj) {
		// 把对象转换成JSON
		String json = object2Json(obj);
		try {
			return json.getBytes("UTF-8");
		}
		catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return null;
	}

	// 将 POJO 转成JSON字符串，只处理非空字段
	public static String object2Json(Object obj) {
		try {
			return MAPPER.writeValueAsString(obj);
		}
		catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return null;
	}

	// 将 POJO 转成JSON字符串，处理全部字段
	public static String object2JsonAll(Object obj) {
		try {
			return ALL_MAPPER.writeValueAsString(obj);
		}
		catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return null;
	}

	// 将 POJO 转成JSON字符串，只处理非空字段，格式美化
	public static String object2JsonPretty(Object obj) {
		try {
			return MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
		}
		catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return null;
	}

	// 将 POJO 转成JSON字符串，处理全部字段，格式美化
	public static String object2JsonAllPretty(Object obj) {
		try {
			return ALL_MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
		}
		catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return null;
	}

	// 将JSON字符串转成 Map
	public static Map<String, Object> json2Map(String json) {
		try {
			return MAPPER.readValue(json, Map.class);
		}
		catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return null;
	}

	// 将POJO对象转Map
	public static Map object2Map(Object obj) {
		try {
			return MAPPER.convertValue(obj, Map.class);
		} catch (IllegalArgumentException e) {
			return null;
		}
	}

	// 将POJO对象转Map
	public static Map object2MapAll(Object obj) {
		try {
			return ALL_MAPPER.convertValue(obj, Map.class);
		} catch (IllegalArgumentException e) {
			return null;
		}
	}

	public static <T> T jsonBytes2Object(byte[] bytes, Class<T> tClass) {
		// 尽量把对象转换成JSON保存更稳妥
		try {
			String json = new String(bytes, "UTF-8");
			T t = json2Object(json, tClass);
			return t;
		}
		catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	// 将JSON字符串转成 POJO对象
	public static <T> T json2Object(String json, Class<T> tClass) {
		try {
			return MAPPER.readValue(json, tClass);
		}
		catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return null;
	}

	// 将JSON字符串转成List
	public static <T> List<T> json2List(String json, Class<T> tClass) {
		try {
			return MAPPER.readValue(json, MAPPER.getTypeFactory().constructParametricType(List.class, tClass));
		}
		catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return null;
	}

	// 将JSON字符串转成元素为Map的List
	public static List<Map> json2MapList(String json) {
		return JsonUtil.json2List(json, Map.class);
	}

	// 将JSON字符串转成 POJO对象
	public static <T> T map2Object(Map map, Class<T> tClass) {
		try {
			return MAPPER.readValue(MAPPER.writeValueAsString(map), tClass);
		}
		catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static ObjectMapper getMapper() {
		return MAPPER;
	}

}
