// © 2017 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html
package com.ibm.icu.dev.impl.number;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.text.FieldPosition;

import com.ibm.icu.impl.StandardPlural;
import com.ibm.icu.impl.number.DecimalQuantity;
import com.ibm.icu.impl.number.Modifier.Signum;
import com.ibm.icu.text.PluralRules;
import com.ibm.icu.text.PluralRules.Operand;
import com.ibm.icu.text.UFieldPosition;

/**
 * This is an older implementation of DecimalQuantity. A newer, faster implementation is
 * DecimalQuantity2. I kept this implementation around because it was useful for testing purposes
 * (being able to compare the output of one implementation with the other).
 *
 * <p>This class is NOT IMMUTABLE and NOT THREAD SAFE and is intended to be used by a single thread
 * to format a number through a formatter, which is thread-safe.
 */
public class DecimalQuantity_SimpleStorage implements DecimalQuantity {
  // Four positions: left optional '(', left required '[', right required ']', right optional ')'.
  // These four positions determine which digits are displayed in the output string.  They do NOT
  // affect rounding.  These positions are internal-only and can be specified only by the public
  // endpoints like setFractionLength, setIntegerLength, and setSignificantDigits, among others.
  //
  //   * Digits between lReqPos and rReqPos are in the "required zone" and are always displayed.
  //   * Digits between lOptPos and rOptPos but outside the required zone are in the "optional zone"
  //     and are displayed unless they are trailing off the left or right edge of the number and
  //     have a numerical value of zero.  In order to be "trailing", the digits need to be beyond
  //     the decimal point in their respective directions.
  //   * Digits outside of the "optional zone" are never displayed.
  //
  // See the table below for illustrative examples.
  //
  // +---------+---------+---------+---------+------------+------------------------+--------------+
  // | lOptPos | lReqPos | rReqPos | rOptPos |   number   |        positions       | en-US string |
  // +---------+---------+---------+---------+------------+------------------------+--------------+
  // |    5    |    2    |   -1    |   -5    |   1234.567 |     ( 12[34.5]67  )    |   1,234.567  |
  // |    3    |    2    |   -1    |   -5    |   1234.567 |      1(2[34.5]67  )    |     234.567  |
  // |    3    |    2    |   -1    |   -2    |   1234.567 |      1(2[34.5]6)7      |     234.56   |
  // |    6    |    4    |    2    |   -5    | 123456789. |  123(45[67]89.     )   | 456,789.     |
  // |    6    |    4    |    2    |    1    | 123456789. |     123(45[67]8)9.     | 456,780.     |
  // |   -1    |   -1    |   -3    |   -4    | 0.123456   |     0.1([23]4)56       |        .0234 |
  // |    6    |    4    |   -2    |   -2    |     12.3   |     (  [  12.3 ])      |    0012.30   |
  // +---------+---------+---------+---------+------------+------------------------+--------------+
  //
  private int lOptPos = Integer.MAX_VALUE;
  private int lReqPos = 0;
  private int rReqPos = 0;
  private int rOptPos = Integer.MIN_VALUE;

  // Internally, attempt to use a long to store the number. A long can hold numbers between 18 and
  // 19 digits, covering the vast majority of use cases. We store three values: the long itself,
  // the "scale" of the long (the power of 10 represented by the rightmost digit in the long), and
  // the "precision" (the number of digits in the long). "primary" and "primaryScale" are the only
  // two variables that are required for representing the number in memory. "primaryPrecision" is
  // saved only for the sake of performance enhancements when performing certain operations. It can
  // always be re-computed from "primary" and "primaryScale".
  private long primary;
  private int primaryScale;
  private int primaryPrecision;

  // If the decimal can't fit into the long, fall back to a BigDecimal.
  private BigDecimal fallback;

  // Other properties
  private int flags;
  private static final int NEGATIVE_FLAG = 1;
  private static final int INFINITY_FLAG = 2;
  private static final int NAN_FLAG = 4;
  private static final long[] POWERS_OF_TEN = {
    1L,
    10L,
    100L,
    1000L,
    10000L,
    100000L,
    1000000L,
    10000000L,
    100000000L,
    1000000000L,
    10000000000L,
    100000000000L,
    1000000000000L,
    10000000000000L,
    100000000000000L,
    1000000000000000L,
    10000000000000000L,
    100000000000000000L,
    1000000000000000000L
  };

