// 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.
  @pragma("vm:external-name", "DateTime_currentTimeMicros")
  static int _getCurrentMicros() =>
      (_jsDateNow() * Duration.microsecondsPerMillisecond).toInt();

  @pragma("vm:external-name", "DateTime_timeZoneName")
  external static String _timeZoneNameForClampedSeconds(int secondsSinceEpoch);

  @pragma("vm:external-name", "DateTime_timeZoneOffsetInSeconds")
  external static int _timeZoneOffsetInSecondsForClampedSeconds(
      int secondsSinceEpoch);

  // Daylight-savings independent adjustment for the local time zone.
  @pragma("vm:external-name", "DateTime_localTimeZoneAdjustmentInSeconds")
  external static int _localTimeZoneAdjustmentInSeconds();

  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);
  }

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