// 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]) =>
      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 => _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) =>
      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) => 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) => 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;
    while (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) {
      if (pattern.peek == _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 '.###'
      // Handle '.###'
      var n = decimalPos == 0 ? 1 : decimalPos;
      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 IterableBase<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> {
  final String input;
  int 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;
}