  private int origPrimaryScale;

  @Override
  public int maxRepresentableDigits() {
    return Integer.MAX_VALUE;
  }

  public DecimalQuantity_SimpleStorage(long input) {
    if (input < 0) {
      setNegative(true);
      input *= -1;
    }

    primary = input;
    primaryScale = 0;
    primaryPrecision = computePrecision(primary);
    fallback = null;
    origPrimaryScale = primaryScale;
  }

  /**
   * Creates a DecimalQuantity from the given double value. Internally attempts several strategies
   * for converting the double to an exact representation, falling back on a BigDecimal if it fails
   * to do so.
   *
   * @param input The double to represent by this DecimalQuantity.
   */
  public DecimalQuantity_SimpleStorage(double input) {
    if (input < 0) {
      setNegative(true);
      input *= -1;
    }

    // First try reading from IEEE bits. This is trivial only for doubles in [2^52, 2^64). If it
    // fails, we wasted only a few CPU cycles.
    long ieeeBits = Double.doubleToLongBits(input);
    int exponent = (int) ((ieeeBits & 0x7ff0000000000000L) >> 52) - 0x3ff;
    if (exponent >= 52 && exponent <= 63) {
      // We can convert this double directly to a long.
      long mantissa = (ieeeBits & 0x000fffffffffffffL) + 0x0010000000000000L;
      primary = (mantissa << (exponent - 52));
      primaryScale = 0;
      primaryPrecision = computePrecision(primary);
      return;
    }

    // Now try parsing the string produced by Double.toString().
    String temp = Double.toString(input);
    try {
      if (temp.length() == 3 && temp.equals("0.0")) {
        // Case 1: Zero.
        primary = 0L;
        primaryScale = 0;
        primaryPrecision = 0;
      } else if (temp.indexOf('E') != -1) {
        // Case 2: Exponential notation.
        assert temp.indexOf('.') == 1;
        int expPos = temp.indexOf('E');
        primary = Long.parseLong(temp.charAt(0) + temp.substring(2, expPos));
        primaryScale = Integer.parseInt(temp.substring(expPos + 1)) - (expPos - 1) + 1;
        primaryPrecision = expPos - 1;
      } else if (temp.charAt(0) == '0') {
        // Case 3: Fraction-only number.
        assert temp.indexOf('.') == 1;
        primary = Long.parseLong(temp.substring(2)); // ignores leading zeros
        primaryScale = 2 - temp.length();
        primaryPrecision = computePrecision(primary);
      } else if (temp.charAt(temp.length() - 1) == '0') {
        // Case 4: Integer-only number.
        assert temp.indexOf('.') == temp.length() - 2;
        int rightmostNonzeroDigitIndex = temp.length() - 3;
        while (temp.charAt(rightmostNonzeroDigitIndex) == '0') {
          rightmostNonzeroDigitIndex -= 1;
        }
        primary = Long.parseLong(temp.substring(0, rightmostNonzeroDigitIndex + 1));
        primaryScale = temp.length() - rightmostNonzeroDigitIndex - 3;
        primaryPrecision = rightmostNonzeroDigitIndex + 1;
      } else if (temp.equals("Infinity")) {
        // Case 5: Infinity.
        primary = 0;
        setInfinity(true);
      } else if (temp.equals("NaN")) {
        // Case 6: NaN.
        primary = 0;
        setNaN(true);
      } else {
        // Case 7: Number with both a fraction and an integer.
        int decimalPos = temp.indexOf('.');
        primary = Long.parseLong(temp.substring(0, decimalPos) + temp.substring(decimalPos + 1));
        primaryScale = decimalPos - temp.length() + 1;
        primaryPrecision = temp.length() - 1;
      }
    } catch (NumberFormatException e) {
      // The digits of the double can't fit into the long.
      primary = -1;
      fallback = new BigDecimal(temp);
    }

    origPrimaryScale = primaryScale;
  }

  static final double LOG_2_OF_TEN = 3.32192809489;

