// Copyright (c) 2012, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of intl;
/**
 * Provides the ability to format a number in a locale-specific way. The
 * format is specified as a pattern using a subset of the ICU formatting
 * patterns.
 *
 * - `0` A single digit
 * - `#` A single digit, omitted if the value is zero
 * - `.` Decimal separator
 * - `-` Minus sign
 * - `,` Grouping separator
 * - `E` Separates mantissa and expontent
 * - `+` - Before an exponent, indicates it should be prefixed with a plus sign.
 * - `%` - In prefix or suffix, multiply by 100 and show as percentage
 * - `‰ (\u2030)` In prefix or suffix, multiply by 1000 and show as per mille
 * - `¤ (\u00A4)` Currency sign, replaced by currency name
 * - `'` Used to quote special characters
 * - `;` Used to separate the positive and negative patterns if both are present
 *
 * For example,
 *       var f = new NumberFormat("###.0#", "en_US");
 *       print(f.format(12.345));
 *       ==> 12.34
 * If the locale is not specified, it will default to the current locale. If
 * the format is not specified it will print in a basic format with at least
 * one integer digit and three fraction digits.
 *
 * There are also standard patterns available via the special constructors. e.g.
 *       var symbols = new NumberFormat.percentFormat("ar");
 * There are four such constructors: decimalFormat, percentFormat,
 * scientificFormat and currencyFormat. However, at the moment,
 * scientificFormat prints only as equivalent to "#E0" and does not take
 * into account significant digits. currencyFormat will always use the name
 * of the currency rather than the symbol.
 */
class NumberFormat {
  /** Variables to determine how number printing behaves. */
  // TODO(alanknight): If these remain as variables and are set based on the
  // pattern, can we make them final?
  String _negativePrefix = '-';
  String _positivePrefix = '';
  String _negativeSuffix = '';
  String _positiveSuffix = '';
  /**
   * How many numbers in a group when using punctuation to group digits in
   * large numbers. e.g. in en_US: "1,000,000" has a grouping size of 3 digits
   * between commas.
   */
  int _groupingSize = 3;
  bool _decimalSeparatorAlwaysShown = false;
  bool _useSignForPositiveExponent = false;
  bool _useExponentialNotation = false;

  int maximumIntegerDigits = 40;
  int minimumIntegerDigits = 1;
  int maximumFractionDigits = 3;
  int minimumFractionDigits = 0;
  int minimumExponentDigits = 0;

  int _multiplier = 1;

  /**
   * Stores the pattern used to create this format. This isn't used, but
   * is helpful in debugging.
   */
  String _pattern;

  /** The locale in which we print numbers. */
  final String _locale;

  /** Caches the symbols used for our locale. */
  NumberSymbols _symbols;

  /**
   * Transient internal state in which to build up the result of the format
   * operation. We can have this be just an instance variable because Dart is
   * single-threaded and unless we do an asynchronous operation in the process
   * of formatting then there will only ever be one number being formatted
   * at a time. In languages with threads we'd need to pass this on the stack.
   */
  StringBuffer _buffer;

  /**
   * Create a number format that prints using [newPattern] as it applies in
   * [locale].
   */
  factory NumberFormat([String newPattern, String locale]) {
    return new NumberFormat._forPattern(locale, (x) => newPattern);
  }

  /** Create a number format that prints as DECIMAL_PATTERN. */
  NumberFormat.decimalPattern([String locale]) :
      this._forPattern(locale, (x) => x.DECIMAL_PATTERN);

  /** Create a number format that prints as PERCENT_PATTERN. */
  NumberFormat.percentPattern([String locale]) :
    this._forPattern(locale, (x) => x.PERCENT_PATTERN);

  /** Create a number format that prints as SCIENTIFIC_PATTERN. */
  NumberFormat.scientificPattern([String locale]) :
    this._forPattern(locale, (x) => x.SCIENTIFIC_PATTERN);

  /** Create a number format that prints as CURRENCY_PATTERN. */
  NumberFormat.currencyPattern([String locale]) :
    this._forPattern(locale, (x) => x.CURRENCY_PATTERN);

