package com.njzscloud.common.core.fastjson.serializer;


import com.alibaba.fastjson2.JSONReader;
import com.alibaba.fastjson2.reader.ObjectReader;
import com.alibaba.fastjson2.util.TypeUtils;
import com.njzscloud.common.core.ex.Exceptions;
import com.njzscloud.common.core.ienum.Dict;
import com.njzscloud.common.core.ienum.DictInt;
import com.njzscloud.common.core.ienum.DictStr;
import com.njzscloud.common.core.ienum.IEnum;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Type;
import java.util.Map;

/**
 * Dict 枚举的 Fastjson 反序列化器<br/>
 * 使用方式（二选一即可）: <br/>
 * 1、在字段上使用 JSONField 进行指定<br/>
 * 如，@JSONField(deserializeUsing = DictObjectSerializer.class)<br/>
 * 2、在枚举类上使用 JSONType 进行指定（在接口上指定无效）<br/>
 * 如，@JSONType(writeEnumAsJavaBean = true, deserializer = DictObjectSerializer.class)<br/><br/>
 * JSON 格式见对应的序列化器 {@link DictObjectSerializer}
 *
 * @see Dict
 * @see DictInt
 * @see DictStr
 * @see DictObjectSerializer
 */
@Slf4j
public class DictObjectDeserializer implements ObjectReader<Dict> {

    private static final ClassLoader CLASSLOADER = DictObjectDeserializer.class.getClassLoader();

    @Override
    public Dict readObject(JSONReader jsonReader, Type fieldType, Object fieldName, long features) {
        try {
            if (jsonReader.isObject()) {
                Map<String, Object> map = jsonReader.readObject();

                String typeField = (String) map.get(IEnum.ENUM_TYPE);
                Object valField = map.get(Dict.ENUM_VAL);


                Class<?> clazz = CLASSLOADER.loadClass(typeField);

                if (valField instanceof String) {
                    if (DictStr.class.isAssignableFrom(clazz)) {
                        DictStr[] constants = (DictStr[]) clazz.getEnumConstants();
                        return Dict.parse((String) valField, constants);
                    } else if (DictInt.class.isAssignableFrom(clazz)) {
                        DictInt[] constants = (DictInt[]) clazz.getEnumConstants();
                        return Dict.parse(Integer.parseInt((String) valField), constants);
                    } else {
                        return null;
                    }
                } else if (valField instanceof Integer) {
                    if (DictStr.class.isAssignableFrom(clazz)) {
                        DictStr[] constants = (DictStr[]) clazz.getEnumConstants();
                        return Dict.parse(String.valueOf(valField), constants);
                    } else if (DictInt.class.isAssignableFrom(clazz)) {
                        DictInt[] constants = (DictInt[]) clazz.getEnumConstants();
                        return Dict.parse((Integer) valField, constants);
                    } else {
                        return null;
                    }
                } else {
                    return null;
                }
            } else {
                if (jsonReader.isString()) {
                    Class<?> clazz = TypeUtils.getClass(fieldType);
                    if (DictStr.class.isAssignableFrom(clazz)) {
                        String val = jsonReader.readString();
                        DictStr[] constants = (DictStr[]) clazz.getEnumConstants();
                        return Dict.parse(val, constants);
                    } else if (DictInt.class.isAssignableFrom(clazz)) {
                        String val = jsonReader.readString();
                        DictInt[] constants = (DictInt[]) clazz.getEnumConstants();
                        return Dict.parse(Integer.parseInt(val), constants);
                    } else {
                        return null;
                    }
                } else if (jsonReader.isInt()) {
                    Class<?> clazz = TypeUtils.getClass(fieldType);
                    if (DictStr.class.isAssignableFrom(clazz)) {
                        String val = jsonReader.readString();
                        DictStr[] constants = (DictStr[]) clazz.getEnumConstants();
                        return Dict.parse(val, constants);
                    } else if (DictInt.class.isAssignableFrom(clazz)) {
                        Integer val = jsonReader.readInt32();
                        DictInt[] constants = (DictInt[]) clazz.getEnumConstants();
                        return Dict.parse(val, constants);
                    } else {
                        return null;
                    }
                } else {
                    return null;
                }
            }
        } catch (Exception e) {
            log.error("字典枚举反序列化失败", e);
            throw Exceptions.error(e, "字典枚举反序列化失败，类型：{}，字段名：{}", fieldType, fieldName);
        }
    }
}
