package com.jiayue.ipfcst.common.core.util;

import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;

/**
 * 提供高精度的运算支持
 *
 * @author bizy
 * @version 2.0
 */
@Slf4j
public class NumberUtils {
    private NumberUtils() {
    }

    /**
     * 精确的加法运算.
     *
     * @param b1    加数
     * @param b2    加数
     * @param scale 运算结果小数后精确的位数
     * @return 结果
     */
    public static BigDecimal add(BigDecimal b1, BigDecimal b2, int scale) {
        return b1.add(b2).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 精确的加法运算.
     *
     * @param b1 加数
     * @param b2 加数
     * @return 保留2位小数
     */
    public static BigDecimal add(BigDecimal b1, BigDecimal b2) {
        return b1.add(b2).setScale(2, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 精确的减法运算.
     *
     * @param b1    被减数
     * @param b2    减数
     * @param scale 运算结果小数后精确的位数
     * @return 结果
     */
    public static BigDecimal subtract(BigDecimal b1, BigDecimal b2, int scale) {
        return b1.subtract(b2).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }


    /**
     * 精确的减法运算.
     *
     * @param b1 被减数
     * @param b2 减数
     * @return 结果 保留2位小数
     */
    public static BigDecimal subtract(BigDecimal b1, BigDecimal b2) {
        return b1.subtract(b2).setScale(2, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 提供精确的乘法运算，并对运算结果截位.
     *
     * @param b1    乘数
     * @param b2    乘数
     * @param scale 运算结果小数后精确的位数
     * @return 结果
     */
    public static BigDecimal multiply(BigDecimal b1, BigDecimal b2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        return b1.multiply(b2).setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 提供精确的乘法运算，并对运算结果截位.
     *
     * @param b1 乘数
     * @param b2 乘数
     * @return 结果 保留2位小数
     */
    public static BigDecimal multiply(BigDecimal b1, BigDecimal b2) {
        return b1.multiply(b2).setScale(2, BigDecimal.ROUND_HALF_UP);
    }


    /**
     * 提供（相对）精确的除法运算. 由scale参数指定精度，以后的数字四舍五入.
     *
     * @param b1    被除数
     * @param b2    除数
     * @param scale 表示表示需要精确到小数点以后几位
     * @return 结果
     */
    public static BigDecimal divide(BigDecimal b1, BigDecimal b2, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 提供（相对）精确的除法运算. 由scale参数指定精度，以后的数字四舍五入.
     *
     * @param b1 被除数
     * @param b2 除数
     * @return 结果 保留2位小数
     */
    public static BigDecimal divide(BigDecimal b1, BigDecimal b2) {
        return b1.divide(b2, 2, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 提供精确的小数位四舍五入处理.
     *
     * @param b     需要四舍五入的数字
     * @param scale 小数点后保留几位
     * @return TODO
     */
    public static BigDecimal round(BigDecimal b, int scale) {
        if (scale < 0) {
            throw new IllegalArgumentException("The scale must be a positive integer or zero");
        }
        return b.setScale(scale, BigDecimal.ROUND_HALF_UP);
    }

    /**
     * 提供精确的小数位四舍五入处理.
     *
     * @param b 需要四舍五入的数字
     * @return 保留2位小数
     */
    public static BigDecimal round(BigDecimal b) {
        return b.setScale(2, BigDecimal.ROUND_HALF_UP);
    }
}