  /**
   * Create a number format that prints in a pattern we get from
   * the [getPattern] function using the locale [locale].
   */
  NumberFormat._forPattern(String locale, Function getPattern) :
      _locale = Intl.verifiedLocale(locale, localeExists) {
    _symbols = numberFormatSymbols[_locale];
    _setPattern(getPattern(_symbols));
  }

  /**
   * Return the locale code in which we operate, e.g. 'en_US' or 'pt'.
   */
  String get locale => _locale;

  /**
   * Return true if the locale exists, or if it is null. The null case
   * is interpreted to mean that we use the default locale.
   */
  static bool localeExists(localeName) {
    if (localeName == null) return false;
    return numberFormatSymbols.containsKey(localeName);
  }

  /**
   * Return the symbols which are used in our locale. Cache them to avoid
   * repeated lookup.
   */
  NumberSymbols get symbols {
    return _symbols;
  }

  /**
   * Format [number] according to our pattern and return the formatted string.
   */
  String format(num number) {
    // TODO(alanknight): Do we have to do anything for printing numbers bidi?
    // Or are they always printed left to right?
    if (number.isNaN) return symbols.NAN;
    if (number.isInfinite) return "${_signPrefix(number)}${symbols.INFINITY}";

    _newBuffer();
    _add(_signPrefix(number));
    _formatNumber(number.abs() * _multiplier);
    _add(_signSuffix(number));

    var result = _buffer.toString();
    _buffer = null;
    return result;
  }

  /**
   * Format the main part of the number in the form dictated by the pattern.
   */
  void _formatNumber(num number) {
    if (_useExponentialNotation) {
      _formatExponential(number);
    } else {
      _formatFixed(number);
    }
  }

  /** Format the number in exponential notation. */
  void _formatExponential(num number) {
    if (number == 0.0) {
      _formatFixed(number);
      _formatExponent(0);
      return;
    }

    var exponent = (log(number) / log(10)).floor();
    var mantissa = number / pow(10.0, exponent);

    var minIntDigits = minimumIntegerDigits;
    if (maximumIntegerDigits > 1 &&
        maximumIntegerDigits > minimumIntegerDigits) {
      // A repeating range is defined; adjust to it as follows.
      // If repeat == 3, we have 6,5,4=>3; 3,2,1=>0; 0,-1,-2=>-3;
      // -3,-4,-5=>-6, etc. This takes into account that the
      // exponent we have here is off by one from what we expect;
      // it is for the format 0.MMMMMx10^n.
      while ((exponent % maximumIntegerDigits) != 0) {
        mantissa *= 10;
        exponent--;
      }
      minIntDigits = 1;
    } else {
      // No repeating range is defined, use minimum integer digits.
      if (minimumIntegerDigits < 1) {
        exponent++;
        mantissa /= 10;
      } else {
        exponent -= minimumIntegerDigits - 1;
        mantissa *= pow(10, minimumIntegerDigits - 1);
      }
    }
    _formatFixed(mantissa);
    _formatExponent(exponent);
  }

  /**
   * Format the exponent portion, e.g. in "1.3e-5" the "e-5".
   */
  void _formatExponent(num exponent) {
    _add(symbols.EXP_SYMBOL);
    if (exponent < 0) {
      exponent = -exponent;
      _add(symbols.MINUS_SIGN);
    } else if (_useSignForPositiveExponent) {
      _add(symbols.PLUS_SIGN);
    }
    _pad(minimumExponentDigits, exponent.toString());
  }

  /** Used to test if we have exceeded Javascript integer limits. */
  final _maxInt = pow(2, 52);

