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

/**
 * A class for holding onto the data for a date so that it can be built
 * up incrementally.
 */
class _DateBuilder {
  // Default the date values to the EPOCH so that there's a valid date
  // in case the format doesn't set them.
  int year = 1970,
      month = 1,
      day = 1,
      hour = 0,
      minute = 0,
      second = 0,
      fractionalSecond = 0;
  bool pm = false;
  bool utc = false;

  // Functions that exist just to be closurized so we can pass them to a general
  // method.
  void setYear(x) { year = x; }
  void setMonth(x) { month = x; }
  void setDay(x) { day = x; }
  void setHour(x) { hour = x; }
  void setMinute(x) { minute = x; }
  void setSecond(x) { second = x; }
  void setFractionalSecond(x) { fractionalSecond = x; }

  get hour24 => pm ? hour + 12 : hour;

  /**
   * Verify that we correspond to a valid date. This will reject out of
   * range values, even if the DateTime constructor would accept them. An
   * invalid message will result in throwing a [FormatException].
   */
   verify(String s) {
     _verify(month, 1, 12, "month", s);
     _verify(hour24, 0, 23, "hour", s);
     _verify(minute, 0, 59, "minute", s);
     _verify(second, 0, 59, "second", s);
     _verify(fractionalSecond, 0, 999, "fractional second", s);
     // Verifying the day is tricky, because it depends on the month. Create
     // our resulting date and then verify that our values agree with it
     // as an additional verification. And since we're doing that, also
     // check the year, which we otherwise can't verify, and the hours,
     // which will catch cases like "14:00:00 PM".
     var date = asDate();
     _verify(hour24, date.hour, date.hour, "hour", s);
     _verify(day, date.day, date.day, "day", s);
     _verify(year, date.year, date.year, "year", s);
   }

   _verify(int value, int min, int max, String desc, String originalInput) {
     if (value < min || value > max) {
       throw new FormatException(
           "Error parsing $originalInput, invalid $desc value: $value");
     }
   }

  /**
   * Return a date built using our values. If no date portion is set,
   * use the "Epoch" of January 1, 1970.
   */
  DateTime asDate({retry: true}) {
    // TODO(alanknight): Validate the date, especially for things which
    // can crash the VM, e.g. large month values.
    var result;
    if (utc) {
      result = new DateTime.utc(
          year,
          month,
          day,
          hour24,
          minute,
          second,
          fractionalSecond);
    } else {
      result = new DateTime(
          year,
          month,
          day,
          hour24,
          minute,
          second,
          fractionalSecond);
      // TODO(alanknight): Issue 15560 means non-UTC dates occasionally come
      // out in UTC. If that happens, retry once. This will always happen if
      // the local time zone is UTC, but that's ok.
      if (result.toUtc() == result) {
        result = asDate(retry: false);
      }
    }
    return result;
  }
}

/**
 * A simple and not particularly general stream class to make parsing
 * dates from strings simpler. It is general enough to operate on either
 * lists or strings.
 */
// TODO(alanknight): With the improvements to the collection libraries
// since this was written we might be able to get rid of it entirely
// in favor of e.g. aString.split('') giving us an iterable of one-character
// strings, or else make the implementation trivial. And consider renaming,
// as _Stream is now just confusing with the system Streams.
class _Stream {
  var contents;
  int index = 0;

  _Stream(this.contents);

  bool atEnd() => index >= contents.length;

  next() => contents[index++];

  /**
   * Return the next [howMany] items, or as many as there are remaining.
   * Advance the stream by that many positions.
   */
  read([int howMany = 1]) {
    var result = peek(howMany);
    index += howMany;
    return result;
  }

  /**
   * Does the input start with the given string, if we start from the
   * current position.
   */
  bool startsWith(String pattern) {
    if (contents is String) return contents.startsWith(pattern, index);
    return pattern == peek(pattern.length);
  }

  /**
   * Return the next [howMany] items, or as many as there are remaining.
   * Does not modify the stream position.
   */
  peek([int howMany = 1]) {
    var result;
    if (contents is String) {
      result = contents.substring(
          index,
          min(index + howMany, contents.length));
    } else {
      // Assume List
      result = contents.sublist(index, index + howMany);
    }
    return result;
  }

  /** Return the remaining contents of the stream */
  rest() => peek(contents.length - index);

  /**
   * Find the index of the first element for which [f] returns true.
   * Advances the stream to that position.
   */
  int findIndex(Function f) {
    while (!atEnd()) {
      if (f(next())) return index - 1;
    }
    return null;
  }

  /**
   * Find the indexes of all the elements for which [f] returns true.
   * Leaves the stream positioned at the end.
   */
  List findIndexes(Function f) {
    var results = [];
    while (!atEnd()) {
      if (f(next())) results.add(index - 1);
    }
    return results;
  }

  /**
   * Assuming that the contents are characters, read as many digits as we
   * can see and then return the corresponding integer. Advance the stream.
   */
  var digitMatcher = new RegExp(r'\d+');
  int nextInteger() {
    var string = digitMatcher.stringMatch(rest());
    if (string == null || string.isEmpty) return null;
    read(string.length);
    return int.parse(string);
  }
}
