// © 2017 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
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 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;
  }
}
