// 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:io';

import 'package:args/args.dart';
import 'package:fxtest/fxtest.dart';
import 'package:fxutils/fxutils.dart';
import 'package:io/ansi.dart';

void usage(ArgParser parser) {
  stdout.writeln('''Usage: fx test [testName ...]

Options:
${parser.usage}

Examples:

  - Execute all tests
  fx test

  - Execute the test component available at this URL
  fx test fuchsia-pkg://fuchsia.com/myPackageName/#meta/componentName.cmx

  - Execute the test whose package URL's `package-name` component matches
    the value. Runs all tests contained in this package.
  fx test myPackageName

  - Execute the test whose package URL's `resource-path` component matches
    the value. Runs only that test out of its containing package.
  fx test componentName

  - Execute all tests at and below this path (usually host tests)
  fx test //subtree/path

  - Multiple test names can be supplied in the same invocation, e.g.:
  fx test //subtree/path //another/path fuchsia-pkg://...

  - Print help for a test:
  fx test -o testName -- --help

The value(s) supplied for `testName` can be fully-formed Fuchsia Package URLs,
Fuchsia package names, or Fuchsia-tree directories. Partial tree paths
will execute all descendent tests.
    ''');
}

void _directoryBuilder(String path, {bool recursive = false}) {
  Directory(path).createSync(recursive: recursive);
}

/// CLI entry point for [FuchsiaTestCommand]. The [main] function mostly
/// handles the SIGINT signal, routing through [FuchsiaTestCommandCli] to handle
/// translating raw command line arguments into constructs that make sense to
/// [FuchsiaTestCommand].
Future<void> main(List<String> args) async {
  FuchsiaTestCommandCli cmdCli;
  try {
    cmdCli = FuchsiaTestCommandCli(
      args,
      fxEnv: FxEnv(envReader: EnvReader.fromEnvironment()),
      usage: usage,
      directoryBuilder: _directoryBuilder,
    );
  } on Exception catch (ex) {
    stderr.writeln('Invalid syntax: $ex');
    usage(fxTestArgParser);
    exitCode = 64; // Improper usage
    return null;
  }

  registerCleanUp(() async {
    await cmdCli.terminateEarly();
    await cmdCli.cleanUp();
  });
  _sigintSub ??= ProcessSignal.sigint.watch().listen(cleanUpAndExit);

  try {
    // Before going through all the trouble of initializing everything for the
    // command, make sure everything is valid and that the user doesn't want
    // some simple debug output.
    bool shouldRun = await cmdCli.preRunChecks(
      stdout.write,
    );
    if (shouldRun) {
      // Finally, run the command
      await cmdCli.run();
    }
  } on FxRunException catch (err) {
    stderr.writeln('${wrapWith("Error:", [red])} ${err.toString()}');
    exitCode = err.exitCode;
  } on Exception catch (err) {
    if (err is OutputClosedException) {
      exitCode = err.exitCode;
    } else {
      stderr.writeln(wrapWith(err.toString(), [red]));
    }
  }
  await closeSigIntListener();
  await cmdCli.cleanUp();
}

StreamSubscription? _sigintSub;

final _cleanup = <Future Function()>[];
void registerCleanUp(Future Function() c) => _cleanup.add(c);

void cleanUpAndExit(ProcessSignal signal,
    [int processExitCode = failureExitCode]) async {
  // Kick off all registered clean up functions.
  List<Future> cleanUpFutures = _cleanup
      .map((Function cleanUpFunction) async => cleanUpFunction())
      .toList();
  await Future.wait(cleanUpFutures);

  exitCode = processExitCode;
  await closeSigIntListener();
  exit(exitCode);
}

Future<void> closeSigIntListener() async {
  await _sigintSub?.cancel();
}
