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