package com.changhu.support.fastjson2;

import cn.hutool.core.util.ClassUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONWriter;
import com.alibaba.fastjson2.support.config.FastJsonConfig;
import com.alibaba.fastjson2.support.spring6.http.converter.FastJsonHttpMessageConverter;
import com.changhu.common.db.BaseEnum;
import com.changhu.common.properties.Fastjson2Properties;
import com.changhu.support.fastjson2.deserialze.DbEnumDeserializer;
import com.changhu.support.fastjson2.deserialze.LatitudeDeserializer;
import com.changhu.support.fastjson2.deserialze.LongitudeDeserializer;
import com.changhu.support.fastjson2.deserialze.PointDeserializer;
import com.changhu.support.fastjson2.filter.DesensitizedFilter;
import com.changhu.support.fastjson2.serializer.DbEnumSerializer;
import com.changhu.support.fastjson2.serializer.LatitudeSerializer;
import com.changhu.support.fastjson2.serializer.LongitudeSerializer;
import com.changhu.support.fastjson2.serializer.PointSerializer;
import lombok.extern.slf4j.Slf4j;
import org.geotools.measure.Latitude;
import org.geotools.measure.Longitude;
import org.locationtech.jts.geom.Point;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.http.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.converter.StringHttpMessageConverter;

import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Set;

/**
 * author: luozhun
 * desc: FastJson2Config
 * createTime: 2023/8/26 16:08
 */
@Slf4j
@Configuration
public class FastJson2Config {

    @Autowired
    private Fastjson2Properties fastjson2Properties;

    //全局序列化默认配置
    static {
        /*
         * !!!注意 在fastjson1中 可使用 SerializeConfig ParserConfig进行序列化与反序列化的配置
         * 在fastjson2中 目前找到的方案是使用JSON.register(type,ObjectWriter)去对属性与 序列化/反序列化 进行绑定
         */
        //序列化配置
        Set<Class<?>> baseEnumClasses = ClassUtil.scanPackageBySuper("com.changhu.common.db", BaseEnum.class);
        baseEnumClasses.forEach(clazz -> {
            JSON.register(clazz, DbEnumSerializer.instance);
            JSON.register(clazz, DbEnumDeserializer.instance);
        });

        JSON.register(Latitude.class, LatitudeSerializer.instance);
        JSON.register(Longitude.class, LongitudeSerializer.instance);
        JSON.register(Point.class, PointSerializer.instance);

        //反序列化配置
        JSON.register(Latitude.class, LatitudeDeserializer.instance);
        JSON.register(Longitude.class, LongitudeDeserializer.instance);
        JSON.register(Point.class, PointDeserializer.instance);

        JSON.config(JSONWriter.Feature.WriteLongAsString);

    }

    @Bean
    public HttpMessageConverters fastJsonHttpMessageConverters() {
        //getFastJsonHttpMessageConverter 自定义的fastjson转换器
        //StringHttpMessageConverter 支持text 转string
        return new HttpMessageConverters(this.getFastJsonHttpMessageConverter(), new StringHttpMessageConverter());
    }

    public FastJsonHttpMessageConverter getFastJsonHttpMessageConverter() {
        //1.定义一个转换消息的对象
        FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
        //在转换器中添加配置信息
        fastConverter.setDefaultCharset(StandardCharsets.UTF_8);

        fastConverter.setFastJsonConfig(this.getFastJsonConfig());

        //4.解决中文乱码问题，相当于在Controller上的@RequestMapping中加了个属性produces = "application/json"
        fastConverter.setSupportedMediaTypes(List.of(
                MediaType.APPLICATION_JSON
        ));
        return fastConverter;
    }

    private FastJsonConfig getFastJsonConfig() {
        FastJsonConfig fastJsonConfig = new FastJsonConfig();

        //配置全局日期格式
        fastJsonConfig.setDateFormat(fastjson2Properties.getDateFormat());

        //配置序列化的指定行为
        fastJsonConfig.setWriterFeatures(
                //将Long序列化为String long 转 string 丢失精度问题
                JSONWriter.Feature.WriteLongAsString,
                //将List类型字段的空值序列化输出为空数组”[]”
                JSONWriter.Feature.WriteNullListAsEmpty,
                //将String类型字段的空值序列化输出为空字符串””
                JSONWriter.Feature.WriteNullStringAsEmpty,
                //在大范围超过JavaScript支持的整数，输出为字符串格式
                JSONWriter.Feature.BrowserCompatible,
                //保留map空的字段
                JSONWriter.Feature.WriteMapNullValue
        );

        //配置序列化过滤器
        fastJsonConfig.setWriterFilters(
                DesensitizedFilter.instance
        );

        return fastJsonConfig;
    }
}
