// Copyright 2019 The Fuchsia Authors. 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:fxtest/fxtest.dart';
import 'package:io/ansi.dart';
import 'package:meta/meta.dart';

import 'exit_code.dart';

/// Main entry-point for all Fuchsia tests, both host and on-device.
///
/// [FuchsiaTestCommand] receives a combination of test names and feature flags,
/// and due to the nature of Fuchsia tests, needs to run each passed test name
/// against the full set of feature flags. For example, if the way to invoke
/// this command is `fx test <...args>`, and the developer executes
/// `... test1 test2 -flag1 -flag2`, the desired behavior for our user lies
/// behind pretending the user entered `... test1 -flag1 -flag2` and
/// `... test2 -flag1 flag2` separately. Note that the individual tests indicated
/// by these two imaginary commands are then rolled back into one singular test
/// suite, so end users will be none the wiser.
///
/// The following is a high level road map of how [FuchsiaTestCommand] works:
///
///  - Parse commands into testNames and flags
///  - Produce a list of each individual `testName` paired with all provided flags
///     - loop over this list `testName` and flag combinations, matching tests
///       out of `out/default/tests.json`
///     - Load each matching test's raw JSON into a [TestDefinition] instance which
///       handles determining all the runtime invocation details for a given test
///  - Loop over the list of [TestDefinition] instances, listening to emitted
///    [TestEvent] instances with a [FormattedOutput] class
///     - Every time a [TestEvent] instance is emitted, our [FormattedOutput]
///       class captures it and flushes appropriate text to [stdout].
///  - Once the [TestDefinition] list has been completely processed, flush any
///    captured stderr from individual test processes to show errors / stacktraces
class FuchsiaTestCommand {
  // ignore: close_sinks
  final _eventStreamController = StreamController<TestEvent>();

  final AnalyticsReporter analyticsReporter;

  /// Bundle of configuration options for this invocation.
  final TestsConfig testsConfig;

  /// Translators between [TestEvent] instances and output for the user.
  final List<OutputFormatter> outputFormatters;

  /// Function that yields disposable wrappers around tests and [Process]
  /// instances.
  final TestRunner Function(TestsConfig) testRunnerBuilder;

  /// Helper which verifies that we actually want to run tests (not a dry run,
  /// for example) and are set up to even be successful (device and package
  /// server are available, for example).
  final Checklist checklist;

  final ExitCodeSetter _exitCodeSetter;

  /// Used to create any new directories needed to house test output / artifacts.
  final DirectoryBuilder directoryBuilder;

  int _numberOfTests;

  FuchsiaTestCommand({
    @required this.analyticsReporter,
    @required this.outputFormatters,
    @required this.checklist,
    @required this.testsConfig,
    @required this.testRunnerBuilder,
    @required this.directoryBuilder,
    ExitCodeSetter exitCodeSetter,
  })  : _exitCodeSetter = exitCodeSetter ?? setExitCode,
        _numberOfTests = 0 {
    if (outputFormatters == null || outputFormatters.isEmpty) {
      throw AssertionError('Must provide at least one OutputFormatter');
    }
    stream.listen((output) {
      for (var formatter in outputFormatters) {
        formatter.update(output);
      }
    });
  }

  factory FuchsiaTestCommand.fromConfig(
    TestsConfig testsConfig, {
    @required TestRunner Function(TestsConfig) testRunnerBuilder,
    DirectoryBuilder directoryBuilder,
    ExitCodeSetter exitCodeSetter,
    OutputFormatter outputFormatter,
  }) {
    var _outputFormatter =
        outputFormatter ?? OutputFormatter.fromConfig(testsConfig);
    var _fileFormatter = FileFormatter.fromConfig(testsConfig);
    return FuchsiaTestCommand(
      analyticsReporter: testsConfig.flags.dryRun
          ? AnalyticsReporter.noop()
          : AnalyticsReporter(fxEnv: testsConfig.fxEnv),
      checklist: PreChecker.fromConfig(
        testsConfig,
        eventSink: _outputFormatter.update,
      ),
      directoryBuilder: directoryBuilder ?? (path, {recursive}) => null,
      outputFormatters: [
        _outputFormatter,
        if (_fileFormatter != null) _fileFormatter
      ],
      testRunnerBuilder: testRunnerBuilder,
      testsConfig: testsConfig,
      exitCodeSetter: exitCodeSetter,
    );
  }

  Stream<TestEvent> get stream => _eventStreamController.stream;

  void emitEvent(TestEvent event) {
    if (!_eventStreamController.isClosed) {
      _eventStreamController.sink.add(event);
    }
  }

