// Copyright 2020 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:io';
import 'package:fxutils/fxutils.dart';
import 'package:meta/meta.dart';

/// Re-entry helper for running other fx subcommands from within any subcommand
/// written in Dart.
///
/// [Fx] instances are source-tree aware (via [RootLocator]), and launch
/// processes via a helper [startProcess].
///
/// Usage:
/// ```dart
/// final fx = Fx();
///
/// // Run prepared commands
/// final deviceName = await fx.getDeviceName();
///
/// // Run custom, specific commands.
/// // This runs `fx some-command`.
/// final output = await fx.getSubCommandOutput('some-command');
/// ```
class Fx {
  final FxEnv fxEnv;
  final ProcessLauncher _processLauncher;
  Fx({
    @required this.fxEnv,
    StartProcess processStarter,
  }) : _processLauncher = ProcessLauncher(processStarter: processStarter);

  factory Fx.mock(Process process, [FxEnv fxEnv]) => Fx(
        processStarter: returnGivenProcess(process),
        fxEnv: fxEnv,
      );

  Future<String> getDeviceName() async {
    return await getSubCommandOutput('get-device');
  }

  Future<bool> isPackageServerRunning() async {
    try {
      await getSubCommandOutput('is-package-server-running');
    } on FailedProcessException {
      return false;
    }
    return true;
  }

  Future<bool> updateIfInBase(
    Iterable<String> testNames, {
    int batchSize = 50,
  }) async {
    final testNamesIterator = ListIterator<String>.from(testNames);
    while (testNamesIterator.isNotEmpty) {
      final result = await runFxSubCommand(
        'update-if-in-base',
        args: testNamesIterator.take(batchSize),
      );
      if (result.exitCode != 0) {
        return false;
      }
    }
    return true;
  }

  /// Helper which invokes a command and returns the response.
  ///
  /// Intentionally offers no realtime access to output, or to the stderr. This
  /// is meant to simplify the task of getting output from an fx subcommand.
  Future<String> getSubCommandOutput(
    /// fx subcommand to execute. For example, "device-name", "status", etc.
    String cmd, {

    /// Optional list of arguments to pass to the subcommand.
    List<String> args,

    /// Accepted exit codes. Unexpected exit codes will throw a
    /// [FailedProcessException]. Set this to [null] to never throw an
    /// exception.
    List<int> allowedExitCodes = const [0],

    /// Convenience flag to remove trailing whitespace from the command, since
    /// that is unlikely to be desired.
    bool shouldTrimTrailing = true,
  }) async {
    final processResult = await runFxSubCommand(
      cmd,
      args: args,
    );
    if (allowedExitCodes != null &&
        !allowedExitCodes.contains(processResult.exitCode)) {
      final fullCommand = [fxEnv.fx, cmd, ...?args];
      throw FailedProcessException(
        command: fullCommand,
        exitCode: processResult.exitCode,
        stdout: processResult.stdout,
        stderr: processResult.stderr,
      );
    }
    return shouldTrimTrailing
        // ignore: avoid_as
        ? (processResult.stdout as String).trimRight()
        : processResult.stdout;
  }

  /// Basic wrapper around running an fx subcommand which exposes all necessary
  /// controls to the caller.
  Future<ProcessResult> runFxSubCommand(
    /// Specific `fx` subcommand to execute.
    String cmd, {

    /// Argument and flags for the subcommand. Optional.
    List<String> args,

    /// I/O mode of the spawned process. Defaults to
    /// [ProcessStartMode.inheritStdio] if unset and if [stdoutSink] and
    /// [stderrSink] are null.
    ProcessStartMode mode = ProcessStartMode.normal,

    // /// Handler for converting raw bytes into readable strings
    SystemEncoding encoding = systemEncoding,
  }) async {
    return _processLauncher.run(
      fxEnv.fx,
      [cmd, ...?args],
      mode: mode,
      outputEncoding: encoding,
    );
  }
}
