// © 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 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;
  }
}
