// Copyright (c) 2022, 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 "core_patch.dart";

// This file is identical to the VM `date_patch.dart` except for the
// implementation of `_getCurrentMicros` and the `_jsDateNow` import.
// TODO(askesc): Share this file with the VM when the patching mechanism gains
// support for patching an external member from a patch in a separate patch.

@pragma("wasm:import", "Date.now")
external double _jsDateNow();

// VM implementation of DateTime.
@patch
class DateTime {
  // Natives.
  // The natives have been moved up here to work around Issue 10401.
  static int _getCurrentMicros() =>
      (_jsDateNow() * Duration.microsecondsPerMillisecond).toInt();

  @pragma("wasm:import", "dart2wasm.getTimeZoneNameForSeconds")
  external static String _timeZoneNameForClampedSecondsRaw(
      double secondsSinceEpoch);

  static String _timeZoneNameForClampedSeconds(int secondsSinceEpoch) =>
      _timeZoneNameForClampedSecondsRaw(secondsSinceEpoch.toDouble());

  @pragma("wasm:import", "dart2wasm.getTimeZoneOffsetInSeconds")
  external static double _timeZoneOffsetInSecondsForClampedSeconds(
      double secondsSinceEpoch);

  static const _MICROSECOND_INDEX = 0;
  static const _MILLISECOND_INDEX = 1;
  static const _SECOND_INDEX = 2;
  static const _MINUTE_INDEX = 3;
  static const _HOUR_INDEX = 4;
  static const _DAY_INDEX = 5;
  static const _WEEKDAY_INDEX = 6;
  static const _MONTH_INDEX = 7;
  static const _YEAR_INDEX = 8;

  List<int>? __parts;

  @patch
  DateTime.fromMillisecondsSinceEpoch(int millisecondsSinceEpoch,
      {bool isUtc: false})
      : this._withValue(
            _validateMilliseconds(millisecondsSinceEpoch) *
                Duration.microsecondsPerMillisecond,
            isUtc: isUtc);

  @patch
  DateTime.fromMicrosecondsSinceEpoch(int microsecondsSinceEpoch,
      {bool isUtc: false})
      : this._withValue(microsecondsSinceEpoch, isUtc: isUtc);

  @patch
  DateTime._internal(int year, int month, int day, int hour, int minute,
      int second, int millisecond, int microsecond, bool isUtc)
      : this.isUtc = isUtc,
        this._value = _brokenDownDateToValue(year, month, day, hour, minute,
                second, millisecond, microsecond, isUtc) ??
            -1 {
    if (_value == -1) throw new ArgumentError();
    if (isUtc == null) throw new ArgumentError();
  }

  static int _validateMilliseconds(int millisecondsSinceEpoch) =>
      RangeError.checkValueInInterval(
          millisecondsSinceEpoch,
          -_maxMillisecondsSinceEpoch,
          _maxMillisecondsSinceEpoch,
          "millisecondsSinceEpoch");

  @patch
  DateTime._now()
      : isUtc = false,
        _value = _getCurrentMicros();

  @patch
  String get timeZoneName {
    if (isUtc) return "UTC";
    return _timeZoneName(microsecondsSinceEpoch);
  }

  @patch
  Duration get timeZoneOffset {
    if (isUtc) return new Duration();
    int offsetInSeconds = _timeZoneOffsetInSeconds(microsecondsSinceEpoch);
    return new Duration(seconds: offsetInSeconds);
  }

  @patch
  bool operator ==(dynamic other) =>
      other is DateTime &&
      _value == other.microsecondsSinceEpoch &&
      isUtc == other.isUtc;

  @patch
  bool isBefore(DateTime other) => _value < other.microsecondsSinceEpoch;

  @patch
  bool isAfter(DateTime other) => _value > other.microsecondsSinceEpoch;

  @patch
  bool isAtSameMomentAs(DateTime other) =>
      _value == other.microsecondsSinceEpoch;

  @patch
  int compareTo(DateTime other) =>
      _value.compareTo(other.microsecondsSinceEpoch);