  public DecimalQuantity_SimpleStorage(double input, boolean fast) {
    if (input < 0) {
      setNegative(true);
      input *= -1;
    }

    // Our strategy is to read all digits that are *guaranteed* to be valid without delving into
    // the IEEE rounding rules.  This strategy might not end up with a perfect representation of
    // the fractional part of the double.
    long ieeeBits = Double.doubleToLongBits(input);
    int exponent = (int) ((ieeeBits & 0x7ff0000000000000L) >> 52) - 0x3ff;
    long mantissa = (ieeeBits & 0x000fffffffffffffL) + 0x0010000000000000L;
    if (exponent > 63) {
      throw new IllegalArgumentException(); // FIXME
    } else if (exponent >= 52) {
      primary = (mantissa << (exponent - 52));
      primaryScale = 0;
      primaryPrecision = computePrecision(primary);
      return;
    } else if (exponent >= 0) {
      int shift = 52 - exponent;
      primary = (mantissa >> shift); // integer part
      int fractionCount = (int) (shift / LOG_2_OF_TEN);
      long fraction = (mantissa - (primary << shift)) + 1L; // TODO: Explain the +1L
      primary *= POWERS_OF_TEN[fractionCount];
      for (int i = 0; i < fractionCount; i++) {
        long times10 = (fraction * 10L);
        long digit = times10 >> shift;
        assert digit >= 0 && digit < 10;
        primary += digit * POWERS_OF_TEN[fractionCount - i - 1];
        fraction = times10 & ((1L << shift) - 1);
      }
      primaryScale = -fractionCount;
      primaryPrecision = computePrecision(primary);
    } else {
      throw new IllegalArgumentException(); // FIXME
    }
  }

  public DecimalQuantity_SimpleStorage(BigDecimal decimal) {
    setToBigDecimal(decimal);
  }

  public DecimalQuantity_SimpleStorage(DecimalQuantity_SimpleStorage other) {
    copyFrom(other);
  }

  @Override
  public void setToBigDecimal(BigDecimal decimal) {
    if (decimal.compareTo(BigDecimal.ZERO) < 0) {
      setNegative(true);
      decimal = decimal.negate();
    }

    primary = -1;
    if (decimal.compareTo(BigDecimal.ZERO) == 0) {
      fallback = BigDecimal.ZERO;
    } else {
      fallback = decimal;
    }
  }

  @Override
  public DecimalQuantity_SimpleStorage createCopy() {
    return new DecimalQuantity_SimpleStorage(this);
  }

  /**
   * Make the internal state of this DecimalQuantity equal to another DecimalQuantity.
   *
   * @param other The template DecimalQuantity. All properties from this DecimalQuantity will be
   *     copied into this DecimalQuantity.
   */
  @Override
  public void copyFrom(DecimalQuantity other) {
    // TODO: Check before casting
    DecimalQuantity_SimpleStorage _other = (DecimalQuantity_SimpleStorage) other;
    lOptPos = _other.lOptPos;
    lReqPos = _other.lReqPos;
    rReqPos = _other.rReqPos;
    rOptPos = _other.rOptPos;
    primary = _other.primary;
    primaryScale = _other.primaryScale;
    primaryPrecision = _other.primaryPrecision;
    fallback = _other.fallback;
    flags = _other.flags;
    origPrimaryScale = _other.origPrimaryScale;
  }

  @Override
  public long getPositionFingerprint() {
    long fingerprint = 0;
    fingerprint ^= lOptPos;
    fingerprint ^= (lReqPos << 16);
    fingerprint ^= ((long) rReqPos << 32);
    fingerprint ^= ((long) rOptPos << 48);
    return fingerprint;
  }

  /**
   * Utility method to compute the number of digits ("precision") in a long.
   *
   * @param input The long (which can't contain more than 19 digits).
   * @return The precision of the long.
   */
  private static int computePrecision(long input) {
    int precision = 0;
    while (input > 0) {
      input /= 10;
      precision++;
    }
    return precision;
  }

