//
// Copyright 2014 Google Inc. All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd
//

library charted.core.time_intervals;

class TimeInterval {
  final DateTime Function(DateTime) _floor;
  final DateTime Function(DateTime, int) _step;
  final int Function(DateTime) _number;

  TimeInterval(this._floor, this._step, this._number);

  DateTime floor(dynamic date) {
    assert(date is int || date is DateTime);
    if (date is int) {
      date = new DateTime.fromMillisecondsSinceEpoch(date as int);
    }
    return _floor(date as DateTime);
  }

  DateTime round(dynamic date) {
    DateTime d0 = floor(date), d1 = offset(d0, 1);
    int ms = date is int ? date : date.millisecondsSinceEpoch;
    return (ms - d0.millisecondsSinceEpoch < d1.millisecondsSinceEpoch - ms)
        ? d0
        : d1;
  }

  DateTime ceil(dynamic date) => offset(floor(date), 1);

  DateTime offset(DateTime date, int k) => _step(date, k);

  Iterable<DateTime> range(dynamic t0, dynamic t1, int dt) {
    assert(t0 is int || t0 is DateTime);
    assert(t1 is int || t1 is DateTime);

    List<DateTime> values = [];
    DateTime t1Date = t1 is DateTime
        ? t1
        : new DateTime.fromMillisecondsSinceEpoch(t1 as int);

    DateTime time = ceil(t0);
    if (dt > 1) {
      while (time.isBefore(t1Date)) {
        if ((_number(time) % dt) == 0) {
          values.add(new DateTime.fromMillisecondsSinceEpoch(
              time.millisecondsSinceEpoch));
        }
        time = _step(time, 1);
      }
    } else {
      while (time.isBefore(t1Date)) {
        values.add(new DateTime.fromMillisecondsSinceEpoch(
            time.millisecondsSinceEpoch));
        time = _step(time, 1);
      }
    }
    return values;
  }

  static final TimeInterval second = new TimeInterval(
      (DateTime date) => new DateTime.fromMillisecondsSinceEpoch(
          (date.millisecondsSinceEpoch ~/ 1000) * 1000),
      (DateTime date, int offset) => date =
          new DateTime.fromMillisecondsSinceEpoch(
              date.millisecondsSinceEpoch + offset * 1000),
      (DateTime date) => date.second);

  static final TimeInterval minute = new TimeInterval(
      (DateTime date) => new DateTime.fromMillisecondsSinceEpoch(
          (date.millisecondsSinceEpoch ~/ 60000) * 60000),
      (DateTime date, int offset) => date =
          new DateTime.fromMillisecondsSinceEpoch(
              date.millisecondsSinceEpoch + offset * 60000),
      (DateTime date) => date.minute);

  static final TimeInterval hour = new TimeInterval(
      (DateTime date) => new DateTime.fromMillisecondsSinceEpoch(
          (date.millisecondsSinceEpoch ~/ 3600000) * 3600000),
      (DateTime date, int offset) => date =
          new DateTime.fromMillisecondsSinceEpoch(
              date.millisecondsSinceEpoch + offset * 3600000),
      (DateTime date) => date.hour);

  static final TimeInterval day = new TimeInterval(
      (DateTime date) => new DateTime(date.year, date.month, date.day),
      (DateTime date, int offset) => new DateTime(
          date.year,
          date.month,
          date.day + offset,
          date.hour,
          date.minute,
          date.second,
          date.millisecond),
      (DateTime date) => date.day - 1);

  static final TimeInterval week = new TimeInterval(
      (DateTime date) =>
          new DateTime(date.year, date.month, date.day - (date.weekday % 7)),
      (DateTime date, int offset) => new DateTime(
          date.year,
          date.month,
          date.day + offset * 7,
          date.hour,
          date.minute,
          date.second,
          date.millisecond), (DateTime date) {
    var day = year.floor(date).day;
    return (dayOfYear(date) + day % 7) ~/ 7;
  });

  static final TimeInterval month = new TimeInterval(
      (DateTime date) => new DateTime(date.year, date.month, 1),
      (DateTime date, int offset) => new DateTime(
          date.year,
          date.month + offset,
          date.day,
          date.hour,
          date.minute,
          date.second,
          date.millisecond),
      (DateTime date) => date.month - 1);

  static final TimeInterval year = new TimeInterval(
      (DateTime date) => new DateTime(date.year),
      (DateTime date, int offset) => new DateTime(
          date.year + offset,
          date.month,
          date.day,
          date.hour,
          date.minute,
          date.second,
          date.millisecond),
      (DateTime date) => date.year);

  static int dayOfYear(DateTime date) =>
      date.difference(year.floor(date)).inDays;
}
