// Copyright (c) 2020, 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.

// Checks that `Future<Future<int>>` is a valid type
// and that futures can contain and complete other futures.

// This essentially checks that `FutureOr<X>` is treated correctly depending
// on what `X` is.

import 'dart:async';
import 'package:expect/async_helper.dart';
import "package:expect/expect.dart";

main() {
  asyncStart();

  // Helper values and factories.
  Future<Null> nullFuture = Future<Null>.value(null);

  var stack = StackTrace.current;
  var error = ArgumentError("yep");
  Future<Null> errorFuture = Future<Null>.error(error, stack)
    ..catchError((_) => null);
  Future<int> fi(int n) => Future<int>.value(n);
  Future<Future<int>> ffi(n) => Future<Future<int>>.value(fi(n));

  // Tests that `Future<Future<int>>` can be created.
  asyncTest(() {
    return expectFutureFutureInt(ffi(0), 0);
  });

  // Check `Future.then`'s callback.

  asyncTest(() {
    Future<int> future = nullFuture.then<int>((_) => fi(1));
    return expectFutureInt(future, 1);
  });

  asyncTest(() {
    Future<Future<int>> future = nullFuture.then<Future<int>>((_) => fi(2));
    return expectFutureFutureInt(future, 2);
  });

  asyncTest(() {
    Future<Future<int>> future = nullFuture.then<Future<int>>((_) => ffi(3));
    return expectFutureFutureInt(future, 3);
  });

  // Check `Future.then`'s `onError`.

  asyncTest(() {
    Future<int> future = errorFuture.then<int>(
      (_) => -1,
      onError: (_) => fi(4),
    );
    return expectFutureInt(future, 4);
  });

  asyncTest(() {
    Future<Future<int>> future = errorFuture.then<Future<int>>(
      (_) => fi(-1),
      onError: (_) => fi(5),
    );
    return expectFutureFutureInt(future, 5);
  });

  asyncTest(() {
    Future<Future<int>> future = errorFuture.then<Future<int>>(
      (_) => fi(-1),
      onError: (_) => ffi(6),
    );
    return expectFutureFutureInt(future, 6);
  });

  // Check `Future.catchError`.
  // Its implied `FutureOr` return type is based on the original future's type.

  asyncTest(() {
    Future<int> errorFuture = Future<int>.error(error, stack);
    Future<int> future = errorFuture.catchError((_) => fi(7));
    return expectFutureInt(future, 7);
  });

  asyncTest(() {
    Future<Future<int>> errorFuture = Future<Future<int>>.error(error, stack);
    Future<Future<int>> future = errorFuture.catchError((_) => fi(8));
    return expectFutureFutureInt(future, 8);
  });

  asyncTest(() {
    Future<Future<int>> errorFuture = Future<Future<int>>.error(error, stack);
    Future<Future<int>> future = errorFuture.catchError((_) => ffi(9));
    return expectFutureFutureInt(future, 9);
  });

  // Check `Completer.complete`.

  asyncTest(() {
    var completer = Completer<int>()..complete(fi(10));
    return expectFutureInt(completer.future, 10);
  });

  asyncTest(() {
    var completer = Completer<Future<int>>()..complete(fi(11));
    return expectFutureFutureInt(completer.future, 11);
  });

  asyncTest(() {
    var completer = Completer<Future<int>>()..complete(ffi(12));
    return expectFutureFutureInt(completer.future, 12);
  });

  // Future<Object> works correctly when Object is another Future.
  asyncTest(() {
    Future<Object> future = nullFuture.then<Object>((_) => fi(13));
    Expect.type<Future<Object>>(future);
    Expect.notType<Future<int>>(future);
    return future.then<void>((o) {
      Expect.equals(13, o);
    });
  });

  asyncTest(() {
    Future<Object> future = nullFuture.then<Object>((_) => ffi(14));
    Expect.type<Future<Object>>(future);
    Expect.notType<Future<int>>(future);
    Expect.notType<Future<Future<int>>>(future);
    return future.then<void>((v) => expectFutureInt(v, 14));
  });

  asyncTest(() {
    Future<Object> future = errorFuture.then<Object>(
      (_) => -1,
      onError: (_) => fi(15),
    );
    Expect.type<Future<Object>>(future);
    Expect.notType<Future<int>>(future);
    return future.then<void>((o) {
      Expect.equals(15, o);
    });
  });

  asyncTest(() {
    Future<Object> future = errorFuture.then<Object>(
      (_) => -1,
      onError: (_) => ffi(16),
    );
    Expect.type<Future<Object>>(future);
    Expect.notType<Future<int>>(future);
    Expect.notType<Future<Future<int>>>(future);
    return future.then<void>((v) => expectFutureInt(v, 16));
  });

  asyncTest(() {
    Future<Object> errorFuture = Future<Object>.error(error, stack);
    Future<Object> future = errorFuture.catchError((_) => fi(17));
    Expect.type<Future<Object>>(future);
    Expect.notType<Future<int>>(future);
    return future.then<void>((o) {
      Expect.equals(17, o);
    });
  });

  asyncTest(() {
    Future<Object> errorFuture = Future<Object>.error(error, stack);
    Future<Object> future = errorFuture.catchError((_) => ffi(18));
    Expect.type<Future<Object>>(future);
    Expect.notType<Future<int>>(future);
    Expect.notType<Future<Future<int>>>(future);
    return future.then<void>((v) => expectFutureInt(v, 18));
  });

  asyncEnd();
}

// Checks that future is a Future<Future<int>> containing the value Future<int>
// which then contains the value 42.
Future<void> expectFutureFutureInt(dynamic future, int n) {
  Expect.type<Future<Future<int>>>(future);
  asyncStart();
  return future.then<void>((dynamic v) {
    Expect.type<Future<int>>(v, "$n");
    return expectFutureInt(v, n).then(asyncSuccess);
  });
}

Future<void> expectFutureInt(dynamic future, int n) {
  Expect.type<Future<int>>(future);
  asyncStart();
  return future.then<void>((dynamic v) {
    Expect.type<int>(v, "$n");
    Expect.equals(n, v);
    asyncEnd();
  });
}
