// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

// @dart = 2.6
import 'package:test/bootstrap/browser.dart';
import 'package:test/test.dart';
import 'package:quiver/testing/async.dart';
import 'package:quiver/time.dart';

import 'package:ui/src/engine/alarm_clock.dart';

void main() {
  internalBootstrapBrowserTest(() => testMain);
}

void testMain() {
  group(AlarmClock, () {
    _alarmClockTests();
  });
}

void _alarmClockTests() {
  int callCount = 0;

  void testCallback() {
    callCount += 1;
  }

  setUp(() {
    callCount = 0;
  });

  testAsync('AlarmClock calls the callback in the future',
      (FakeAsync fakeAsync) {
    final Clock clock = fakeAsync.getClock(DateTime(2019, 1, 24));
    final AlarmClock alarm = AlarmClock(clock.now);
    alarm.callback = testCallback;

    // There should be no timers scheduled until we set a non-null datetime.
    expect(fakeAsync.nonPeriodicTimerCount, 0);

    alarm.datetime = clock.fromNow(minutes: 1);

    // There should be exactly 1 timer scheduled.
    expect(fakeAsync.nonPeriodicTimerCount, 1);

    // No time has passed; the callback should not be called.
    expect(callCount, 0);

    // Not enough time has passed; the callback should not be called.
    fakeAsync.elapse(const Duration(seconds: 30));
    expect(callCount, 0);

    // Exactly 1 minute has passed; fire the callback.
    fakeAsync.elapse(const Duration(seconds: 30));
    expect(callCount, 1);

    // Timers should be cleaned up.
    expect(fakeAsync.nonPeriodicTimerCount, 0);

    // Rescheduling.
    alarm.datetime = clock.fromNow(minutes: 1);
    expect(fakeAsync.nonPeriodicTimerCount, 1);
    fakeAsync.elapse(const Duration(minutes: 1));
    expect(fakeAsync.nonPeriodicTimerCount, 0);
    expect(callCount, 2);
  });

  testAsync('AlarmClock does nothing when new datetime is the same',
      (FakeAsync fakeAsync) {
    final Clock clock = fakeAsync.getClock(DateTime(2019, 1, 24));
    final AlarmClock alarm = AlarmClock(clock.now);
    alarm.callback = testCallback;

    alarm.datetime = clock.fromNow(minutes: 1);
    expect(fakeAsync.nonPeriodicTimerCount, 1);
    expect(callCount, 0);

    alarm.datetime = alarm.datetime.add(Duration.zero);
    expect(fakeAsync.nonPeriodicTimerCount, 1);
    expect(callCount, 0);

    fakeAsync.elapse(const Duration(seconds: 30));

    alarm.datetime = alarm.datetime.add(Duration.zero);
    expect(fakeAsync.nonPeriodicTimerCount, 1);
    expect(callCount, 0);

    fakeAsync.elapse(const Duration(seconds: 30));
    expect(fakeAsync.nonPeriodicTimerCount, 0);
    expect(callCount, 1);
  });

  testAsync('AlarmClock does not call the callback in the past',
      (FakeAsync fakeAsync) {
    final Clock clock = fakeAsync.getClock(DateTime(2019, 1, 24));
    final AlarmClock alarm = AlarmClock(clock.now);
    alarm.callback = testCallback;
    alarm.datetime = clock.ago(minutes: 1);

    // No timers scheduled for past dates.
    expect(fakeAsync.nonPeriodicTimerCount, 0);
    expect(callCount, 0);
  });

  testAsync('AlarmClock reschedules to a future time', (FakeAsync fakeAsync) {
    final Clock clock = fakeAsync.getClock(DateTime(2019, 1, 24));
    final AlarmClock alarm = AlarmClock(clock.now);
    alarm.callback = testCallback;

    alarm.datetime = clock.fromNow(minutes: 1);
    expect(fakeAsync.nonPeriodicTimerCount, 1);

    expect(callCount, 0);
    fakeAsync.elapse(const Duration(seconds: 30));
    expect(callCount, 0);

    // Reschedule.
    alarm.datetime = alarm.datetime.add(const Duration(minutes: 1));

    fakeAsync.elapse(const Duration(minutes: 1));

    // Still no calls because we rescheduled.
    expect(callCount, 0);

    fakeAsync.elapse(const Duration(seconds: 30));
    expect(callCount, 1);
    expect(fakeAsync.nonPeriodicTimerCount, 0);
  });

  testAsync('AlarmClock reschedules to an earlier time', (FakeAsync fakeAsync) {
    final Clock clock = fakeAsync.getClock(DateTime(2019, 1, 24));
    final AlarmClock alarm = AlarmClock(clock.now);
    alarm.callback = testCallback;

    alarm.datetime = clock.fromNow(minutes: 1);
    expect(fakeAsync.nonPeriodicTimerCount, 1);

    expect(callCount, 0);
    fakeAsync.elapse(const Duration(seconds: 30));
    expect(callCount, 0);

    // Reschedule to an earlier time that's still in the future.
    alarm.datetime = alarm.datetime.subtract(const Duration(seconds: 15));

    fakeAsync.elapse(const Duration(seconds: 45));
    expect(callCount, 1);
    expect(fakeAsync.nonPeriodicTimerCount, 0);
  });

  testAsync('AlarmClock cancels the timer when datetime is null',
      (FakeAsync fakeAsync) {
    final Clock clock = fakeAsync.getClock(DateTime(2019, 1, 24));
    final AlarmClock alarm = AlarmClock(clock.now);
    alarm.callback = testCallback;

    alarm.datetime = clock.fromNow(minutes: 1);
    expect(fakeAsync.nonPeriodicTimerCount, 1);

    // Cancel.
    alarm.datetime = null;
    expect(fakeAsync.nonPeriodicTimerCount, 0);
    expect(callCount, 0);

    // Make sure nothing fires even if we wait long enough.
    fakeAsync.elapse(const Duration(minutes: 2));
    expect(callCount, 0);
    expect(fakeAsync.nonPeriodicTimerCount, 0);
  });

  testAsync('AlarmClock cancels the timer when datetime is in the past',
      (FakeAsync fakeAsync) {
    final Clock clock = fakeAsync.getClock(DateTime(2019, 1, 24));
    final AlarmClock alarm = AlarmClock(clock.now);
    alarm.callback = testCallback;

    alarm.datetime = clock.fromNow(minutes: 1);
    expect(fakeAsync.nonPeriodicTimerCount, 1);
    fakeAsync.elapse(const Duration(seconds: 30));
    expect(callCount, 0);
    expect(fakeAsync.nonPeriodicTimerCount, 1);

    // Cancel.
    alarm.datetime = clock.ago(seconds: 1);
    expect(fakeAsync.nonPeriodicTimerCount, 0);
    expect(callCount, 0);

    // Make sure nothing fires even if we wait long enough.
    fakeAsync.elapse(const Duration(minutes: 2));
    expect(callCount, 0);
    expect(fakeAsync.nonPeriodicTimerCount, 0);
  });
}

typedef FakeAsyncTest = void Function(FakeAsync);

void testAsync(String description, FakeAsyncTest fn) {
  test(description, () {
    FakeAsync().run(fn);
  });
}
