package io.wdd.common.config;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
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 org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;


@Component
public class OctopusObjectMapperConfig {

    private static final String STANDARD_PATTERN = "yyyy-MM-dd HH:mm:ss";

    private static final String DATE_PATTERN = "yyyy-MM-dd";

    private static final String TIME_PATTERN = "HH:mm:ss";

    public static ObjectMapper OctopusObjectMapper = null;

    public static String WriteToString(Object data) {

        try {
            return OctopusObjectMapper.writeValueAsString(data);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    public static String WriteToStringPretty(Object data) {
        try {

            return OctopusObjectMapper
                    .writerWithDefaultPrettyPrinter()
                    .writeValueAsString(data);

        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    public static byte[] WriteToBytes(Object data) {

        try {

            return OctopusObjectMapper.writeValueAsBytes(data);

        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }

    }


    @PostConstruct
    public void setOctopusObjectMapper() {
        OctopusObjectMapper = new ObjectMapper();

        /*
         * 1. java.util.Date yyyy-MM-dd HH:mm:ss
         * 2. 支持JDK8 LocalDateTime、LocalDate、 LocalTime
         * 3. Jdk8Module模块支持如Stream、Optional等类
         * 4. 序列化时包含所有字段
         * 5. 在序列化一个空对象时时不抛出异常
         * 6. 忽略反序列化时在json字符串中存在, 但在java对象中不存在的属性
         * 7. 数字序列化成字符穿且调用BigDecimal.toPlainString()方法
         */
        OctopusObjectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

        // 初始化JavaTimeModule
        JavaTimeModule javaTimeModule = new JavaTimeModule();

        //处理LocalDateTime
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter
                .ofPattern(STANDARD_PATTERN);
        javaTimeModule.addSerializer(
                LocalDateTime.class,
                new LocalDateTimeSerializer(dateTimeFormatter)
        );
        javaTimeModule.addDeserializer(
                LocalDateTime.class,
                new LocalDateTimeDeserializer(dateTimeFormatter)
        );

        //处理LocalDate
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern(DATE_PATTERN);
        javaTimeModule.addSerializer(
                LocalDate.class,
                new LocalDateSerializer(dateFormatter)
        );
        javaTimeModule.addDeserializer(
                LocalDate.class,
                new LocalDateDeserializer(dateFormatter)
        );

        //处理LocalTime
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(TIME_PATTERN);
        javaTimeModule.addSerializer(
                LocalTime.class,
                new LocalTimeSerializer(timeFormatter)
        );
        javaTimeModule.addDeserializer(
                LocalTime.class,
                new LocalTimeDeserializer(timeFormatter)
        );

        OctopusObjectMapper.registerModule(javaTimeModule);
        OctopusObjectMapper.setDateFormat(
                new SimpleDateFormat(STANDARD_PATTERN)
        );

        OctopusObjectMapper.configure(
                SerializationFeature.FAIL_ON_EMPTY_BEANS,
                false
        );
        OctopusObjectMapper.configure(
                DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES,
                false
        );

    }


}
