// 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'];
  } 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();
}

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()
      : 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}
''');
}
