// Copyright (c) 2016, 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:test_api/src/utils.dart'; // ignore: implementation_imports

import '../util/io.dart';
import 'runner_suite.dart';
import 'configuration.dart';
import 'console.dart';
import 'engine.dart';
import 'load_suite.dart';
import 'reporter.dart';

/// Runs [loadSuite] in debugging mode.
///
/// Runs the suite's tests using [engine]. The [reporter] should already be
/// watching [engine], and the [config] should contain the user configuration
/// for the test runner.
///
/// Returns a [CancelableOperation] that will complete once the suite has
/// finished running. If the operation is canceled, the debugger will clean up
/// any resources it allocated.
CancelableOperation debug(
    Engine engine, Reporter reporter, LoadSuite loadSuite) {
  _Debugger? debugger;
  var canceled = false;
  return CancelableOperation.fromFuture(() async {
    // Make the underlying suite null so that the engine doesn't start running
    // it immediately.
    engine.suiteSink.add(loadSuite.changeSuite((runnerSuite) {
      engine.pause();
      return runnerSuite;
    }));

    var suite = await loadSuite.suite;
    if (canceled || suite == null) return;

    await (debugger = _Debugger(engine, reporter, suite)).run();
  }(), onCancel: () {
    canceled = true;
    // Make sure the load test finishes so the engine can close.
    engine.resume();
    if (debugger != null) debugger!.close();
  });
}

// TODO(nweiz): Test using the console and restarting a test once sdk#25369 is
// fixed and the VM service client is released
/// A debugger for a single test suite.
class _Debugger {
  /// The test runner configuration.
  final _config = Configuration.current;

  /// The engine that will run the suite.
  final Engine _engine;

  /// The reporter that's reporting [_engine]'s progress.
  final Reporter _reporter;

  /// The suite to run.
  final RunnerSuite _suite;

  /// The console through which the user can control the debugger.
  ///
  /// This is only visible when the test environment is paused, so as not to
  /// overlap with the reporter's reporting.
  final Console _console;

  /// A completer that's used to manually unpause the test if the debugger is
  /// closed.
  final _pauseCompleter = CancelableCompleter();

  /// The subscription to [_suite.onDebugging].
  StreamSubscription<bool>? _onDebuggingSubscription;

  /// The subscription to [_suite.environment.onRestart].
  late final StreamSubscription _onRestartSubscription;

  /// Whether [close] has been called.
  bool _closed = false;

  bool get _json => _config.reporter == 'json';

  _Debugger(this._engine, this._reporter, this._suite)
      : _console = Console(color: Configuration.current.color) {
    _console.registerCommand('restart',
        'Restart the current test after it finishes running.', _restartTest);

    _onRestartSubscription = _suite.environment.onRestart.listen((_) {
      _restartTest();
    });
  }

  /// Runs the debugger.
  ///
  /// This prints information about the suite's debugger, then once the user has
  /// had a chance to set breakpoints, runs the suite's tests.
  Future run() async {
    try {
      await _pause();
      if (_closed) return;

      _onDebuggingSubscription = _suite.onDebugging.listen((debugging) {
        if (debugging) {
          _onDebugging();
        } else {
          _onNotDebugging();
        }
      });

      _engine.resume();
      await _engine.onIdle.first;
    } finally {
      close();
    }
  }

  /// Prints URLs for the [_suite]'s debugger and waits for the user to tell the
  /// suite to run.
  Future _pause() async {
    if (!_suite.environment.supportsDebugging) return;

    try {
      if (!_json) {
        _reporter.pause();

        var bold = _config.color ? '\u001b[1m' : '';
        var yellow = _config.color ? '\u001b[33m' : '';
        var noColor = _config.color ? '\u001b[0m' : '';
        print('');

        var runtime = _suite.platform.runtime;
        if (runtime.isDartVM) {
          var url = _suite.environment.observatoryUrl;
          if (url == null) {
            print("${yellow}Observatory URL not found. Make sure you're using "
                '${runtime.name} 1.11 or later.$noColor');
          } else {
            print('Observatory URL: $bold$url$noColor');
          }
        }

        if (runtime.isHeadless && !runtime.isDartVM) {
          var url = _suite.environment.remoteDebuggerUrl;
          if (url == null) {
            print('${yellow}Remote debugger URL not found.$noColor');
          } else {
            print('Remote debugger URL: $bold$url$noColor');
          }
        }

        var buffer =
            StringBuffer('${bold}The test runner is paused.${noColor} ');
        if (runtime.isDartVM) {
          buffer.write('Open the Observatory ');
        } else {
          if (!runtime.isHeadless) {
            buffer.write('Open the dev console in $runtime ');
          } else {
            buffer.write('Open the remote debugger ');
          }
        }

        buffer.write("and set breakpoints. Once you're finished, return to "
            'this terminal and press Enter.');

        print(wordWrap(buffer.toString()));
      }

      await inCompletionOrder([
        _suite.environment.displayPause(),
        stdinLines.cancelable((queue) => queue.next),
        _pauseCompleter.operation
      ]).first;
    } finally {
      if (!_json) _reporter.resume();
    }
  }

  /// Handles the environment pausing to debug.
  ///
  /// This starts the interactive console.
  void _onDebugging() {
    if (!_json) _reporter.pause();

    if (!_json) {
      print('\nEntering debugging console. Type "help" for help.');
    }
    _console.start();
  }

  /// Handles the environment starting up again.
  ///
  /// This closes the interactive console.
  void _onNotDebugging() {
    if (!_json) _reporter.resume();
    _console.stop();
  }

  /// Restarts the current test.
  void _restartTest() {
    if (_engine.active.isEmpty) return;
    var liveTest = _engine.active.single;
    _engine.restartTest(liveTest);
    if (!_json) {
      print(wordWrap(
          'Will restart "${liveTest.test.name}" once it finishes running.'));
    }
  }

  /// Closes the debugger and releases its resources.
  void close() {
    _pauseCompleter.complete();
    _closed = true;
    _onDebuggingSubscription?.cancel();
    _onRestartSubscription.cancel();
    _console.stop();
  }
}
