// Copyright (c) 2016, 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.md file.

library testing.run_tests;

import 'dart:async' show Future;

import 'dart:io' show Directory, File, FileSystemEntity;

import 'dart:io' as io show exitCode;

import 'dart:isolate' show Isolate;

import 'error_handling.dart' show withErrorHandling;

import 'test_root.dart' show TestRoot;

import 'zone_helper.dart' show runGuarded;

import 'log.dart' show enableVerboseOutput, isVerbose, StdoutLogger;

import 'run.dart' show SuiteRunner, runProgram;

class CommandLine {
  final Set<String> options;
  final List<String> arguments;

  CommandLine(this.options, this.arguments);

  bool get verbose => options.contains("--verbose") || options.contains("-v");

  Set<String> get skip => commaSeparated("--skip=");

  Set<String> commaSeparated(String prefix) {
    return new Set<String>.from(options.expand((String s) {
      if (!s.startsWith(prefix)) return const [];
      s = s.substring(prefix.length);
      return s.split(",");
    }));
  }

  Map<String, String> get environment {
    Map<String, String> result = <String, String>{};
    for (String option in options) {
      if (option.startsWith("-D")) {
        int equalIndex = option.indexOf("=");
        if (equalIndex != -1) {
          String key = option.substring(2, equalIndex);
          String value = option.substring(equalIndex + 1);
          result[key] = value;
        }
      }
    }
    return result;
  }

  Set<String> get selectedSuites {
    return selectors.map((String selector) {
      int index = selector.indexOf("/");
      return index == -1 ? selector : selector.substring(0, index);
    }).toSet();
  }

  Iterable<String> get selectors => arguments;

  Future<Uri?> get configuration async {
    const String configPrefix = "--config=";
    List<String> configurationPaths = options
        .where((String option) => option.startsWith(configPrefix))
        .map((String option) => option.substring(configPrefix.length))
        .toList();
    if (configurationPaths.length > 1) {
      return fail("Only one --config option is supported");
    }
    String configurationPath;
    if (configurationPaths.length == 1) {
      configurationPath = configurationPaths.single;
      File file = new File(configurationPath);
      if (await file.exists()) {
        // If [configurationPath] exists as a file, use the absolute URI. This
        // handles absolute paths on Windows.
        configurationPath = file.absolute.uri.toString();
      }
    } else {
      configurationPath = "testing.json";
      if (!await new File(configurationPath).exists()) {
        Directory test = new Directory("test");
        if (await test.exists()) {
          List<FileSystemEntity> candidates = await test
              .list(recursive: true, followLinks: false)
              .where((FileSystemEntity entity) {
            return entity is File && entity.uri.path.endsWith("/testing.json");
          }).toList();
          switch (candidates.length) {
            case 0:
              return fail("Couldn't locate: '$configurationPath'.");

            case 1:
              configurationPath = candidates.single.path;
              break;

            default:
              return fail(
                  "Usage: run_tests.dart [$configPrefix=configuration_file]\n"
                  "Where configuration_file is one of:\n  "
                  "${candidates.map((file) => file.path).join('\n  ')}");
          }
        }
      }
    }
    const StdoutLogger()
        .logMessage("Reading configuration file '$configurationPath'.");
    Uri? configuration =
        await Isolate.resolvePackageUri(Uri.base.resolve(configurationPath));
    if (configuration == null ||
        !await new File.fromUri(configuration).exists()) {
      return fail("Couldn't locate: '$configurationPath'.");
    }
    return configuration;
  }

  static CommandLine parse(List<String> arguments) {
    int index = arguments.indexOf("--");
    Set<String> options;
    if (index != -1) {
      options = new Set<String>.from(arguments.getRange(0, index));
      arguments = arguments.sublist(index + 1);
    } else {
      options = arguments.where((argument) => argument.startsWith("-")).toSet();
      arguments =
          arguments.where((argument) => !argument.startsWith("-")).toList();
    }
    return new CommandLine(options, arguments);
  }
}

fail(String message) {
  print(message);
  io.exitCode = 1;
  return null;
}

main(List<String> arguments) => withErrorHandling(() async {
      CommandLine cl = CommandLine.parse(arguments);
      if (cl.verbose) {
        enableVerboseOutput();
      }
      Map<String, String> environment = cl.environment;
      Uri? configuration = await cl.configuration;
      if (configuration == null) return;
      if (!isVerbose) {
        print("Use --verbose to display more details.");
      }
      TestRoot root = await TestRoot.fromUri(configuration);
      SuiteRunner runner = new SuiteRunner(
          root.suites, environment, cl.selectors, cl.selectedSuites, cl.skip);
      String? program = await runner.generateDartProgram();
      bool hasAnalyzerSuites = await runner.analyze(root.packages);
      Stopwatch sw = new Stopwatch()..start();
      if (program == null) {
        if (!hasAnalyzerSuites) {
          fail("No tests configured.");
        }
      } else {
        await runProgram(program, root.packages);
      }
      print("Running tests took: ${sw.elapsed}.");
    });

Future<void> runTests(Map<String, Function> tests) =>
    withErrorHandling<void>(() async {
      int completed = 0;
      for (String name in tests.keys) {
        const StdoutLogger()
            .logTestStart(completed, 0, tests.length, null, null);
        StringBuffer sb = new StringBuffer();
        try {
          await runGuarded(() {
            print("Running test $name");
            return tests[name]!();
          }, printLineOnStdout: sb.writeln);
          const StdoutLogger().logMessage(sb);
        } catch (e) {
          print(sb);
          rethrow;
        }
        const StdoutLogger()
            .logTestComplete(++completed, 0, tests.length, null, null);
      }
    });
