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

library test.backend.declarer;

import 'dart:async';

import '../frontend/timeout.dart';
import '../utils.dart';
import 'group.dart';
import 'group_entry.dart';
import 'invoker.dart';
import 'metadata.dart';
import 'test.dart';

/// A class that manages the state of tests as they're declared.
///
/// A nested tree of Declarers tracks the current group, set-up, and tear-down
/// functions. Each Declarer in the tree corresponds to a group. This tree is
/// tracked by a zone-scoped "current" Declarer; the current declarer can be set
/// for a block using [Declarer.declare], and it can be accessed using
/// [Declarer.current].
class Declarer {
  /// The parent declarer, or `null` if this corresponds to the root group.
  final Declarer _parent;

  /// The name of the current test group, including the name of any parent
  /// groups.
  ///
  /// This is `null` if this is the root group.
  final String _name;

  /// The metadata for this group, including the metadata of any parent groups
  /// and of the test suite.
  final Metadata _metadata;

  /// The set-up functions to run for each test in this group.
  final _setUps = new List<AsyncFunction>();

  /// The tear-down functions to run for each test in this group.
  final _tearDowns = new List<AsyncFunction>();

  /// The set-up functions to run once for this group.
  final _setUpAlls = new List<AsyncFunction>();

  /// The tear-down functions to run once for this group.
  final _tearDownAlls = new List<AsyncFunction>();

  /// The children of this group, either tests or sub-groups.
  final _entries = new List<GroupEntry>();

  /// Whether [build] has been called for this declarer.
  bool _built = false;

  /// The current zone-scoped declarer.
  static Declarer get current => Zone.current[#test.declarer];

  /// Creates a new declarer for the root group.
  ///
  /// This is the implicit group that exists outside of any calls to `group()`.
  /// If [metadata] is passed, it's used as the metadata for the implicit root
  /// group.
  Declarer([Metadata metadata])
      : this._(null, null, metadata == null ? new Metadata() : metadata);

  Declarer._(this._parent, this._name, this._metadata);

  /// Runs [body] with this declarer as [Declarer.current].
  ///
  /// Returns the return value of [body].
  declare(body()) => runZoned(body, zoneValues: {#test.declarer: this});

  /// Defines a test case with the given name and body.
  void test(String name, body(), {String testOn, Timeout timeout, skip,
      Map<String, dynamic> onPlatform}) {
    _checkNotBuilt("test");

    var metadata = _metadata.merge(new Metadata.parse(
        testOn: testOn, timeout: timeout, skip: skip, onPlatform: onPlatform));

    _entries.add(new LocalTest(_prefix(name), metadata, () {
      // TODO(nweiz): It might be useful to throw an error here if a test starts
      // running while other tests from the same declarer are also running,
      // since they might share closurized state.

      // TODO(nweiz): Use async/await here once issue 23497 has been fixed in
      // two stable versions.
      return Invoker.current.waitForOutstandingCallbacks(() {
        return _runSetUps().then((_) => body());
      }).then((_) => _runTearDowns());
    }));
  }

  /// Creates a group of tests.
  void group(String name, void body(), {String testOn, Timeout timeout, skip,
      Map<String, dynamic> onPlatform}) {
    _checkNotBuilt("group");

    var metadata = _metadata.merge(new Metadata.parse(
        testOn: testOn, timeout: timeout, skip: skip, onPlatform: onPlatform));

    // Don't load the tests for a skipped group.
    if (metadata.skip) {
      _entries.add(new Group(name, [], metadata: metadata));
      return;
    }

    var declarer = new Declarer._(this, _prefix(name), metadata);
    declarer.declare(body);
    _entries.add(declarer.build());
  }

  /// Returns [name] prefixed with this declarer's group name.
  String _prefix(String name) => _name == null ? name : "$_name $name";

  /// Registers a function to be run before each test in this group.
  void setUp(callback()) {
    _checkNotBuilt("setUp");
    _setUps.add(callback);
  }

  /// Registers a function to be run after each test in this group.
  void tearDown(callback()) {
    _checkNotBuilt("tearDown");
    _tearDowns.add(callback);
  }

  /// Registers a function to be run once before all tests.
  void setUpAll(callback()) {
    _checkNotBuilt("setUpAll");
    _setUpAlls.add(callback);
  }

  /// Registers a function to be run once after all tests.
  void tearDownAll(callback()) {
    _checkNotBuilt("tearDownAll");
    _tearDownAlls.add(callback);
  }

  /// Finalizes and returns the group being declared.
  Group build() {
    _checkNotBuilt("build");

    _built = true;
    return new Group(_name, _entries.toList(),
        metadata: _metadata,
        setUpAll: _setUpAll,
        tearDownAll: _tearDownAll);
  }

  /// Throws a [StateError] if [build] has been called.
  ///
  /// [name] should be the name of the method being called.
  void _checkNotBuilt(String name) {
    if (!_built) return;
    throw new StateError("Can't call $name() once tests have begun running.");
  }

  /// Run the set-up functions for this and any parent groups.
  ///
  /// If no set-up functions are declared, this returns a [Future] that
  /// completes immediately.
  Future _runSetUps() {
    // TODO(nweiz): Use async/await here once issue 23497 has been fixed in two
    // stable versions.
    if (_parent != null) {
      return _parent._runSetUps().then((_) {
        return Future.forEach(_setUps, (setUp) => setUp());
      });
    }

    return Future.forEach(_setUps, (setUp) => setUp());
  }

  /// Run the tear-up functions for this and any parent groups.
  ///
  /// If no set-up functions are declared, this returns a [Future] that
  /// completes immediately.
  ///
  /// This should only be called within a test.
  Future _runTearDowns() {
    return Invoker.current.unclosable(() {
      var tearDowns = [];
      for (var declarer = this; declarer != null; declarer = declarer._parent) {
        tearDowns.addAll(declarer._tearDowns.reversed);
      }

      return Future.forEach(tearDowns, _errorsDontStopTest);
    });
  }

  /// Returns a [Test] that runs the callbacks in [_setUpAll].
  Test get _setUpAll {
    if (_setUpAlls.isEmpty) return null;

    return new LocalTest(_prefix("(setUpAll)"), _metadata, () {
      return Future.forEach(_setUpAlls, (setUp) => setUp());
    });
  }

  /// Returns a [Test] that runs the callbacks in [_tearDownAll].
  Test get _tearDownAll {
    if (_tearDownAlls.isEmpty) return null;

    return new LocalTest(_prefix("(tearDownAll)"), _metadata, () {
      return Invoker.current.unclosable(() {
        return Future.forEach(_tearDownAlls.reversed, _errorsDontStopTest);
      });
    });
  }

  /// Runs [body] with special error-handling behavior.
  ///
  /// Errors emitted [body] will still cause the current test to fail, but they
  /// won't cause it to *stop*. In particular, they won't remove any outstanding
  /// callbacks registered outside of [body].
  Future _errorsDontStopTest(body()) {
    var completer = new Completer();

    Invoker.current.addOutstandingCallback();
    Invoker.current.waitForOutstandingCallbacks(() {
      new Future.sync(body).whenComplete(completer.complete);
    }).then((_) => Invoker.current.removeOutstandingCallback());

    return completer.future;
  }
}