  /**
   * Changes the internal representation from a long to a BigDecimal. Used only for operations that
   * don't support longs.
   */
  private void convertToBigDecimal() {
    if (primary == -1) {
      return;
    }

    fallback = new BigDecimal(primary).scaleByPowerOfTen(primaryScale);
    primary = -1;
  }

  @Override
  public long toLong(boolean truncateIfOverflow) {
    BigDecimal temp = toBigDecimal().setScale(0, RoundingMode.FLOOR);
    if (truncateIfOverflow) {
      return temp.longValue();
    } else {
      return temp.longValueExact();
    }
  }

  @Override
  public void setMinInteger(int minInt) {
    // Graceful failures for bogus input
    minInt = Math.max(0, minInt);

    // Save values into internal state
    // Negation is safe for minFrac/maxFrac because -Integer.MAX_VALUE > Integer.MIN_VALUE
    lReqPos = minInt;
  }

  @Override
  public void setMinFraction(int minFrac) {
    // Graceful failures for bogus input
    minFrac = Math.max(0, minFrac);

    // Save values into internal state
    // Negation is safe for minFrac/maxFrac because -Integer.MAX_VALUE > Integer.MIN_VALUE
    rReqPos = -minFrac;
  }

  @Override
  public void applyMaxInteger(int maxInt) {
    BigDecimal d;
    if (primary != -1) {
      d = BigDecimal.valueOf(primary).scaleByPowerOfTen(primaryScale);
    } else {
      d = fallback;
    }
    d = d.scaleByPowerOfTen(-maxInt).remainder(BigDecimal.ONE).scaleByPowerOfTen(maxInt);
    if (primary != -1) {
      primary = d.scaleByPowerOfTen(-primaryScale).longValueExact();
    } else {
      fallback = d;
    }
  }

  @Override
  public void roundToIncrement(BigDecimal roundingInterval, MathContext mathContext) {
    BigDecimal d =
        (primary == -1) ? fallback : new BigDecimal(primary).scaleByPowerOfTen(primaryScale);
    if (isNegative()) d = d.negate();
    d = d.divide(roundingInterval, 0, mathContext.getRoundingMode()).multiply(roundingInterval);
    if (isNegative()) d = d.negate();
    fallback = d;
    primary = -1;
  }

  @Override
  public void roundToNickel(int roundingMagnitude, MathContext mathContext) {
    BigDecimal nickel = BigDecimal.valueOf(5).scaleByPowerOfTen(roundingMagnitude);
    roundToIncrement(nickel, mathContext);
  }

  @Override
  public void roundToMagnitude(int roundingMagnitude, MathContext mathContext) {
    if (roundingMagnitude < -1000) {
      roundToInfinity();
      return;
    }
    if (primary == -1) {
      if (isNegative()) fallback = fallback.negate();
      fallback = fallback.setScale(-roundingMagnitude, mathContext.getRoundingMode());
      if (isNegative()) fallback = fallback.negate();
      // Enforce the math context.
      fallback = fallback.round(mathContext);
    } else {
      int relativeScale = primaryScale - roundingMagnitude;
      if (relativeScale < -18) {
        // No digits will remain after rounding the number.
        primary = 0L;
        primaryScale = roundingMagnitude;
        primaryPrecision = 0;
      } else if (relativeScale < 0) {
        // This is the harder case, when we need to perform the rounding logic.
        // First check if the rightmost digits are already zero, where we can skip rounding.
        if ((primary % POWERS_OF_TEN[0 - relativeScale]) == 0) {
          // No rounding is necessary.
        } else {
          // TODO: Make this more efficient. Temporarily, convert to a BigDecimal and back again.
          BigDecimal temp = new BigDecimal(primary).scaleByPowerOfTen(primaryScale);
          if (isNegative()) temp = temp.negate();
          temp = temp.setScale(-roundingMagnitude, mathContext.getRoundingMode());
          if (isNegative()) temp = temp.negate();
          temp = temp.scaleByPowerOfTen(-roundingMagnitude);
          primary = temp.longValueExact(); // should never throw
          primaryScale = roundingMagnitude;
          primaryPrecision = computePrecision(primary);
        }
      } else {
        // No rounding is necessary. All digits are to the left of the rounding magnitude.
      }
      // Enforce the math context.
      primary = new BigDecimal(primary).round(mathContext).longValueExact();
      primaryPrecision = computePrecision(primary);
    }
  }

