// 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 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 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) {
      fail("Only one --config option is supported");
      return null;
    }
    String configurationPath;
    if (configurationPaths.length == 1) {
      configurationPath = configurationPaths.single;
      File file = 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 File(configurationPath).exists()) {
        Directory test = 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:
              fail("Couldn't locate: '$configurationPath'.");
              return null;

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

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

  static CommandLine parse(List<String> arguments) {
    int index = arguments.indexOf("--");
    Set<String> options;
    if (index != -1) {
      options = 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 CommandLine(options, arguments);
  }
}

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

Future<void> main(List<String> arguments) {
  return 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 = SuiteRunner(
        root.suites, environment, cl.selectors, cl.selectedSuites, cl.skip);
    String? program = await runner.generateDartProgram();
    bool hasAnalyzerSuites = await runner.analyze(root.packages);
    Stopwatch sw = 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 = 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);
      }
    });