  /**
   * Format the basic number portion, inluding the fractional digits.
   */
  void _formatFixed(num number) {
    // Very fussy math to get integer and fractional parts.
    var power = pow(10, maximumFractionDigits);
    var shiftedNumber = (number * power);
    // We must not roundToDouble() an int or it will lose precision. We must not
    // round() a large double or it will take its loss of precision and
    // preserve it in an int, which we will then print to the right
    // of the decimal place. Therefore, only roundToDouble if we are already
    // a double.
    if (shiftedNumber is double) {
      shiftedNumber = shiftedNumber.roundToDouble();
    }
    var intValue, fracValue;
    if (shiftedNumber.isInfinite) {
      intValue = number.toInt();
      fracValue = 0;
    } else {
      intValue = shiftedNumber.round() ~/ power;
      fracValue = (shiftedNumber - intValue * power).floor();
    }
    var fractionPresent = minimumFractionDigits > 0 || fracValue > 0;

    // If the int part is larger than 2^52 and we're on Javascript (so it's
    // really a float) it will lose precision, so pad out the rest of it
    // with zeros. Check for Javascript by seeing if an integer is double.
    var paddingDigits = new StringBuffer();
    if (1 is double && intValue > _maxInt) {
        var howManyDigitsTooBig = (log(intValue) / LN10).ceil() - 16;
        var divisor = pow(10, howManyDigitsTooBig).round();
        for (var each in new List(howManyDigitsTooBig.toInt())) {
          paddingDigits.write(symbols.ZERO_DIGIT);
        }
        intValue = (intValue / divisor).truncate();
    }
    var integerDigits = "${intValue}${paddingDigits}".codeUnits;
    var digitLength = integerDigits.length;

    if (_hasPrintableIntegerPart(intValue)) {
      _pad(minimumIntegerDigits - digitLength);
      for (var i = 0; i < digitLength; i++) {
        _addDigit(integerDigits[i]);
        _group(digitLength, i);
      }
    } else if (!fractionPresent) {
      // If neither fraction nor integer part exists, just print zero.
      _addZero();
    }

    _decimalSeparator(fractionPresent);
    _formatFractionPart((fracValue + power).toString());
  }

  /**
   * Format the part after the decimal place in a fixed point number.
   */
  void _formatFractionPart(String fractionPart) {
    var fractionCodes = fractionPart.codeUnits;
    var fractionLength = fractionPart.length;
    while(fractionCodes[fractionLength - 1] == _zero &&
           fractionLength > minimumFractionDigits + 1) {
      fractionLength--;
    }
    for (var i = 1; i < fractionLength; i++) {
      _addDigit(fractionCodes[i]);
    }
  }

  /** Print the decimal separator if appropriate. */
  void _decimalSeparator(bool fractionPresent) {
    if (_decimalSeparatorAlwaysShown || fractionPresent) {
      _add(symbols.DECIMAL_SEP);
    }
  }

  /**
   * Return true if we have a main integer part which is printable, either
   * because we have digits left of the decimal point, or because there are
   * a minimum number of printable digits greater than 1.
   */
  bool _hasPrintableIntegerPart(int intValue) {
    return intValue > 0 || minimumIntegerDigits > 0;
  }

  /**
   * Create a new empty buffer. See comment on [_buffer] variable for why
   * we have it as an instance variable rather than passing it on the stack.
   */
  void _newBuffer() { _buffer = new StringBuffer(); }

  /** A group of methods that provide support for writing digits and other
   * required characters into [_buffer] easily.
   */
  void _add(String x) { _buffer.write(x);}
  void _addCharCode(int x) { _buffer.writeCharCode(x); }
  void _addZero() { _buffer.write(symbols.ZERO_DIGIT); }
  void _addDigit(int x) { _buffer.writeCharCode(_localeZero + x - _zero); }

  /** Print padding up to [numberOfDigits] above what's included in [basic]. */
  void _pad(int numberOfDigits, [String basic = '']) {
    for (var i = 0; i < numberOfDigits - basic.length; i++) {
      _add(symbols.ZERO_DIGIT);
    }
    for (var x in basic.codeUnits) {
      _addDigit(x);
    }
  }

  /**
   * We are printing the digits of the number from left to right. We may need
   * to print a thousands separator or other grouping character as appropriate
   * to the locale. So we find how many places we are from the end of the number
   * by subtracting our current [position] from the [totalLength] and print
   * the separator character every [_groupingSize] digits.
   */
  void _group(int totalLength, int position) {
    var distanceFromEnd = totalLength - position;
    if (distanceFromEnd <= 1 || _groupingSize <= 0) return;
    if (distanceFromEnd % _groupingSize == 1) {
      _add(symbols.GROUP_SEP);
    }
  }