  @Override
  public void roundToInfinity() {
    // noop
  }

  /**
   * Multiply the internal number by the specified multiplicand. This method forces the internal
   * representation into a BigDecimal. If you are multiplying by a power of 10, use {@link
   * #adjustMagnitude} instead.
   *
   * @param multiplicand The number to be passed to {@link BigDecimal#multiply}.
   */
  @Override
  public void multiplyBy(BigDecimal multiplicand) {
    convertToBigDecimal();
    fallback = fallback.multiply(multiplicand);
    if (fallback.compareTo(BigDecimal.ZERO) < 0) {
      setNegative(!isNegative());
      fallback = fallback.negate();
    }
  }

  @Override
  public void negate() {
    flags ^= NEGATIVE_FLAG;
  }

  /**
   * Divide the internal number by the specified quotient. This method forces the internal
   * representation into a BigDecimal. If you are dividing by a power of 10, use {@link
   * #adjustMagnitude} instead.
   *
   * @param divisor The number to be passed to {@link BigDecimal#divide}.
   * @param scale The scale of the final rounded number. More negative means more decimal places.
   * @param mathContext The math context to use if rounding is necessary.
   */
  @SuppressWarnings("unused")
  private void divideBy(BigDecimal divisor, int scale, MathContext mathContext) {
    convertToBigDecimal();
    // Negate the scale because BigDecimal's scale is defined as the inverse of our scale
    fallback = fallback.divide(divisor, -scale, mathContext.getRoundingMode());
    if (fallback.compareTo(BigDecimal.ZERO) < 0) {
      setNegative(!isNegative());
      fallback = fallback.negate();
    }
  }

  @Override
  public boolean isZeroish() {
    if (primary == -1) {
      return fallback.compareTo(BigDecimal.ZERO) == 0;
    } else {
      return primary == 0;
    }
  }

  /** @return The power of ten of the highest digit represented by this DecimalQuantity */
  @Override
  public int getMagnitude() throws ArithmeticException {
    int scale = (primary == -1) ? scaleBigDecimal(fallback) : primaryScale;
    int precision = (primary == -1) ? precisionBigDecimal(fallback) : primaryPrecision;
    if (precision == 0) {
      throw new ArithmeticException("Magnitude is not well-defined for zero");
    } else {
      return scale + precision - 1;
    }
  }

  /**
   * Changes the magnitude of this DecimalQuantity. If the indices of the represented digits had been
   * previously specified, those indices are moved relative to the DecimalQuantity.
   *
   * <p>This method does NOT perform rounding.
   *
   * @param delta The number of powers of ten to shift (positive shifts to the left).
   */
  @Override
  public void adjustMagnitude(int delta) {
    if (primary == -1) {
      fallback = fallback.scaleByPowerOfTen(delta);
    } else {
      primaryScale = addOrMaxValue(primaryScale, delta);
    }
  }

  private static int addOrMaxValue(int a, int b) {
    // Check for overflow, and return min/max value if overflow occurs.
    if (b < 0 && a + b > a) {
      return Integer.MIN_VALUE;
    } else if (b > 0 && a + b < a) {
      return Integer.MAX_VALUE;
    }
    return a + b;
  }

  /** @return If the number represented by this DecimalQuantity is less than zero */
  @Override
  public boolean isNegative() {
    return (flags & NEGATIVE_FLAG) != 0;
  }

  @Override
  public Signum signum() {
      boolean isZero = (isZeroish() && !isInfinite());
      boolean isNeg = isNegative();
      if (isZero && isNeg) {
          return Signum.NEG_ZERO;
      } else if (isZero) {
          return Signum.POS_ZERO;
      } else if (isNeg) {
          return Signum.NEG;
      } else {
          return Signum.POS;
      }
  }

  private void setNegative(boolean isNegative) {
    flags = (flags & (~NEGATIVE_FLAG)) | (isNegative ? NEGATIVE_FLAG : 0);
  }

  @Override
  public boolean isInfinite() {
    return (flags & INFINITY_FLAG) != 0;
  }