  /** The first list contains the days until each month in non-leap years. The
    * second list contains the days in leap years. */
  static const List<List<int>> _DAYS_UNTIL_MONTH = const [
    const [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
    const [0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]
  ];

  static List<int> _computeUpperPart(int localMicros) {
    const int DAYS_IN_4_YEARS = 4 * 365 + 1;
    const int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1;
    const int DAYS_IN_400_YEARS = 4 * DAYS_IN_100_YEARS + 1;
    const int DAYS_1970_TO_2000 = 30 * 365 + 7;
    const int DAYS_OFFSET =
        1000 * DAYS_IN_400_YEARS + 5 * DAYS_IN_400_YEARS - DAYS_1970_TO_2000;
    const int YEARS_OFFSET = 400000;

    int resultYear = 0;
    int resultMonth = 0;
    int resultDay = 0;

    // Always round down.
    final int daysSince1970 =
        _flooredDivision(localMicros, Duration.microsecondsPerDay);
    int days = daysSince1970;
    days += DAYS_OFFSET;
    resultYear = 400 * (days ~/ DAYS_IN_400_YEARS) - YEARS_OFFSET;
    days = unsafeCast<int>(days.remainder(DAYS_IN_400_YEARS));
    days--;
    int yd1 = days ~/ DAYS_IN_100_YEARS;
    days = unsafeCast<int>(days.remainder(DAYS_IN_100_YEARS));
    resultYear += 100 * yd1;
    days++;
    int yd2 = days ~/ DAYS_IN_4_YEARS;
    days = unsafeCast<int>(days.remainder(DAYS_IN_4_YEARS));
    resultYear += 4 * yd2;
    days--;
    int yd3 = days ~/ 365;
    days = unsafeCast<int>(days.remainder(365));
    resultYear += yd3;

    bool isLeap = (yd1 == 0 || yd2 != 0) && yd3 == 0;
    if (isLeap) days++;

    List<int> daysUntilMonth = _DAYS_UNTIL_MONTH[isLeap ? 1 : 0];
    for (resultMonth = 12;
        daysUntilMonth[resultMonth - 1] > days;
        resultMonth--) {
      // Do nothing.
    }
    resultDay = days - daysUntilMonth[resultMonth - 1] + 1;

    int resultMicrosecond = localMicros % Duration.microsecondsPerMillisecond;
    int resultMillisecond =
        _flooredDivision(localMicros, Duration.microsecondsPerMillisecond) %
            Duration.millisecondsPerSecond;
    int resultSecond =
        _flooredDivision(localMicros, Duration.microsecondsPerSecond) %
            Duration.secondsPerMinute;

    int resultMinute =
        _flooredDivision(localMicros, Duration.microsecondsPerMinute);
    resultMinute %= Duration.minutesPerHour;

    int resultHour =
        _flooredDivision(localMicros, Duration.microsecondsPerHour);
    resultHour %= Duration.hoursPerDay;

    // In accordance with ISO 8601 a week
    // starts with Monday. Monday has the value 1 up to Sunday with 7.
    // 1970-1-1 was a Thursday.
    int resultWeekday = ((daysSince1970 + DateTime.thursday - DateTime.monday) %
            DateTime.daysPerWeek) +
        DateTime.monday;

    List<int> list = new List<int>.filled(_YEAR_INDEX + 1, 0);
    list[_MICROSECOND_INDEX] = resultMicrosecond;
    list[_MILLISECOND_INDEX] = resultMillisecond;
    list[_SECOND_INDEX] = resultSecond;
    list[_MINUTE_INDEX] = resultMinute;
    list[_HOUR_INDEX] = resultHour;
    list[_DAY_INDEX] = resultDay;
    list[_WEEKDAY_INDEX] = resultWeekday;
    list[_MONTH_INDEX] = resultMonth;
    list[_YEAR_INDEX] = resultYear;
    return list;
  }

  List<int> get _parts {
    return __parts ??= _computeUpperPart(_localDateInUtcMicros);
  }

  @patch
  DateTime add(Duration duration) {
    return new DateTime._withValue(_value + duration.inMicroseconds,
        isUtc: isUtc);
  }

  @patch
  DateTime subtract(Duration duration) {
    return new DateTime._withValue(_value - duration.inMicroseconds,
        isUtc: isUtc);
  }

  @patch
  Duration difference(DateTime other) {
    return new Duration(microseconds: _value - other.microsecondsSinceEpoch);
  }

  @patch
  int get millisecondsSinceEpoch =>
      _value ~/ Duration.microsecondsPerMillisecond;

  @patch
  int get microsecondsSinceEpoch => _value;

  @patch
  int get microsecond => _parts[_MICROSECOND_INDEX];

  @patch
  int get millisecond => _parts[_MILLISECOND_INDEX];

  @patch
  int get second => _parts[_SECOND_INDEX];

  @patch
  int get minute => _parts[_MINUTE_INDEX];

  @patch
  int get hour => _parts[_HOUR_INDEX];

  @patch
  int get day => _parts[_DAY_INDEX];

  @patch
  int get weekday => _parts[_WEEKDAY_INDEX];

  @patch
  int get month => _parts[_MONTH_INDEX];

  @patch
  int get year => _parts[_YEAR_INDEX];

  /**
   * Returns the amount of microseconds in UTC that represent the same values
   * as [this].
   *
   * Say `t` is the result of this function, then
   * * `this.year == new DateTime.fromMicrosecondsSinceEpoch(t, true).year`,
   * * `this.month == new DateTime.fromMicrosecondsSinceEpoch(t, true).month`,
   * * `this.day == new DateTime.fromMicrosecondsSinceEpoch(t, true).day`,
   * * `this.hour == new DateTime.fromMicrosecondsSinceEpoch(t, true).hour`,
   * * ...
   *
   * Daylight savings is computed as if the date was computed in [1970..2037].
   * If [this] lies outside this range then it is a year with similar
   * properties (leap year, weekdays) is used instead.
   */
  int get _localDateInUtcMicros {
    int micros = _value;
    if (isUtc) return micros;
    int offset =
        _timeZoneOffsetInSeconds(micros) * Duration.microsecondsPerSecond;
    return micros + offset;
  }

  static int _flooredDivision(int a, int b) {
    return (a - (a < 0 ? b - 1 : 0)) ~/ b;
  }

  // Returns the days since 1970 for the start of the given [year].
  // [year] may be before epoch.
  static int _dayFromYear(int year) {
    return 365 * (year - 1970) +
        _flooredDivision(year - 1969, 4) -
        _flooredDivision(year - 1901, 100) +
        _flooredDivision(year - 1601, 400);
  }

  static bool _isLeapYear(int y) {
    // (y % 16 == 0) matches multiples of 400, and is faster than % 400.
    return (y % 4 == 0) && ((y % 16 == 0) || (y % 100 != 0));
  }

  /// Converts the given broken down date to microseconds.
  @patch
  static int? _brokenDownDateToValue(int year, int month, int day, int hour,
      int minute, int second, int millisecond, int microsecond, bool isUtc) {
    // Simplify calculations by working with zero-based month.
    --month;
    // Deal with under and overflow.
    if (month >= 12) {
      year += month ~/ 12;
      month = month % 12;
    } else if (month < 0) {
      int realMonth = month % 12;
      year += (month - realMonth) ~/ 12;
      month = realMonth;
    }

    // First compute the seconds in UTC, independent of the [isUtc] flag. If
    // necessary we will add the time-zone offset later on.
    int days = day - 1;
    days += _DAYS_UNTIL_MONTH[_isLeapYear(year) ? 1 : 0][month];
    days += _dayFromYear(year);
    int microsecondsSinceEpoch = days * Duration.microsecondsPerDay +
        hour * Duration.microsecondsPerHour +
        minute * Duration.microsecondsPerMinute +
        second * Duration.microsecondsPerSecond +
        millisecond * Duration.microsecondsPerMillisecond +
        microsecond;

    if (!isUtc) {
      // Since [_timeZoneOffsetInSeconds] will crash if the input is far out of
      // the valid range we do a preliminary test that weeds out values that can
      // not become valid even with timezone adjustments.
      // The timezone adjustment is always less than a day, so adding a security
      // margin of one day should be enough.
      if (microsecondsSinceEpoch.abs() >
          _maxMillisecondsSinceEpoch * Duration.microsecondsPerMillisecond +
              Duration.microsecondsPerDay) {
        return null;
      }

      microsecondsSinceEpoch -= _toLocalTimeOffset(microsecondsSinceEpoch);
    }
    if (microsecondsSinceEpoch.abs() >
        _maxMillisecondsSinceEpoch * Duration.microsecondsPerMillisecond) {
      return null;
    }
    return microsecondsSinceEpoch;
  }

  static int _weekDay(y) {
    // 1/1/1970 was a Thursday.
    return (_dayFromYear(y) + 4) % 7;
  }

  /**
   * Returns a year in the range 2008-2035 matching
   * * leap year, and
   * * week day of first day.
   *
   * Leap seconds are ignored.
   * Adapted from V8's date implementation. See ECMA 262 - 15.9.1.9.
   */
  static int _equivalentYear(int year) {
    // Returns year y so that _weekDay(y) == _weekDay(year).
    // _weekDay returns the week day (in range 0 - 6).
    // 1/1/1956 was a Sunday (i.e. weekday 0). 1956 was a leap-year.
    // 1/1/1967 was a Sunday (i.e. weekday 0).
    // Without leap years a subsequent year has a week day + 1 (for example
    // 1/1/1968 was a Monday). With leap-years it jumps over one week day
    // (e.g. 1/1/1957 was a Tuesday).
    // After 12 years the weekdays have advanced by 12 days + 3 leap days =
    // 15 days. 15 % 7 = 1. So after 12 years the week day has always
    // (now independently of leap-years) advanced by one.
    // weekDay * 12 gives thus a year starting with the wanted weekDay.
    int recentYear = (_isLeapYear(year) ? 1956 : 1967) + (_weekDay(year) * 12);
    // Close to the year 2008 the calendar cycles every 4 * 7 years (4 for the
    // leap years, 7 for the weekdays).
    // Find the year in the range 2008..2037 that is equivalent mod 28.
    return 2008 + (recentYear - 2008) % 28;
  }

  /**
   * Returns the UTC year for the corresponding [secondsSinceEpoch].
   * It is relatively fast for values in the range 0 to year 2098.
   *
   * Code is adapted from V8.
   */
  static int _yearsFromSecondsSinceEpoch(int secondsSinceEpoch) {
    const int DAYS_IN_4_YEARS = 4 * 365 + 1;
    const int DAYS_IN_100_YEARS = 25 * DAYS_IN_4_YEARS - 1;
    const int DAYS_YEAR_2098 = DAYS_IN_100_YEARS + 6 * DAYS_IN_4_YEARS;

    int days = secondsSinceEpoch ~/ Duration.secondsPerDay;
    if (days > 0 && days < DAYS_YEAR_2098) {
      // According to V8 this fast case works for dates from 1970 to 2099.
      return 1970 + (4 * days + 2) ~/ DAYS_IN_4_YEARS;
    }
    int micros = secondsSinceEpoch * Duration.microsecondsPerSecond;
    return _computeUpperPart(micros)[_YEAR_INDEX];
  }

  /**
   * Returns a date in seconds that is equivalent to the given
   * date in microseconds [microsecondsSinceEpoch]. An equivalent
   * date has the same fields (`month`, `day`, etc.) as the given
   * date, but the `year` is in the range [1901..2038].
   *
   * * The time since the beginning of the year is the same.
   * * If the given date is in a leap year then the returned
   *   seconds are in a leap year, too.
   * * The week day of given date is the same as the one for the
   *   returned date.
   */
  static int _equivalentSeconds(int microsecondsSinceEpoch) {
    const int CUT_OFF_SECONDS = 0x7FFFFFFF;

    int secondsSinceEpoch = _flooredDivision(
        microsecondsSinceEpoch, Duration.microsecondsPerSecond);

    if (secondsSinceEpoch.abs() > CUT_OFF_SECONDS) {
      int year = _yearsFromSecondsSinceEpoch(secondsSinceEpoch);
      int days = _dayFromYear(year);
      int equivalentYear = _equivalentYear(year);
      int equivalentDays = _dayFromYear(equivalentYear);
      int diffDays = equivalentDays - days;
      secondsSinceEpoch += diffDays * Duration.secondsPerDay;
    }
    return secondsSinceEpoch;
  }

  static int _timeZoneOffsetInSeconds(int microsecondsSinceEpoch) {
    int equivalentSeconds = _equivalentSeconds(microsecondsSinceEpoch);
    return _timeZoneOffsetInSecondsForClampedSeconds(
            equivalentSeconds.toDouble())
        .toInt();
  }

  static String _timeZoneName(int microsecondsSinceEpoch) {
    int equivalentSeconds = _equivalentSeconds(microsecondsSinceEpoch);
    return _timeZoneNameForClampedSeconds(equivalentSeconds);
  }

  /// Finds the local time corresponding to a UTC date and time.
  ///
  /// The [microsecondsSinceEpoch] represents a particular
  /// calendar date and clock time in UTC.
  /// This methods returns a (usually different) point in time
  /// where the local time had the same calendar date and clock
  /// time (if such a time exists, otherwise it finds the "best"
  /// substitute).
  ///
  /// A valid result is a point in time `microsecondsSinceEpoch - offset`
  /// where the local time zone offset is `+offset`.
  ///
  /// In some cases there are two valid results, due to a time zone
  /// change setting the clock back (for example exiting from daylight
  /// saving time). In that case, we return the *earliest* valid result.
  ///
  /// In some cases there are no valid results, due to a time zone
  /// change setting the clock forward (for example entering daylight
  /// saving time). In that case, we return the time which would have
  /// been correct in the earlier time zone (so asking for 2:30 AM
  /// when clocks move directly from 2:00 to 3:00 will give the
  /// time that *would have been* 2:30 in the earlier time zone,
  /// which is now 3:30 in the local time zone).
  ///
  /// Returns the point in time as a number of microseconds since epoch.
  static int _toLocalTimeOffset(int microsecondsSinceEpoch) {
    // Argument is the UTC time corresponding to the desired
    // calendar date/wall time.
    // We now need to find an UTC time where the difference
    // from `microsecondsSinceEpoch` is the same as the
    // local time offset at that time. That is, we want to
    // find `adjustment` in microseconds such that:
    //
    //  _timeZoneOffsetInSeconds(microsecondsSinceEpoch - offset)
    //      * Duration.microsecondsPerSecond == offset
    //
    // Such an offset might not exist, if that wall time
    // is skipped when a time zone change moves the clock forwards.
    // In that case we pick a time after the switch which would be
    // correct in the previous time zone.
    // Also, there might be more than one solution if a time zone
    // change moves the clock backwards and the same wall clock
    // time occurs twice in the same day.
    // In that case we pick the one in the time zone prior to
    // the switch.

    // Start with the time zone at the current microseconds since
    // epoch. It's within one day of the real time we're looking for.

    int offset = _timeZoneOffsetInSeconds(microsecondsSinceEpoch) *
        Duration.microsecondsPerSecond;

    // If offset is 0 (we're right around the UTC+0, and)
    // we have found one solution.
    if (offset != 0) {
      // If not, try to find an actual solution in the time zone
      // we just discovered.
      int offset2 = _timeZoneOffsetInSeconds(microsecondsSinceEpoch - offset) *
          Duration.microsecondsPerSecond;
      if (offset2 != offset) {
        // Also not a solution. We have found a second time zone
        // within the same day. We assume that's all there are.
        // Try again with the new time zone.
        int offset3 =
            _timeZoneOffsetInSeconds(microsecondsSinceEpoch - offset2) *
                Duration.microsecondsPerSecond;
        // Either offset3 is a solution (equal to offset2),
        // or we have found two different time zones and no solution.
        // In the latter case we choose the lower offset (latter time).
        return (offset2 <= offset3 ? offset2 : offset3);
      }
      // We have found one solution and one time zone.
      offset = offset2;
    }
    // Try to see if there is an earlier time zone which also
    // has a solution.
    // Pretends time zone changes are always at most two hours.
    // (Double daylight saving happened, fx, in part of Canada in 1988).
    int offset4 = _timeZoneOffsetInSeconds(microsecondsSinceEpoch -
            offset -
            2 * Duration.microsecondsPerHour) *
        Duration.microsecondsPerSecond;
    if (offset4 > offset) {
      // The time zone at the earlier time had a greater
      // offset, so it's possible that the desired wall clock
      // occurs in that time zone too.
      if (offset4 == offset + 2 * Duration.microsecondsPerHour) {
        // A second and earlier solution, so use that.
        return offset4;
      }
      // The time zone differs one hour earlier, but not by one
      // hour, so check again in that time zone.
      int offset5 = _timeZoneOffsetInSeconds(microsecondsSinceEpoch - offset4) *
          Duration.microsecondsPerSecond;
      if (offset5 == offset4) {
        // Found a second solution earlier than the first solution, so use that.
        return offset4;
      }
    }
    // Did not find a solution in the earlier time
    // zone, so just use the original result.
    return offset;
  }
}