  /** Returns the code point for the character '0'. */
  final _zero = '0'.codeUnits.first;

  /** Returns the code point for the locale's zero digit. */
  // Note that there is a slight risk of a locale's zero digit not fitting
  // into a single code unit, but it seems very unlikely, and if it did,
  // there's a pretty good chance that our assumptions about being able to do
  // arithmetic on it would also be invalid.
  get _localeZero => symbols.ZERO_DIGIT.codeUnits.first;

  /**
   * Returns the prefix for [x] based on whether it's positive or negative.
   * In en_US this would be '' and '-' respectively.
   */
  String _signPrefix(num x) {
    return x.isNegative ? _negativePrefix : _positivePrefix;
  }

  /**
   * Returns the suffix for [x] based on wether it's positive or negative.
   * In en_US there are no suffixes for positive or negative.
   */
  String _signSuffix(num x) {
    return x.isNegative ? _negativeSuffix : _positiveSuffix;
  }

  void _setPattern(String newPattern) {
    if (newPattern == null) return;
    // Make spaces non-breaking
    _pattern = newPattern.replaceAll(' ', '\u00a0');
    var parser = new _NumberFormatParser(this, newPattern);
    parser.parse();
  }

  String toString() => "NumberFormat($_locale, $_pattern)";
}

/**
 * Private class that parses the numeric formatting pattern and sets the
 * variables in [format] to appropriate values. Instances of this are
 * transient and store parsing state in instance variables, so can only be used
 * to parse a single pattern.
 */
class _NumberFormatParser {

  /**
   * The special characters in the pattern language. All others are treated
   * as literals.
   */
  static const _PATTERN_SEPARATOR = ';';
  static const _QUOTE = "'";
  static const _PATTERN_DIGIT = '#';
  static const _PATTERN_ZERO_DIGIT = '0';
  static const _PATTERN_GROUPING_SEPARATOR = ',';
  static const _PATTERN_DECIMAL_SEPARATOR = '.';
  static const _PATTERN_CURRENCY_SIGN = '\u00A4';
  static const _PATTERN_PER_MILLE = '\u2030';
  static const _PATTERN_PERCENT = '%';
  static const _PATTERN_EXPONENT = 'E';
  static const _PATTERN_PLUS = '+';

  /** The format whose state we are setting. */
  final NumberFormat format;

  /** The pattern we are parsing. */
  final _StringIterator pattern;

  /**
   * Create a new [_NumberFormatParser] for a particular [NumberFormat] and
   * [input] pattern.
   */
  _NumberFormatParser(this.format, input) : pattern = _iterator(input) {
    pattern.moveNext();
  }

  /** The [NumberSymbols] for the locale in which our [format] prints. */
  NumberSymbols get symbols => format.symbols;

  /** Parse the input pattern and set the values. */
  void parse() {
    format._positivePrefix = _parseAffix();
    var trunk = _parseTrunk();
    format._positiveSuffix = _parseAffix();
    // If we have separate positive and negative patterns, now parse the
    // the negative version.
    if (pattern.current == _NumberFormatParser._PATTERN_SEPARATOR) {
      pattern.moveNext();
      format._negativePrefix = _parseAffix();
      // Skip over the negative trunk, verifying that it's identical to the
      // positive trunk.
      for (var each in _iterable(trunk)) {
        if (pattern.current != each && pattern.current != null) {
          throw new FormatException(
              "Positive and negative trunks must be the same");
        }
        pattern.moveNext();
      }
      format._negativeSuffix = _parseAffix();
    } else {
      // If no negative affix is specified, they share the same positive affix.
      format._negativePrefix = format._positivePrefix + format._negativePrefix;
      format._negativeSuffix = format._negativeSuffix + format._positiveSuffix;
    }
  }

  /** Variable used in parsing prefixes and suffixes to keep track of
   * whether or not we are in a quoted region. */
  bool inQuote = false;

