// Copyright 2019 The Fuchsia Authors. 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 'dart:convert';
import 'dart:io';

import 'package:fxtest/fxtest.dart';
import 'package:fxutils/fxutils.dart';

/// Disposable runner which executes a single test and presents its output in
/// realtime (via streams) and aggregates for the end (via a [StringBuffer]).
class TestRunner {
  final StreamController<String> _stdoutController;
  final StartProcess _startProcess;

  TestRunner({StartProcess? startProcess})
      : _stdoutController = StreamController<String>(),
        _startProcess = startProcess ?? Process.start;

  Stream<String> get output => _stdoutController.stream;
  void addOutput(String content) => _stdoutController.sink.add(content);

  /// Wrapper which runs commands and not only collects all output for a
  /// [ProcessResult], but also optionally emits realtime events from nested
  /// stdout.
  ///
  /// The [run] method takes an optional [realtimeOutputSink], which is used to
  /// flush output from the process running individual tests. To achieve this,
  /// two intermediate streams are created, one each for the sub-process's
  /// [stdout] and [stderr], with listeners that maintain complete copies for
  /// our value and which dump each update into [realtimeOutputSink] if it was
  /// supplied.
  Future<ProcessResult> run(
    String command,
    List<String> args, {
    required String workingDirectory,
    Map<String, String>? environment,
  }) async {
    var processArgs = _buildProcessArgs(command, args);
    Process process = await _startProcess(
      processArgs.command,
      processArgs.args,
      environment: environment,
      workingDirectory: workingDirectory,
    );

    var utf8decoder = Utf8Decoder(allowMalformed: true);
    var _stdOut = StringBuffer();
    var stdOutFinish = Future(() async {
      var lines =
          process.stdout.transform(utf8decoder).transform(LineSplitter());
      await for (var val in lines) {
        _stdOut.writeln(val);
        addOutput(val);
      }
    });

    var _stdErr = StringBuffer();
    var stdErrFinish = Future(() async {
      var lines =
          process.stderr.transform(utf8decoder).transform(LineSplitter());
      await for (var val in lines) {
        _stdErr.writeln(val);
        addOutput(val);
      }
    });

    // Wait for test to actually end. This means waiting for the test process
    // to terminate and for the output streams to be flushed.
    var results =
        await Future.wait([process.exitCode, stdOutFinish, stdErrFinish]);
    var _exitCode = results[0] ?? -1;

    await close();

    // Return the same thing as if we'd used `Process.run`.
    return ProcessResult(
      process.pid,
      _exitCode,
      _stdOut.toString(),
      _stdErr.toString(),
    );
  }

  Future close() {
    return _stdoutController.close();
  }

  _ProcessArgs _buildProcessArgs(String command, List<String> args) {
    return _ProcessArgs(command, args);
  }
}

class SymbolizingTestRunner extends TestRunner {
  final String fx;

  SymbolizingTestRunner({
    required this.fx,
  }) : assert(fx != '');

  factory SymbolizingTestRunner.builder(TestsConfig testsConfig) =>
      SymbolizingTestRunner(fx: testsConfig.fxEnv.fx);

  @override
  _ProcessArgs _buildProcessArgs(String command, List<String> args) {
    return _ProcessArgs('bash', [
      // `-o pipefail` forwards the exitcode from `command` (the test itself)
      // instead of the always-zero exitcode from symbolize
      '-o',
      'pipefail',
      // `-c` keeps the pipe in the domain of `bash`, and not in the domain of
      // `fx shell ...`, which leads to "can't find fx" errors (since that's
      // not on the device)
      '-c',
      [command, ...args, '|', fx, 'symbolize'].join(' ')
    ]);
  }
}

class _ProcessArgs {
  final String command;
  final List<String> args;
  _ProcessArgs(this.command, this.args);

  @override
  String toString() => '$command ${args.join(' ')}';
}