  void dispose() {
    for (var formatter in outputFormatters) {
      formatter.close();
    }
    _eventStreamController.close();
  }

  Future<void> runTestSuite([TestsManifestReader manifestReader]) async {
    manifestReader ??= TestsManifestReader();
    advertiseLogFile();
    var parsedManifest = await readManifest(manifestReader);

    manifestReader.reportOnTestBundles(
      userFriendlyBuildDir: testsConfig.fxEnv.userFriendlyOutputDir,
      eventEmitter: emitEvent,
      parsedManifest: parsedManifest,
      testsConfig: testsConfig,
    );

    if (parsedManifest.testBundles.isEmpty) {
      _exitCodeSetter(noTestFoundExitCode);
      return noMatchesHelp(
        manifestReader: manifestReader,
        testDefinitions: parsedManifest.testDefinitions,
        testsConfig: testsConfig,
      );
    }

    if (testsConfig.flags.shouldRandomizeTestOrder) {
      parsedManifest.testBundles.shuffle();
    }

    if (testsConfig.flags.shouldRebuild) {
      Set<String> buildArgs = TestBundle.calculateMinimalBuildTargets(
          testsConfig, parsedManifest.testBundles);
      emitEvent(TestInfo(testsConfig.wrapWith(
          '> fx build ${buildArgs?.join(' ') ?? ''}', [green, styleBold])));
      try {
        await fxCommandRun(testsConfig.fxEnv.fx, 'build', buildArgs?.toList());
      } on FxRunException {
        emitEvent(FatalError(
            '\'fx test\' could not perform a successful build. Try to run \'fx build\' manually or use the \'--no-build\' flag'));
        _exitCodeSetter(failureExitCode);
        return;
      }
      // Re-parse the manifest in case it has changed as a side effect of building
      parsedManifest = await readManifest(manifestReader);
    }

    try {
      // Let the output formatter know that we're done parsing and
      // emitting preliminary events
      emitEvent(BeginningTests());
      await runTests(parsedManifest.testBundles);
    } on FailFastException catch (_) {
      // Non-zero exit code indicates generic but fatal failure
      _exitCodeSetter(failureExitCode);
    }
    emitEvent(AllTestsCompleted());
  }

  Future<ParsedManifest> readManifest(
    TestsManifestReader manifestReader,
  ) async {
    List<TestDefinition> testDefinitions = await manifestReader.loadTestsJson(
      buildDir: testsConfig.fxEnv.outputDir,
      fxLocation: testsConfig.fxEnv.fx,
      manifestFileName: 'tests.json',
    );
    return manifestReader.aggregateTests(
      eventEmitter: emitEvent,
      matchLength: testsConfig.flags.matchLength,
      testBundleBuilder: testBundleBuilder,
      testDefinitions: testDefinitions,
      testsConfig: testsConfig,
    );
  }

  void noMatchesHelp({
    @required TestsManifestReader manifestReader,
    @required List<TestDefinition> testDefinitions,
    @required TestsConfig testsConfig,
  }) {
    emitEvent(GeneratingHintsEvent());
    emitEvent(TestInfo(
      testsConfig.wrapWith(
          'Could not find any tests to run with the '
          'arguments you provided.',
          [lightYellow]),
    ));
    var manifestOfHints = manifestReader.aggregateTests(
      comparer: FuzzyComparer(threshold: testsConfig.flags.fuzzyThreshold),
      eventEmitter: (TestEvent event) => null,
      matchLength: testsConfig.flags.matchLength,
      testBundleBuilder: testBundleBuilder,
      testDefinitions: testDefinitions,
      testsConfig: testsConfig,
    );
    if (manifestOfHints.testBundles.isNotEmpty) {
      manifestOfHints.testBundles.sort(
        (TestBundle bundle1, TestBundle bundle2) {
          return bundle1.confidence.compareTo(bundle2.confidence);
        },
      );
      var hints = manifestOfHints.testBundles.length > 1 ? 'hints' : 'hint';
      emitEvent(TestInfo(
        'Did you mean... (${manifestOfHints.testBundles.length} $hints)?',
        requiresPadding: false,
      ));
      for (TestBundle bundle in manifestOfHints.testBundles) {
        emitEvent(TestInfo(
          ' -- ${bundle.testDefinition.name}',
          requiresPadding: false,
        ));
      }
    } else {
      emitEvent(TestInfo(
        'Make sure this test is transitively in your \'fx set\' arguments. See https://fuchsia.dev/fuchsia-src/development/testing/faq for more information.',
        requiresPadding: false,
      ));
    }
  }

