package org.knowm.xchange.utils;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import org.knowm.xchange.dto.Order;
import org.knowm.xchange.dto.meta.CurrencyPairMetaData;

/**
 * Helps you to validate and / or adjust order values like price and amount to the restrictions
 * dictated by {@link CurrencyPairMetaData}
 *
 * @author walec51
 */
public class OrderValuesHelper {

  private final CurrencyPairMetaData metaData;

  public OrderValuesHelper(CurrencyPairMetaData metaData) {
    this.metaData = metaData;
  }

  /**
   * @return true if the minimum amount is specified in the currency pair and if the amount is under
   *     it
   */
  public boolean amountUnderMinimum(BigDecimal amount) {
    BigDecimal minimalAmount = metaData.getMinimumAmount();
    if (minimalAmount == null) {
      return false;
    }
    return amount.compareTo(minimalAmount) < 0;
  }

  /**
   * Adjusts the given amount to the restrictions dictated by {@link CurrencyPairMetaData}.
   *
   * <p>This mainly does rounding based on {@link CurrencyPairMetaData#getBaseScale()} and {@link
   * CurrencyPairMetaData#getAmountStepSize()} if they are present in the metadata. It will also
   * return the maximum allowed amount if {@link CurrencyPairMetaData#getMaximumAmount() ()} is set
   * and your amount is greater.
   *
   * @param amount the amount your derived from your users input or your calculations
   * @return amount adjusted to the restrictions dictated by {@link CurrencyPairMetaData}
   */
  public BigDecimal adjustAmount(BigDecimal amount) {
    BigDecimal maximumAmount = metaData.getMaximumAmount();
    if (maximumAmount != null && amount.compareTo(maximumAmount) > 0) {
      return maximumAmount;
    }
    BigDecimal result = amount;
    BigDecimal stepSize = metaData.getAmountStepSize();
    if (stepSize != null && stepSize.compareTo(BigDecimal.ZERO) != 0) {
      BigDecimal divided =
          amount.divide(stepSize, MathContext.DECIMAL32).setScale(0, RoundingMode.FLOOR);
      result = divided.multiply(stepSize, MathContext.DECIMAL32).stripTrailingZeros();
    }
    Integer baseScale = metaData.getBaseScale();
    if (baseScale != null) {
      result = result.setScale(baseScale, RoundingMode.FLOOR);
    }
    return result;
  }

  public BigDecimal adjustPrice(BigDecimal price, Order.OrderType orderType) {
    return adjustPrice(
        price,
        orderType == Order.OrderType.ASK || orderType == Order.OrderType.EXIT_ASK
            ? RoundingMode.CEILING
            : RoundingMode.FLOOR);
  }

  /**
   * Adjusts the given price to the restrictions dictated by {@link CurrencyPairMetaData}.
   *
   * <p>This mainly does rounding based on {@link CurrencyPairMetaData#getPriceScale()} if it is
   * present in the metadata.
   *
   * @param price the price your derived from your users input or your calculations
   * @return price adjusted to the restrictions dictated by {@link CurrencyPairMetaData}
   */
  public BigDecimal adjustPrice(BigDecimal price, RoundingMode roundingMode) {
    BigDecimal result = price;
    Integer scale = metaData.getPriceScale();
    if (scale != null) {
      result = result.setScale(scale, roundingMode);
    }
    return result;
  }
}

@@ -60,38 +60,8 @@
 al;%0A
-import java.math.MathContext;%0A
 impo
@@ -1884,16 +1884,25 @@
  %7B%0A     
+ result =
  BigDeci
@@ -1908,193 +1908,66 @@
 imal
- divided =%0A          amount.divide(stepSize, MathContext.DECIMAL32).setScale(0, RoundingMode.FLOOR);%0A      result = divided.multiply(stepSize, MathContext.DECIMAL32).stripTrailingZeros(
+Utils.roundToStepSize(result, stepSize, RoundingMode.FLOOR
 );%0A 

use BigDecimalUtils in OrderValuesHelper