  /**
   * Parse a prefix or suffix and return the prefix/suffix string. Note that
   * this also may modify the state of [format].
   */
  String _parseAffix() {
    var affix = new StringBuffer();
    inQuote = false;
    var loop = true;
    while (loop) {
      loop = parseCharacterAffix(affix) && pattern.moveNext();
    }
    return affix.toString();
  }

  /**
   * Parse an individual character as part of a prefix or suffix.  Return true
   * if we should continue to look for more affix characters, and false if
   * we have reached the end.
   */
  bool parseCharacterAffix(StringBuffer affix) {
    var ch = pattern.current;
    if (ch == null) return false;
    if (ch == _QUOTE) {
      var nextChar = pattern.peek;
      if (nextChar == _QUOTE) {
        pattern.moveNext();
        affix.write(_QUOTE); // 'don''t'
      } else {
        inQuote = !inQuote;
      }
      return true;
    }

    if (inQuote) {
      affix.write(ch);
    } else {
      switch (ch) {
        case _PATTERN_DIGIT:
        case _PATTERN_ZERO_DIGIT:
        case _PATTERN_GROUPING_SEPARATOR:
        case _PATTERN_DECIMAL_SEPARATOR:
        case _PATTERN_SEPARATOR:
          return false;
        case _PATTERN_CURRENCY_SIGN:
          // TODO(alanknight): Handle the local/global/portable currency signs
          affix.write(symbols.DEF_CURRENCY_CODE);
          break;
        case _PATTERN_PERCENT:
          if (format._multiplier != 1) {
            throw new FormatException('Too many percent/permill');
          }
          format._multiplier = 100;
          affix.write(symbols.PERCENT);
          break;
        case _PATTERN_PER_MILLE:
          if (format._multiplier != 1) {
            throw new FormatException('Too many percent/permill');
          }
          format._multiplier = 1000;
          affix.write(symbols.PERMILL);
          break;
        default:
          affix.write(ch);
      }
    }
    return true;
  }

  /** Variables used in [_parseTrunk] and [parseTrunkCharacter]. */
  var decimalPos;
  var digitLeftCount;
  var zeroDigitCount;
  var digitRightCount;
  var groupingCount;
  var trunk;

  /**
   * Parse the "trunk" portion of the pattern, the piece that doesn't include
   * positive or negative prefixes or suffixes.
   */
  String _parseTrunk() {
    decimalPos = -1;
    digitLeftCount = 0;
    zeroDigitCount = 0;
    digitRightCount = 0;
    groupingCount = -1;

    var loop = true;
    trunk = new StringBuffer();
    while (pattern.current != null && loop) {
      loop = parseTrunkCharacter();
    }

    if (zeroDigitCount == 0 && digitLeftCount > 0 && decimalPos >= 0) {
      // Handle '###.###' and '###.' and '.###'
      var n = decimalPos;
      if (n == 0) { // Handle '.###'
        n++;
      }
      digitRightCount = digitLeftCount - n;
      digitLeftCount = n - 1;
      zeroDigitCount = 1;
    }

    // Do syntax checking on the digits.
    if (decimalPos < 0 && digitRightCount > 0 ||
        decimalPos >= 0 && (decimalPos < digitLeftCount ||
            decimalPos > digitLeftCount + zeroDigitCount) ||
            groupingCount == 0) {
      throw new FormatException('Malformed pattern "${pattern.input}"');
    }
    var totalDigits = digitLeftCount + zeroDigitCount + digitRightCount;

    format.maximumFractionDigits =
        decimalPos >= 0 ? totalDigits - decimalPos : 0;
    if (decimalPos >= 0) {
      format.minimumFractionDigits =
          digitLeftCount + zeroDigitCount - decimalPos;
      if (format.minimumFractionDigits < 0) {
        format.minimumFractionDigits = 0;
      }
    }

    // The effectiveDecimalPos is the position the decimal is at or would be at
    // if there is no decimal. Note that if decimalPos<0, then digitTotalCount
    // == digitLeftCount + zeroDigitCount.
    var effectiveDecimalPos = decimalPos >= 0 ? decimalPos : totalDigits;
    format.minimumIntegerDigits = effectiveDecimalPos - digitLeftCount;
    if (format._useExponentialNotation) {
      format.maximumIntegerDigits =
          digitLeftCount + format.minimumIntegerDigits;

      // In exponential display, we need to at least show something.
      if (format.maximumFractionDigits == 0 &&
          format.minimumIntegerDigits == 0) {
        format.minimumIntegerDigits = 1;
      }
    }

    format._groupingSize = max(0, groupingCount);
    format._decimalSeparatorAlwaysShown = decimalPos == 0 ||
        decimalPos == totalDigits;

    return trunk.toString();
  }

