package cn.com.ty.lift.business.framework.conf;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.JsonTokenId;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.deser.std.StdScalarDeserializer;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.Objects;

/**
 * BigDecimal反序列化: 默认四舍五入保留两位小数
 *
 * @author wcz
 * @since 2020/4/26
 */
public class BigDecimalDeserializer extends StdScalarDeserializer<BigDecimal> {

    public static final BigDecimalDeserializer instance = new BigDecimalDeserializer();

    public BigDecimalDeserializer() {
        super(BigDecimal.class);
    }

    @Override
    public Object getEmptyValue(DeserializationContext context) {
        return BigDecimal.ZERO;
    }

    @Override
    public BigDecimal deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException {
        BigDecimal value;
        switch (parser.getCurrentTokenId()) {
            case JsonTokenId.ID_NUMBER_INT:
            case JsonTokenId.ID_NUMBER_FLOAT:
                value = parser.getDecimalValue();
                break;
            case JsonTokenId.ID_STRING:
                String text = parser.getText().trim();
                // note: no need to call `coerce` as this is never primitive
                if (_isEmptyOrTextualNull(text)) {
                    _verifyNullForScalarCoercion(context, text);
                    value = getNullValue(context);
                    break;
                }
                _verifyStringForScalarCoercion(context, text);
                try {
                    value = new BigDecimal(text);
                    break;
                } catch (IllegalArgumentException ignore) {
                }
                value = ((BigDecimal) context.handleWeirdStringValue(_valueClass, text, "not a valid representation"));
                break;
            case JsonTokenId.ID_START_ARRAY:
                value = _deserializeFromArray(parser, context);
                break;
            default:
                // Otherwise, no can do:
                value = ((BigDecimal) context.handleUnexpectedToken(_valueClass, parser));
        }
        if (Objects.nonNull(value)) {
            return value.setScale(2, BigDecimal.ROUND_HALF_UP);
        } else {
            return value;
        }
    }
}
