// 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/backend/util/pretty_print.dart'; // ignore: implementation_imports

import 'runner.dart';
import 'runner/application_exception.dart';
import 'runner/configuration.dart';
import 'runner/no_tests_found_exception.dart';
import 'runner/version.dart';
import 'util/errors.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']!;
  } else if (Platform.operatingSystem == 'windows') {
    return p.join(Platform.environment['LOCALAPPDATA']!, 'DartTest.yaml');
  } else {
    return '${Platform.environment['HOME']}/.dart_test.yaml';
  }
}();

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

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

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

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.
          ? const Stream<Never>.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.testSelections.keys.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;
  } on NoTestsFoundException catch (error) {
    stderr.writeln(error.message);
    exitCode = exit_codes.noTestsRan;
  } 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();
  }

  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: dart test [files or directories...]

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