  /**
   * Parse an individual character of the trunk. Return true if we should
   * continue to look for additional trunk characters or false if we have
   * reached the end.
   */
  bool parseTrunkCharacter() {
    var ch = pattern.current;
    switch (ch) {
      case _PATTERN_DIGIT:
        if (zeroDigitCount > 0) {
          digitRightCount++;
        } else {
          digitLeftCount++;
        }
        if (groupingCount >= 0 && decimalPos < 0) {
          groupingCount++;
        }
        break;
      case _PATTERN_ZERO_DIGIT:
        if (digitRightCount > 0) {
          throw new FormatException('Unexpected "0" in pattern "'
              + pattern.input + '"');
        }
        zeroDigitCount++;
        if (groupingCount >= 0 && decimalPos < 0) {
          groupingCount++;
        }
        break;
      case _PATTERN_GROUPING_SEPARATOR:
        groupingCount = 0;
        break;
      case _PATTERN_DECIMAL_SEPARATOR:
        if (decimalPos >= 0) {
          throw new FormatException(
              'Multiple decimal separators in pattern "$pattern"');
        }
        decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
        break;
      case _PATTERN_EXPONENT:
        trunk.write(ch);
        if (format._useExponentialNotation) {
          throw new FormatException(
              'Multiple exponential symbols in pattern "$pattern"');
        }
        format._useExponentialNotation = true;
        format.minimumExponentDigits = 0;

        // exponent pattern can have a optional '+'.
        pattern.moveNext();
        var nextChar = pattern.current;
        if (nextChar == _PATTERN_PLUS) {
          trunk.write(pattern.current);
          pattern.moveNext();
          format._useSignForPositiveExponent = true;
        }

        // Use lookahead to parse out the exponential part
        // of the pattern, then jump into phase 2.
        while (pattern.current == _PATTERN_ZERO_DIGIT) {
          trunk.write(pattern.current);
          pattern.moveNext();
          format.minimumExponentDigits++;
        }

        if ((digitLeftCount + zeroDigitCount) < 1 ||
            format.minimumExponentDigits < 1) {
          throw new FormatException(
              'Malformed exponential pattern "$pattern"');
        }
        return false;
      default:
        return false;
    }
    trunk.write(ch);
    pattern.moveNext();
    return true;
  }
}

/**
 * Returns an [Iterable] on the string as a list of substrings.
 */
Iterable _iterable(String s) => new _StringIterable(s);

/**
 * Return an iterator on the string as a list of substrings.
 */
Iterator _iterator(String s) => new _StringIterator(s);

// TODO(nweiz): remove this when issue 3780 is fixed.
/**
 * Provides an Iterable that wraps [_iterator] so it can be used in a `for`
 * loop.
 */
class _StringIterable extends Iterable<String> {
  final Iterator<String> iterator;

  _StringIterable(String s)
      : iterator = _iterator(s);
}

/**
 * Provides an iterator over a string as a list of substrings, and also
 * gives us a lookahead of one via the [peek] method.
 */
class _StringIterator implements Iterator<String> {
  String input;
  var index = -1;
  inBounds(i) => i >= 0 && i < input.length;
  _StringIterator(this.input);
  String get current => inBounds(index) ? input[index] : null;

  bool moveNext() => inBounds(++index);
  String get peek => inBounds(index + 1) ? input[index + 1] : null;
  Iterator<String> get iterator => this;
}