package com.sjyt.icom.asst.common.deserializer;

import cn.hutool.core.util.StrUtil;
import com.google.gson.*;
import com.sjyt.icom.asst.common.annotation.JsonRequired;
import com.sjyt.icom.asst.common.model.message.Message;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.lang.reflect.Type;

/**
 * 注解反序列化 用于序列化时，参数校验
 *
 * @author renyanru
 * @version V1.0.0
 * @date 2022/6/7 10:45
 */
@Slf4j
public class AnnotationDeserializer<T> implements JsonDeserializer<T> {
    private static final Gson gson;
    /**
     * 谷歌 GsonBuilder 构造器
     */
    static GsonBuilder gb = new GsonBuilder();

    static {
        gson = gb.create();
    }

    @Override
    public T deserialize(
            JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) {
        return jsonParse(jsonElement, type);
    }

    private T jsonParse(JsonElement jsonElement, Type type) {
        T pojo = gson.fromJson(jsonElement, type);
        Field[] fields = pojo.getClass().getDeclaredFields();
        for (Field f : fields) {
            if (f.getAnnotation(JsonRequired.class) != null) {
                try {
                    if (f.getType() == Message.class) {
                        JsonObject jsonObject = jsonElement.getAsJsonObject();
                        JsonElement message = jsonObject.get("message");
                        Object o = gson.fromJson(message, f.getType());
                        jsonParse(message, f.getType());
                    }
                    f.setAccessible(true);
                    if (f.get(pojo) == null) {
                        throw new JsonParseException("错误字段：" + f.getName());
                    }
                    if (StrUtil.isEmptyIfStr(f.get(pojo))) {
                        throw new JsonParseException("错误不能为空：" + f.getName());
                    }
                } catch (IllegalArgumentException | IllegalAccessException e) {
                    log.error(e.getMessage(), e);
                }
            }
        }
        return pojo;
    }
}
