package com.fjhx.utils;

import cn.hutool.core.convert.Convert;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 精确的浮点数运算
 */
public class BigDecimalUtil {

    private BigDecimalUtil() {
    }

    /**
     * 值保留几位小数
     */
    public static BigDecimal keepDecimals(Object value, int scale) {
        if (value == null) {
            return BigDecimal.ZERO.setScale(scale, RoundingMode.HALF_UP);
        }
        return (objToBigDecimal(value)).setScale(scale, RoundingMode.HALF_UP);
    }

    /**
     * 默认保留2位小数
     */
    public static BigDecimal keepDecimals(Object value) {
        if (value == null) {
            return BigDecimal.ZERO.setScale(2, RoundingMode.HALF_UP);
        }
        return (objToBigDecimal(value)).setScale(2, RoundingMode.HALF_UP);
    }

    /**
     * 加法运算
     */
    public static BigDecimal add(Object v1, Object v2) {
        return objToBigDecimal(v1).add(objToBigDecimal(v2));
    }

    /**
     * 减法运算
     */
    public static BigDecimal subtract(Object v1, Object v2) {
        return objToBigDecimal(v1).add(objToBigDecimal(v2));
    }

    /**
     * 乘法运算
     */
    public static BigDecimal multiply(Object v1, Object v2) {
        return objToBigDecimal(v1).multiply(objToBigDecimal(v2));
    }

    /**
     * 乘法运算
     */
    public static BigDecimal multiply(Object v1, Object v2, int scale) {
        return objToBigDecimal(v1).multiply(objToBigDecimal(v2).setScale(scale, RoundingMode.HALF_UP));
    }

    /**
     * 乘法运算
     */
    public static BigDecimal multiply(Object v1, Object v2, int scale, RoundingMode roundingMode) {
        return objToBigDecimal(v1).multiply(objToBigDecimal(v2).setScale(scale, roundingMode));
    }

    /**
     * 除法运算
     */
    public static BigDecimal divide(Object v1, Object v2, int scale) {
        return objToBigDecimal(v1).divide(objToBigDecimal(v2), scale, RoundingMode.HALF_UP);
    }

    /**
     * 大于
     */
    public static boolean gt(Object v1, Object v2) {
        return objToBigDecimal(v1).compareTo(objToBigDecimal(v2)) > 0;
    }

    /**
     * 大于等于
     */
    public static boolean ge(Object v1, Object v2) {
        return objToBigDecimal(v1).compareTo(objToBigDecimal(v2)) >= 0;
    }

    /**
     * 小于
     */
    public static boolean lt(Object v1, Object v2) {
        return objToBigDecimal(v1).compareTo(objToBigDecimal(v2)) < 0;
    }

    /**
     * 小于等于
     */
    public static boolean le(Object v1, Object v2) {
        return objToBigDecimal(v1).compareTo(objToBigDecimal(v2)) <= 0;
    }

    /**
     * 等于
     */
    public static boolean eq(Object v1, Object v2) {
        return objToBigDecimal(v1).compareTo(objToBigDecimal(v2)) == 0;
    }

    /**
     * 取最大值
     */
    public static BigDecimal max(Object v1, Object v2) {
        BigDecimal b1 = objToBigDecimal(v1);
        BigDecimal b2 = objToBigDecimal(v2);
        return b1.compareTo(b2) >= 0 ? b1 : b2;
    }

    /**
     * 取最小值
     */
    public static BigDecimal min(Object v1, Object v2) {
        BigDecimal b1 = objToBigDecimal(v1);
        BigDecimal b2 = objToBigDecimal(v2);
        return b1.compareTo(b2) >= 0 ? b2 : b1;
    }

    /*
     * ==============================================================================================
     * 以下为链式调用方法
     * ==============================================================================================
     */

    /**
     * 结果值
     */
    private BigDecimal bigDecimal;

    /**
     * 初始化
     */
    public static BigDecimalUtil init() {
        BigDecimalUtil bigDecimalUtil = new BigDecimalUtil();
        bigDecimalUtil.bigDecimal = BigDecimal.ZERO;
        return bigDecimalUtil;
    }

    /**
     * 初始化
     */
    public static BigDecimalUtil init(Object value) {
        BigDecimalUtil bigDecimalUtil = new BigDecimalUtil();
        bigDecimalUtil.bigDecimal = objToBigDecimal(value);
        return bigDecimalUtil;
    }

    /**
     * 加法运算
     */
    public BigDecimalUtil add(Object value) {
        bigDecimal = bigDecimal.add(objToBigDecimal(value));
        return this;
    }

    /**
     * 减法运算
     */
    public BigDecimalUtil subtract(Object value) {
        bigDecimal = bigDecimal.subtract(objToBigDecimal(value));
        return this;
    }

    /**
     * 乘法运算
     */
    public BigDecimalUtil multiply(Object value) {
        bigDecimal = bigDecimal.multiply(objToBigDecimal(value));
        return this;
    }

    /**
     * 除法运算
     */
    public BigDecimalUtil divide(Object value, int scale) {
        bigDecimal = bigDecimal.divide(objToBigDecimal(value), scale, RoundingMode.HALF_UP);
        return this;
    }

    /**
     * 除法运算
     */
    public BigDecimalUtil divideTry(Object value, int scale) {
        BigDecimal bigDecimal = objToBigDecimal(value);
        if (bigDecimal.compareTo(BigDecimal.ZERO) == 0) {
            this.bigDecimal = BigDecimal.ZERO;
            return this;
        }

        this.bigDecimal = this.bigDecimal.divide(bigDecimal, scale, RoundingMode.HALF_UP);
        return this;
    }


    /**
     * 获取计算结果值
     */
    public BigDecimal getValue() {
        return bigDecimal;
    }

    /**
     * 获取计算结果值，并指定保留位数
     */
    public BigDecimal getValue(int scale) {
        return bigDecimal.setScale(scale, RoundingMode.HALF_UP);
    }

    /**
     * Object转BigDecimal
     */
    public static BigDecimal objToBigDecimal(Object value) {
        if (value == null) {
            throw new NullPointerException("参与计算的字段为空");
        }
        return Convert.toBigDecimal(value);
    }

}