  private void setInfinity(boolean isInfinity) {
    flags = (flags & (~INFINITY_FLAG)) | (isInfinity ? INFINITY_FLAG : 0);
  }

  @Override
  public boolean isNaN() {
    return (flags & NAN_FLAG) != 0;
  }

  private void setNaN(boolean isNaN) {
    flags = (flags & (~NAN_FLAG)) | (isNaN ? NAN_FLAG : 0);
  }

  /**
   * Returns a representation of this DecimalQuantity as a double, with possible loss of information.
   */
  @Override
  public double toDouble() {
    double result;
    if (primary == -1) {
      result = fallback.doubleValue();
    } else {
      // TODO: Make this more efficient
      result = primary;
      for (int i = 0; i < primaryScale; i++) {
        result *= 10.;
      }
      for (int i = 0; i > primaryScale; i--) {
        result /= 10.;
      }
    }
    return isNegative() ? -result : result;
  }

  @Override
  public BigDecimal toBigDecimal() {
    BigDecimal result;
    if (primary != -1) {
      result = new BigDecimal(primary).scaleByPowerOfTen(primaryScale);
    } else {
      result = fallback;
    }
    return isNegative() ? result.negate() : result;
  }

  @Override
  public StandardPlural getStandardPlural(PluralRules rules) {
    if (rules == null) {
      // Fail gracefully if the user didn't provide a PluralRules
      return StandardPlural.OTHER;
    } else {
      // TODO: Avoid converting to a double for the sake of PluralRules
      String ruleString = rules.select(toDouble());
      return StandardPlural.orOtherFromString(ruleString);
    }
  }

  @Override
  public double getPluralOperand(Operand operand) {
    // TODO: This is a temporary hack.
    return new PluralRules.FixedDecimal(toDouble()).getPluralOperand(operand);
  }

  public boolean hasNextFraction() {
    if (rReqPos < 0) {
      // We are in the required zone.
      return true;
    } else if (rOptPos >= 0) {
      // We are in the forbidden zone.
      return false;
    } else {
      // We are in the optional zone.
      if (primary == -1) {
        return fallback.remainder(BigDecimal.ONE).compareTo(BigDecimal.ZERO) > 0;
      } else {
        if (primaryScale <= -19) {
          // The number is a fraction so small that it consists of only fraction digits.
          return primary > 0;
        } else if (primaryScale < 0) {
          // Check if we have a fraction part.
          long factor = POWERS_OF_TEN[0 - primaryScale];
          return ((primary % factor) != 0);
        } else {
          // The lowest digit in the long has magnitude greater than -1.
          return false;
        }
      }
    }
  }

  public byte nextFraction() {
    byte returnValue;
    if (primary == -1) {
      BigDecimal temp = fallback.multiply(BigDecimal.TEN);
      returnValue = temp.setScale(0, RoundingMode.FLOOR).remainder(BigDecimal.TEN).byteValue();
      fallback = fallback.setScale(0, RoundingMode.FLOOR).add(temp.remainder(BigDecimal.ONE));
    } else {
      if (primaryScale <= -20) {
        // The number is a fraction so small that it has no first fraction digit.
        primaryScale += 1;
        returnValue = 0;
      } else if (primaryScale < 0) {
        // Extract the fraction digit out of the middle of the long.
        long factor = POWERS_OF_TEN[0 - primaryScale - 1];
        long temp1 = primary / factor;
        long temp2 = primary % factor;
        returnValue = (byte) (temp1 % 10); // not necessarily nonzero
        primary = ((temp1 / 10) * factor) + temp2;
        primaryScale += 1;
        if (temp1 != 0) {
          primaryPrecision -= 1;
        }
      } else {
        // The lowest digit in the long has magnitude greater than -1.
        returnValue = 0;
      }
    }

    // Update digit brackets
    if (lOptPos < 0) {
      lOptPos += 1;
    }
    if (lReqPos < 0) {
      lReqPos += 1;
    }
    if (rReqPos < 0) {
      rReqPos += 1;
    }
    if (rOptPos < 0) {
      rOptPos += 1;
    }

    assert returnValue >= 0;
    return returnValue;
  }

