package com.eco.common.mapper.core.handler;

import cn.hutool.core.util.ObjectUtil;
import com.eco.common.mapper.core.FieldMapperInterface;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.eco.common.mapper.annotation.FieldMapper;
import org.eco.common.core.utils.StringUtils;
import org.eco.common.core.utils.reflect.ReflectUtils;

import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description: FieldMapperHandler
 * @Author: GaoKun Wang
 * @Date: 2024/7/1
 */
public class FieldMapperHandler extends JsonSerializer<Object> implements ContextualSerializer {

    /**
     * 全局实现类映射器
     */
    public static final Map<String, FieldMapperInterface<?>> FIELD_MAPPER = new ConcurrentHashMap<>();

    private FieldMapper fieldMapper;

    @Override
    public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        FieldMapperInterface<?> trans = FIELD_MAPPER.get(fieldMapper.type());
        if (ObjectUtil.isNotNull(trans)) {
            // 如果映射字段不为空 则取映射字段的值
            if (StringUtils.isNotBlank(fieldMapper.mapper())) {
                o = ReflectUtils.invokeGetter(jsonGenerator.getCurrentValue(), fieldMapper.mapper());
            }
            // 如果为 null 直接写出
            if (ObjectUtil.isNull(o)) {
                jsonGenerator.writeNull();
                return;
            }
            Object result = trans.fieldMapper(o, fieldMapper.other());
            jsonGenerator.writeObject(result);
        } else {
            jsonGenerator.writeObject(o);
        }
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider serializerProvider, BeanProperty beanProperty) throws JsonMappingException {
        FieldMapper fieldMapper = beanProperty.getAnnotation(FieldMapper.class);
        if (Objects.nonNull(fieldMapper)) {
            this.fieldMapper = fieldMapper;
            return this;
        }
        return serializerProvider.findValueSerializer(beanProperty.getType(), beanProperty);
    }
}
