/*
 * Copyright 2017 Product Mog LLC.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.lokalized;

import javax.annotation.Nonnull;
import javax.annotation.concurrent.ThreadSafe;
import java.math.BigDecimal;
import java.math.BigInteger;

import static java.util.Objects.requireNonNull;

/**
 * Collection of utility methods for working with numbers.
 *
 * @author <a href="https://revetkn.com">Mark Allen</a>
 */
@ThreadSafe
class NumberUtils {
  private NumberUtils() {
    // Non-instantiable
  }

  /**
   * Determines the number of decimal places in the given number.
   * <p>
   * If the number is a {@link BigDecimal}, then the scale (which may include trailing zeroes) is returned.
   * <p>
   * Otherwise, the number of decimal places without trailing zeroes is returned.
   * <p>
   * For example:
   * <p>
   * <ul>
   * <li>{@code 2} has {@code 0} decimal places</li>
   * <li>{@code 2.1} has {@code 1} decimal place</li>
   * <li>{@code 2.150} has {@code 2} decimal places (if non-{@code BigDecimal}) and 3 decimal places (if {@code BigDecimal})</li>
   * </ul>
   *
   * @param number the number for which we are counting decimal places, not null
   * @return the number of decimal places, not null
   */
  @Nonnull
  static Integer numberOfDecimalPlaces(@Nonnull Number number) {
    requireNonNull(number);

    if (number instanceof BigDecimal) {
      // Can determine trailing zeroes in this case
      BigDecimal numberAsBigDecimal = (BigDecimal) number;
      return numberAsBigDecimal.scale();
    }

    // Cannot determine trailing zeroes in this case
    BigDecimal numberAsBigDecimal = new BigDecimal(String.valueOf(number.doubleValue()));
    return Math.max(0, numberAsBigDecimal.stripTrailingZeros().scale());
  }

  /**
   * Determines the integer component of the given number.
   * <p>
   * For example:
   * <p>
   * <ul>
   * <li>{@code 2} has an integer component of {@code 2}</li>
   * <li>{@code 1.234} has an integer component of {@code 1}</li>
   * <li>{@code -1.5} has an integer component of {@code -1}</li>
   * <li>{@code .5} has an integer component of {@code 0}</li>
   * </ul>
   *
   * @param number the number for which we are determining the integer component, not null
   * @return the integer component, not null
   */
  static BigInteger integerComponent(@Nonnull Number number) {
    requireNonNull(number);

    if (number instanceof BigDecimal) {
      BigDecimal numberAsBigDecimal = (BigDecimal) number;
      return numberAsBigDecimal.toBigInteger();
    }

    return new BigDecimal(String.valueOf(number.doubleValue())).toBigInteger();
  }
}
@@ -2126,20 +2126,18 @@
 cimal = 
-new 
+to
 BigDecim
@@ -2143,44 +2143,14 @@
 mal(
-String.valueOf(number.doubleValue())
+number
 );%0A 
@@ -2752,16 +2752,27 @@
 l%0A   */%0A
+  @Nonnull%0A
   static
@@ -3005,24 +3005,493 @@
 r();%0A    %7D%0A%0A
+    return toBigDecimal(number).toBigInteger();%0A  %7D%0A%0A  /**%0A   * Provides a %7B@code BigDecimal%7D representation of the given number.%0A   *%0A   * @param number the number to represent as a %7B@code BigDecimal%7D, not null%0A   * @return a %7B@code BigDecimal%7D representation of the given number, not null%0A   */%0A  @Nonnull%0A  static BigDecimal toBigDecimal(@Nonnull Number number) %7B%0A    requireNonNull(number);%0A%0A    if (number instanceof BigDecimal)%0A      return (BigDecimal) number;%0A%0A
     return n
@@ -3541,30 +3541,15 @@
 alue()))
-.toBigInteger()
 ;%0A  %7D%0A%7D

Introduce NumberUtils#toBigDecimal(Number)