  TestBundle testBundleBuilder(
    TestDefinition testDefinition, [
    double confidence,
  ]) =>
      TestBundle.build(
        confidence: confidence ?? 1,
        directoryBuilder: directoryBuilder,
        fxPath: testsConfig.fxEnv.fx,
        realtimeOutputSink: (String val) => emitEvent(TestOutputEvent(val)),
        timeElapsedSink: (Duration duration, String cmd, String output) =>
            emitEvent(TimeElapsedEvent(duration, cmd, output)),
        testRunnerBuilder: testRunnerBuilder,
        testDefinition: testDefinition,
        testsConfig: testsConfig,
        workingDirectory: testsConfig.fxEnv.outputDir,
      );

  bool _maybeAddPackageHash(
      TestBundle testBundle, PackageRepository repository) {
    if (testsConfig.flags.shouldUsePackageHash &&
        testBundle.testDefinition.packageUrl != null) {
      if (repository == null) {
        emitEvent(TestResult(
            runtime: Duration(seconds: 0),
            exitCode: failureExitCode,
            message:
                'Package repository is not available. Run "fx serve-updates" again or use the "--no-use-package-hash" flag.',
            testName: testBundle.testDefinition.name));
        return false;
      } else {
        String packageName = testBundle.testDefinition.packageUrl.packageName;
        if (repository[packageName] == null) {
          emitEvent(TestResult(
              runtime: Duration(seconds: 0),
              exitCode: failureExitCode,
              message:
                  'Package $packageName is not in the package repository, check if it was correctly built or use the "--no-use-package-hash" flag.',
              testName: testBundle.testDefinition.name));
          return false;
        }
        testBundle.testDefinition.hash = repository[packageName].merkle;
      }
    }
    return true;
  }

  Future<void> runTests(List<TestBundle> testBundles) async {
    // Enforce a limit
    var _testBundles = testsConfig.flags.limit > 0 &&
            testsConfig.flags.limit < testBundles.length
        ? testBundles.sublist(0, testsConfig.flags.limit)
        : testBundles;
    if (!testsConfig.flags.infoOnly &&
        !await checklist.isDeviceReady(_testBundles)) {
      emitEvent(FatalError('Device is not ready for running device tests'));
      _exitCodeSetter(failureExitCode);
      return;
    }

    // set merkle root hash on component tests
    // TODO: This should not require checking if `buildDir != null`, as that is
    // a temporary workaround to get tests passing on CQ. The correct
    // implementation is to abstract file-reading just as we have process-launching.
    PackageRepository packageRepository;
    if (testsConfig.flags.shouldUsePackageHash &&
        testsConfig.fxEnv.outputDir != null) {
      packageRepository = await PackageRepository.fromManifest(
          buildDir: testsConfig.fxEnv.outputDir);
    }

    for (TestBundle testBundle in _testBundles) {
      if (!testsConfig.flags.infoOnly &&
          !_maybeAddPackageHash(testBundle, packageRepository)) {
        _exitCodeSetter(failureExitCode);
        continue;
      }
      try {
        await testBundle.run().forEach((TestEvent event) {
          emitEvent(event);
          if (event is FatalError) {
            _exitCodeSetter(failureExitCode);
          } else if (event is TestResult && !event.isSuccess) {
            _exitCodeSetter(event.exitCode ?? failureExitCode);
          }
        });
        _numberOfTests += 1;
      } on Exception catch (e) {
        throw FxRunException(
            'Exception in ${testBundle.testDefinition.name}: $e',
            failureExitCode);
      }
    }
  }

  /// Function guaranteed to be called at the end of execution, whether that is
  /// natural or the result of a SIGINT.
  Future<void> cleanUp() async {
    await _reportAnalytics();
  }

  Future<void> _reportAnalytics() async {
    final bool _actuallyRanTests = _numberOfTests != null && _numberOfTests > 0;
    if (!testsConfig.flags.dryRun && _actuallyRanTests) {
      await analyticsReporter.report(
        subcommand: 'test',
        action: 'number',
        label: '$_numberOfTests',
      );
    }
  }

  void advertiseLogFile() {
    for (var outputFormatter in outputFormatters) {
      if (outputFormatter is FileFormatter) {
        // ignore: avoid_as
        (outputFormatter.buffer.stdout as FileStandardOut).initPath();
        // ignore: avoid_as
        var path = (outputFormatter.buffer.stdout as FileStandardOut).path;
        emitEvent(TestInfo(testsConfig.wrapWith(
          'Logging all output to: $path\n'
          'Use the `--logpath` argument to specify a log location or '
          '`--no-log` to disable\n',
          [darkGray],
        )));
      }
    }
  }
}
