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

/// A minimal, dependency-free emulation layer for a subset of the
/// unittest/test API used by the language and core library.
///
/// Compared with `minitest.dart`, this library supports and expects
/// asynchronous tests. It uses a `Zone` per test to associate a test name with
/// the failure.
///
/// It does not support `setUp` or `tearDown` methods,
/// and matchers are severely restricted.
///
/// A number of our language and core library tests were written against the
/// unittest package, which is now deprecated in favor of the new test package.
/// The latter is much better feature-wise, but is also quite complex and has
/// many dependencies. For low-level language and core library tests, we don't
/// want to have to pull in a large number of dependencies and be able to run
/// them correctly in order to run a test, so we want to test them against
/// something simpler.
///
/// When possible, we just use the tiny expect library. But to avoid rewriting
/// all of the existing tests that use unittest, they can instead use this,
/// which shims the unittest API with as little code as possible and calls into
/// expect.
///
/// Eventually, it would be good to refactor those tests to use the expect
/// package directly and remove this.
library;

import 'dart:async';

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

void group(String name, Function() body) {
  var oldName = _pushName(name);
  try {
    body();
  } finally {
    _popName(oldName);
  }
}

void test(String name, Function() body) {
  var oldName = _pushName(name);

  asyncStart();
  var result = runZoned(body, zoneValues: {_testToken: _currentName});
  if (result is Future) {
    result.then((_) {
      asyncEnd();
    });
  } else {
    // Ensure all tests get to be set up first.
    scheduleMicrotask(asyncEnd);
  }

  _popName(oldName);
}

void expect(dynamic value, dynamic matcher, {String reason = ""}) {
  Matcher m;
  if (matcher is _Matcher) {
    m = matcher.call;
  } else if (matcher is! Matcher) {
    m = equals(matcher);
  } else {
    m = matcher;
  }
  m(value);
}

R Function() expectAsync0<R>(R Function() f, {int count = 1}) {
  asyncStart(count);
  return () {
    var result = f();
    asyncEnd();
    return result;
  };
}

R Function(A) expectAsync1<R, A>(R Function(A) f, {int count = 1}) {
  asyncStart(count);
  return (A a) {
    var result = f(a);
    asyncEnd();
    return result;
  };
}

R Function(A, B) expectAsync2<R, A, B>(R Function(A, B) f, {int count = 1}) {
  asyncStart(count);
  return (A a, B b) {
    var result = f(a, b);
    asyncEnd();
    return result;
  };
}

dynamic expectAsync(Function f, {int count = 1}) {
  var f2 = f; // Avoid type-promoting f, we want dynamic invocations.
  if (f2 is Function(Never, Never, Never, Never, Never)) {
    asyncStart(count);
    return ([a, b, c, d, e]) {
      var result = f(a, b, c, d, e);
      asyncEnd();
      return result;
    };
  }
  if (f2 is Function(Never, Never, Never, Never)) {
    asyncStart(count);
    return ([a, b, c, d]) {
      var result = f(a, b, c, d);
      asyncEnd();
      return result;
    };
  }
  if (f2 is Function(Never, Never, Never)) {
    asyncStart(count);
    return ([a, b, c]) {
      var result = f(a, b, c);
      asyncEnd();
      return result;
    };
  }
  if (f2 is Function(Never, Never)) {
    asyncStart(count);
    return ([a, b]) {
      var result = f(a, b);
      asyncEnd();
      return result;
    };
  }
  if (f2 is Function(Never)) {
    asyncStart(count);
    return ([a]) {
      var result = f(a);
      asyncEnd();
      return result;
    };
  }
  if (f2 is Function()) {
    asyncStart(count);
    return () {
      var result = f();
      asyncEnd();
      return result;
    };
  }
  throw UnsupportedError(
      "expectAsync only accepts up to five argument functions");
}

// Matchers
typedef Matcher = void Function(dynamic);

Matcher same(dynamic o) => (v) {
      Expect.identical(o, v);
    };

Matcher equals(dynamic o) => (v) {
      Expect.deepEquals(o, v);
    };