  public boolean hasNextInteger() {
    if (lReqPos > 0) {
      // We are in the required zone.
      return true;
    } else if (lOptPos <= 0) {
      // We are in the forbidden zone.
      return false;
    } else {
      // We are in the optional zone.
      if (primary == -1) {
        return fallback.setScale(0, RoundingMode.FLOOR).compareTo(BigDecimal.ZERO) > 0;
      } else {
        if (primaryScale < -18) {
          // The number is a fraction so small that it has no integer part.
          return false;
        } else if (primaryScale < 0) {
          // Check if we have an integer part.
          long factor = POWERS_OF_TEN[0 - primaryScale];
          return ((primary % factor) != primary); // equivalent: ((primary / 10) != 0)
        } else {
          // The lowest digit in the long has magnitude of at least 0.
          return primary != 0;
        }
      }
    }
  }

  private int integerCount() {
    int digitsRemaining;
    if (primary == -1) {
      digitsRemaining = precisionBigDecimal(fallback) + scaleBigDecimal(fallback);
    } else {
      digitsRemaining = primaryPrecision + primaryScale;
    }
    return Math.min(Math.max(digitsRemaining, lReqPos), lOptPos);
  }

  private int fractionCount() {
    // TODO: This is temporary.
    DecimalQuantity_SimpleStorage copy = new DecimalQuantity_SimpleStorage(this);
    int fractionCount = 0;
    while (copy.hasNextFraction()) {
      copy.nextFraction();
      fractionCount++;
    }
    return fractionCount;
  }

  @Override
  public int getUpperDisplayMagnitude() {
    return integerCount() - 1;
  }

  @Override
  public int getLowerDisplayMagnitude() {
    return -fractionCount();
  }

  //  @Override
  //  public byte getIntegerDigit(int index) {
  //    return getDigitPos(index);
  //  }
  //
  //  @Override
  //  public byte getFractionDigit(int index) {
  //    return getDigitPos(-index - 1);
  //  }

  @Override
  public byte getDigit(int magnitude) {
    // TODO: This is temporary.
    DecimalQuantity_SimpleStorage copy = new DecimalQuantity_SimpleStorage(this);
    if (magnitude < 0) {
      for (int p = -1; p > magnitude; p--) {
        copy.nextFraction();
      }
      return copy.nextFraction();
    } else {
      for (int p = 0; p < magnitude; p++) {
        copy.nextInteger();
      }
      return copy.nextInteger();
    }
  }

  public byte nextInteger() {
    byte returnValue;
    if (primary == -1) {
      returnValue = fallback.setScale(0, RoundingMode.FLOOR).remainder(BigDecimal.TEN).byteValue();
      BigDecimal temp = fallback.divide(BigDecimal.TEN).setScale(0, RoundingMode.FLOOR);
      fallback = fallback.remainder(BigDecimal.ONE).add(temp);
    } else {
      if (primaryScale < -18) {
        // The number is a fraction so small that it has no integer part.
        returnValue = 0;
      } else if (primaryScale < 0) {
        // Extract the integer digit out of the middle of the long. In many ways, this is the heart
        // of the digit iterator algorithm.
        long factor = POWERS_OF_TEN[0 - primaryScale];
        if ((primary % factor) != primary) { // equivalent: ((primary / 10) != 0)
          returnValue = (byte) ((primary / factor) % 10);
          long temp = (primary / 10);
          primary = temp - (temp % factor) + (primary % factor);
          primaryPrecision -= 1;
        } else {
          returnValue = 0;
        }
      } else if (primaryScale == 0) {
        // Fast-path for primaryScale == 0 (otherwise equivalent to previous step).
        if (primary != 0) {
          returnValue = (byte) (primary % 10);
          primary /= 10;
          primaryPrecision -= 1;
        } else {
          returnValue = 0;
        }
      } else {
        // The lowest digit in the long has magnitude greater than 0.
        primaryScale -= 1;
        returnValue = 0;
      }
    }

    // Update digit brackets
    if (lOptPos > 0) {
      lOptPos -= 1;
    }
    if (lReqPos > 0) {
      lReqPos -= 1;
    }
    if (rReqPos > 0) {
      rReqPos -= 1;
    }
    if (rOptPos > 0) {
      rOptPos -= 1;
    }

    assert returnValue >= 0;
    return returnValue;
  }

