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

import 'package:async/async.dart';
import 'package:path/path.dart' as p;
import 'package:source_span/source_span.dart';
import 'package:stack_trace/stack_trace.dart';
import 'package:test_api/src/utils.dart'; // ignore: implementation_imports

import 'runner/application_exception.dart';
import 'runner/configuration.dart';
import 'runner/version.dart';
import 'runner.dart';
import 'util/exit_codes.dart' as exit_codes;
import 'util/io.dart';

StreamSubscription? signalSubscription;
bool isShutdown = false;

/// Returns the path to the global test configuration file.
final String _globalConfigPath = () {
  if (Platform.environment.containsKey('DART_TEST_CONFIG')) {
    return Platform.environment['DART_TEST_CONFIG'] as String;
  } else if (Platform.operatingSystem == 'windows') {
    return p.join(
        Platform.environment['LOCALAPPDATA'] as String, 'DartTest.yaml');
  } else {
    return '${Platform.environment['HOME']}/.dart_test.yaml';
  }
}();

Future<void> main(List<String> args) async {
  await _execute(args);
  completeShutdown();
}

Future<void> runTests(List<String> args) async {
  await _execute(args);
}

void completeShutdown() {
  if (isShutdown) return;
  if (signalSubscription != null) {
    signalSubscription!.cancel();
    signalSubscription = null;
  }
  isShutdown = true;
  stdinLines.cancel(immediate: true);
}

Future<void> _execute(List<String> args) async {
  /// A merged stream of all signals that tell the test runner to shut down
  /// gracefully.
  ///
  /// Signals will only be captured as long as this has an active subscription.
  /// Otherwise, they'll be handled by Dart's default signal handler, which
  /// terminates the program immediately.
  final _signals = Platform.isWindows
      ? ProcessSignal.sigint.watch()
      : Platform.isFuchsia // Signals don't exist on Fuchsia.
          ? Stream.empty()
          : StreamGroup.merge(
              [ProcessSignal.sigterm.watch(), ProcessSignal.sigint.watch()]);

  Configuration configuration;
  try {
    configuration = Configuration.parse(args);
  } on FormatException catch (error) {
    _printUsage(error.message);
    exitCode = exit_codes.usage;
    return;
  }

  if (configuration.help) {
    _printUsage();
    return;
  }

  if (configuration.version) {
    var version = testVersion;
    if (version == null) {
      stderr.writeln("Couldn't find version number.");
      exitCode = exit_codes.data;
    } else {
      print(version);
    }
    return;
  }

  try {
    var fileConfiguration = Configuration.empty;
    if (File(_globalConfigPath).existsSync()) {
      fileConfiguration = fileConfiguration
          .merge(Configuration.load(_globalConfigPath, global: true));
    }

    if (File(configuration.configurationPath).existsSync()) {
      fileConfiguration = fileConfiguration
          .merge(Configuration.load(configuration.configurationPath));
    }

    configuration = fileConfiguration.merge(configuration);
  } on SourceSpanFormatException catch (error) {
    stderr.writeln(error.toString(color: configuration.color));
    exitCode = exit_codes.data;
    return;
  } on FormatException catch (error) {
    stderr.writeln(error.message);
    exitCode = exit_codes.data;
    return;
  } on IOException catch (error) {
    stderr.writeln(error.toString());
    exitCode = exit_codes.noInput;
    return;
  }

  var undefinedPresets = configuration.chosenPresets
      .where((preset) => !configuration.knownPresets.contains(preset))
      .toList();
  if (undefinedPresets.isNotEmpty) {
    _printUsage("Undefined ${pluralize('preset', undefinedPresets.length)} "
        "${toSentence(undefinedPresets.map((preset) => '"$preset"'))}.");
    exitCode = exit_codes.usage;
    return;
  }

  if (!configuration.explicitPaths &&
      !Directory(configuration.paths.single).existsSync()) {
    _printUsage('No test files were passed and the default "test/" '
        "directory doesn't exist.");
    exitCode = exit_codes.data;
    return;
  }

  Runner? runner;

  signalSubscription ??= _signals.listen((signal) async {
    completeShutdown();
    await runner?.close();
  });

  try {
    runner = Runner(configuration);
    exitCode = (await runner.run()) ? 0 : 1;
  } on ApplicationException catch (error) {
    stderr.writeln(error.message);
    exitCode = exit_codes.data;
  } on SourceSpanFormatException catch (error) {
    stderr.writeln(error.toString(color: configuration.color));
    exitCode = exit_codes.data;
  } on FormatException catch (error) {
    stderr.writeln(error.message);
    exitCode = exit_codes.data;
  } catch (error, stackTrace) {
    stderr.writeln(getErrorMessage(error));
    stderr.writeln(Trace.from(stackTrace).terse);
    stderr.writeln('This is an unexpected error. Please file an issue at '
        'http://github.com/dart-lang/test\n'
        'with the stack trace and instructions for reproducing the error.');
    exitCode = exit_codes.software;
  } finally {
    await runner?.close();
  }

  // TODO(grouma) - figure out why the executable can hang in the travis
  // environment. https://github.com/dart-lang/test/issues/599
  if (Platform.environment['FORCE_TEST_EXIT'] == 'true') {
    exit(exitCode);
  }

  return;
}

/// Print usage information for this command.
///
/// If [error] is passed, it's used in place of the usage message and the whole
/// thing is printed to stderr instead of stdout.
void _printUsage([String? error]) {
  var output = stdout;

  var message = 'Runs tests in this package.';
  if (error != null) {
    message = error;
    output = stderr;
  }

  output.write('''${wordWrap(message)}

Usage: pub run test [files or directories...]

${Configuration.usage}
''');
}