Matcher greaterThan(num n) => (dynamic v) {
      Expect.type<num>(v);
      num value = v;
      if (value > n) return;
      Expect.fail("$v is not greater than $n");
    };

Matcher greaterThanOrEqualTo(num n) => (dynamic v) {
      Expect.type<num>(v);
      num value = v;
      if (value >= n) return;
      Expect.fail("$v is not greater than $n");
    };

Matcher lessThan(num n) => (dynamic v) {
      Expect.type<num>(v);
      num value = v;
      if (value < n) return;
      Expect.fail("$v is not less than $n");
    };

Matcher lessThanOrEqualTo(num n) => (dynamic v) {
      Expect.type<num>(v);
      num value = v;
      if (value <= n) return;
      Expect.fail("$v is not less than $n");
    };

Matcher predicate(bool Function(dynamic value) fn, [String description = ""]) =>
    (dynamic v) {
      Expect.isTrue(fn(v), description);
    };

Matcher anyOf(List<String> expected) => (dynamic actual) {
      for (var string in expected) {
        if (actual == string) return;
      }

      Expect.fail("Expected $actual to be one of $expected.");
    };

void isTrue(dynamic v) {
  Expect.isTrue(v);
}

void isFalse(dynamic v) {
  Expect.isFalse(v);
}

void isNull(dynamic o) {
  Expect.isNull(o);
}

void _checkThrow<T extends Object>(
    dynamic v, void Function(dynamic error) onError) {
  if (v is Future) {
    asyncStart();
    v.then((_) {
      Expect.fail("Did not throw");
    }, onError: (e, s) {
      if (e is! T) throw e;
      onError(e);
      asyncEnd();
    });
    return;
  }
  Expect.throws<T>(v, (e) {
    onError(e);
    return true;
  });
}

void returnsNormally(dynamic o) {
  try {
    Expect.type<Function()>(o);
    o();
  } catch (error, trace) {
    Expect.fail(
        "Expected function to return normally, but threw:\n$error\n\n$trace");
  }
}

void throws(dynamic v) {
  _checkThrow<Object>(v, (_) {});
}

Matcher throwsA(matcher) => (dynamic o) {
      _checkThrow<Object>(o, (error) {
        expect(error, matcher);
      });
    };

Matcher completion(matcher) => (dynamic o) {
      Expect.type<Future>(o);
      Future future = o;
      asyncStart();
      future.then((value) {
        expect(value, matcher);
        asyncEnd();
      });
    };

void completes(dynamic o) {
  Expect.type<Future>(o);
  Future future = o;
  asyncStart();
  future.then(asyncSuccess);
}

void isMap(dynamic o) {
  Expect.type<Map>(o);
}

void isList(dynamic o) {
  Expect.type<List>(o);
}

void isNotNull(dynamic o) {
  Expect.isNotNull(o);
}

abstract class _Matcher {
  void call(dynamic o);
}

// ignore: camel_case_types
class isInstanceOf<T> implements _Matcher {
  @override
  void call(dynamic o) {
    Expect.type<T>(o);
  }
}

void throwsArgumentError(dynamic v) {
  _checkThrow<ArgumentError>(v, (_) {});
}

void throwsStateError(dynamic v) {
  _checkThrow<StateError>(v, (_) {});
}

void fail(String message) {
  Expect.fail(message);
}

/// Key for zone value holding current test name.
final _testToken = Object();

bool _initializedTestNameCallback = false;

/// The current combined name of the nesting [group] or [test].
String _currentName = "";

String _pushName(String newName) {
  // Look up the current test name from the zone created for the test.
  if (!_initializedTestNameCallback) {
    ExpectException.setTestNameCallback(() => Zone.current[_testToken]);
    _initializedTestNameCallback = true;
  }

  var oldName = _currentName;
  if (oldName == "") {
    _currentName = newName;
  } else {
    _currentName = "$oldName $newName";
  }
  return oldName;
}

void _popName(String oldName) {
  _currentName = oldName;
}