  /**
   * Helper method to compute the precision of a BigDecimal by our definition of precision, which is
   * that the number zero gets precision zero.
   *
   * @param decimal The BigDecimal whose precision to compute.
   * @return The precision by our definition.
   */
  private static int precisionBigDecimal(BigDecimal decimal) {
    if (decimal.compareTo(BigDecimal.ZERO) == 0) {
      return 0;
    } else {
      return decimal.precision();
    }
  }

  /**
   * Helper method to compute the scale of a BigDecimal by our definition of scale, which is that
   * deeper fractions result in negative scales as opposed to positive scales.
   *
   * @param decimal The BigDecimal whose scale to compute.
   * @return The scale by our definition.
   */
  private static int scaleBigDecimal(BigDecimal decimal) {
    return -decimal.scale();
  }

  @Override
  public String toString() {
    StringBuilder sb = new StringBuilder();
    sb.append("<DecimalQuantity1 ");
    if (primary == -1) {
      sb.append(lOptPos > 1000 ? "max" : lOptPos);
      sb.append(":");
      sb.append(lReqPos);
      sb.append(":");
      sb.append(rReqPos);
      sb.append(":");
      sb.append(rOptPos < -1000 ? "min" : rOptPos);
      sb.append(" ");
      sb.append(fallback.toString());
    } else {
      String digits = Long.toString(primary);
      int iDec = digits.length() + primaryScale;
      int iLP = iDec - toRange(lOptPos, -1000, 1000);
      int iLB = iDec - toRange(lReqPos, -1000, 1000);
      int iRB = iDec - toRange(rReqPos, -1000, 1000);
      int iRP = iDec - toRange(rOptPos, -1000, 1000);
      iDec = Math.max(Math.min(iDec, digits.length() + 1), -1);
      iLP = Math.max(Math.min(iLP, digits.length() + 1), -1);
      iLB = Math.max(Math.min(iLB, digits.length() + 1), -1);
      iRB = Math.max(Math.min(iRB, digits.length() + 1), -1);
      iRP = Math.max(Math.min(iRP, digits.length() + 1), -1);

      for (int i = -1; i <= digits.length() + 1; i++) {
        if (i == iLP) sb.append('(');
        if (i == iLB) sb.append('[');
        if (i == iDec) sb.append('.');
        if (i == iRB) sb.append(']');
        if (i == iRP) sb.append(')');
        if (i >= 0 && i < digits.length()) sb.append(digits.charAt(i));
        else sb.append('\u00A0');
      }
    }
    sb.append(">");
    return sb.toString();
  }

  @Override
  public String toPlainString() {
      // NOTE: This logic is duplicated between here and DecimalQuantity_AbstractBCD.
      StringBuilder sb = new StringBuilder();
      if (isNegative()) {
          sb.append('-');
      }
      int upper = getUpperDisplayMagnitude();
      int lower = getLowerDisplayMagnitude();
      int p = upper;
      for (; p >= 0; p--) {
          sb.append((char) ('0' + getDigit(p)));
      }
      if (lower < 0) {
          sb.append('.');
      }
      for(; p >= lower; p--) {
          sb.append((char) ('0' + getDigit(p)));
      }
      return sb.toString();
  }

  private static int toRange(int i, int lo, int hi) {
    if (i < lo) {
      return lo;
    } else if (i > hi) {
      return hi;
    } else {
      return i;
    }
  }

  @Override
  public void populateUFieldPosition(FieldPosition fp) {
    if (fp instanceof UFieldPosition) {
      ((UFieldPosition) fp)
          .setFractionDigits((int) getPluralOperand(Operand.v), (long) getPluralOperand(Operand.f));
    }
  }

  @Override
  public int getExponent() {
    return origPrimaryScale;
  }

  @Override
  public void adjustExponent(int delta) {
      origPrimaryScale = origPrimaryScale + delta;
  }

  @Override
  public boolean isHasIntegerValue() {
    return scaleBigDecimal(toBigDecimal()) >= 0;
  }
}
