package com.hdkj.lt.base.serializer;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.hdkj.lt.base.annotations.DecimalFormat;
import org.apache.commons.lang3.StringUtils;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @Description:
 * @Author: wenhao
 * @Create: 2022/10/18 14:07
 * @Version: 1.0
 */
public class DecimalFormatJsonDeserializer extends JsonDeserializer<Object> {

    private static final Pattern NUMBER_PATTERN = Pattern.compile("-?[0-9]+.?[0-9]*");

    @Override
    public Object deserialize(JsonParser parser, DeserializationContext context) {
        // 默认是要抛出异常的，如果出现异常并且没有抛出异常的情况需要返回默认值
        boolean isThrowException = true;
        double defaultVal = 0.0;
        // 当前转换的字段的类型
        Class<?> type = null;
        try {
            String numStr = parser.getText();
            Class<?> clazz = parser.getCurrentValue().getClass();
            Field field = clazz.getDeclaredField(parser.getCurrentName());
            // 加了注解才会进入到这个方法，这里就不再校验注解为null的情况
            DecimalFormat annotation = field.getAnnotation(DecimalFormat.class);
            // 保留的小数位数
            int scale = annotation.scale();
            // 是否抛出异常
            isThrowException = annotation.isThrowException();
            // 默认值
            defaultVal = annotation.defaultVal();
            // 格式化的规则，默认是四舍五入
            RoundingMode roundMode = annotation.roundMode();
            // 需要转换的字段类型
            type = field.getType();
            // 空字符串和非数字字符
            if (StringUtils.isEmpty(numStr) || !isNumeric(numStr)) {
                if (type == String.class) {
                    return String.valueOf(defaultVal);
                }
                return defaultVal;
            }
            BigDecimal decimalValue = new BigDecimal(numStr);
            if (type == String.class) {
                return decimalValue.setScale(scale, roundMode).toString();
            }
            return decimalValue.setScale(scale, roundMode).doubleValue();
        } catch (Exception e) {
            if (isThrowException) {
                throw new RuntimeException(e.getMessage());
            } else {
                if (type == String.class) {
                    return String.valueOf(defaultVal);
                }
                return defaultVal;
            }
        }
    }

    public boolean isNumeric(String str) {
        Matcher isNum = NUMBER_PATTERN.matcher(str);
        return isNum.matches();
    }

}
