// 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.

import 'dart:async';

import 'package:async/async.dart';
import 'package:stream_channel/stream_channel.dart';
import 'package:test_api/src/backend/group.dart'; // ignore: implementation_imports
import 'package:test_api/src/backend/suite.dart'; // ignore: implementation_imports
import 'package:test_api/src/backend/suite_platform.dart'; // ignore: implementation_imports
import 'package:test_api/src/backend/test.dart'; // ignore: implementation_imports

import 'environment.dart';
import 'suite.dart';

/// A suite produced and consumed by the test runner that has runner-specific
/// logic and lifecycle management.
///
/// This is separated from [Suite] because the backend library (which will
/// eventually become its own package) is primarily for test code itself to use,
/// for which the [RunnerSuite] APIs don't make sense.
///
/// A [RunnerSuite] can be produced and controlled using a
/// [RunnerSuiteController].
class RunnerSuite extends Suite {
  final RunnerSuiteController _controller;

  /// The environment in which this suite runs.
  Environment get environment => _controller._environment;

  /// The configuration for this suite.
  SuiteConfiguration get config => _controller._config;

  /// Whether the suite is paused for debugging.
  ///
  /// When using a dev inspector, this may also mean that the entire browser is
  /// paused.
  bool get isDebugging => _controller._isDebugging;

  /// A broadcast stream that emits an event whenever the suite is paused for
  /// debugging or resumed afterwards.
  ///
  /// The event is `true` when debugging starts and `false` when it ends.
  Stream<bool> get onDebugging => _controller._onDebuggingController.stream;

  /// Returns a channel that communicates with the remote suite.
  ///
  /// This connects to a channel created by code in the test worker calling
  /// `suiteChannel()` from `remote_platform_helpers.dart` with the same name.
  /// It can be used used to send and receive any JSON-serializable object.
  StreamChannel channel(String name) => _controller.channel(name);

  /// A shortcut constructor for creating a [RunnerSuite] that never goes into
  /// debugging mode and doesn't support suite channels.
  factory RunnerSuite(Environment environment, SuiteConfiguration config,
      Group group, SuitePlatform platform,
      {String path, Function() onClose}) {
    var controller =
        RunnerSuiteController._local(environment, config, onClose: onClose);
    var suite = RunnerSuite._(controller, group, path, platform);
    controller._suite = Future.value(suite);
    return suite;
  }

  RunnerSuite._(
      this._controller, Group group, String path, SuitePlatform platform)
      : super(group, platform, path: path);

  @override
  RunnerSuite filter(bool Function(Test) callback) {
    var filtered = group.filter(callback);
    filtered ??= Group.root([], metadata: metadata);
    return RunnerSuite._(_controller, filtered, path, platform);
  }

  /// Closes the suite and releases any resources associated with it.
  Future close() => _controller._close();

  /// Collects a hit-map containing merged coverage.
  ///
  /// Result is suitable for input to the coverage formatters provided by
  /// `package:coverage`.
  Future<Map<String, dynamic>> gatherCoverage() async =>
      (await _controller._gatherCoverage?.call()) ?? {};
}

/// A class that exposes and controls a [RunnerSuite].
class RunnerSuiteController {
  /// The suite controlled by this controller.
  Future<RunnerSuite> get suite => _suite;
  Future<RunnerSuite> _suite;

  /// The backing value for [suite.environment].
  final Environment _environment;

  /// The configuration for this suite.
  final SuiteConfiguration _config;

  /// A channel that communicates with the remote suite.
  final MultiChannel _suiteChannel;

  /// The function to call when the suite is closed.
  final Function() _onClose;

  /// The backing value for [suite.isDebugging].
  bool _isDebugging = false;

  /// The controller for [suite.onDebugging].
  final _onDebuggingController = StreamController<bool>.broadcast();

  /// The channel names that have already been used.
  final _channelNames = <String>{};

  /// Collects a hit-map containing merged coverage.
  final Future<Map<String, dynamic>> Function() _gatherCoverage;

  RunnerSuiteController(this._environment, this._config, this._suiteChannel,
      Future<Group> groupFuture, SuitePlatform platform,
      {String path,
      Function() onClose,
      Future<Map<String, dynamic>> Function() gatherCoverage})
      : _onClose = onClose,
        _gatherCoverage = gatherCoverage {
    _suite =
        groupFuture.then((group) => RunnerSuite._(this, group, path, platform));
  }

  /// Used by [new RunnerSuite] to create a runner suite that's not loaded from
  /// an external source.
  RunnerSuiteController._local(this._environment, this._config,
      {Function() onClose,
      Future<Map<String, dynamic>> Function() gatherCoverage})
      : _suiteChannel = null,
        _onClose = onClose,
        _gatherCoverage = gatherCoverage;

  /// Sets whether the suite is paused for debugging.
  ///
  /// If this is different than [suite.isDebugging], this will automatically
  /// send out an event along [suite.onDebugging].
  void setDebugging(bool debugging) {
    if (debugging == _isDebugging) return;
    _isDebugging = debugging;
    _onDebuggingController.add(debugging);
  }

  /// Returns a channel that communicates with the remote suite.
  ///
  /// This connects to a channel created by code in the test worker calling
  /// `suiteChannel()` from `remote_platform_helpers.dart` with the same name.
  /// It can be used used to send and receive any JSON-serializable object.
  ///
  /// This is exposed on the [RunnerSuiteController] so that runner plugins can
  /// communicate with the workers they spawn before the associated [suite] is
  /// fully loaded.
  StreamChannel channel(String name) {
    if (!_channelNames.add(name)) {
      throw StateError('Duplicate RunnerSuite.channel() connection "$name".');
    }

    var channel = _suiteChannel.virtualChannel();
    _suiteChannel.sink
        .add({'type': 'suiteChannel', 'name': name, 'id': channel.id});
    return channel;
  }

  /// The backing function for [suite.close].
  Future _close() => _closeMemo.runOnce(() async {
        await _onDebuggingController.close();
        if (_onClose != null) await _onClose();
      });
  final _closeMemo = AsyncMemoizer();
}
