// Copyright 2013 The Flutter 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:args/args.dart';
import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:fuchsia_ctl/fuchsia_ctl.dart';
import 'package:path/path.dart' as path;
import 'package:retry/retry.dart';
import 'package:uuid/uuid.dart';

typedef AsyncResult = Future<OperationResult> Function(String, FFX, ArgResults);

const Map<String, AsyncResult> commands = <String, AsyncResult>{
  'emu': emulator,
  'pave': pave,
  'pm': pm,
  'ssh': ssh,
  'test': test,
  'push-packages': pushPackages,
};

Future<void> main(List<String> args) async {
  if (!Platform.isLinux) {
    throw UnsupportedError('This tool only supports Linux.');
  }

  final ArgParser parser = ArgParser();
  parser
    ..addOption('device-name',
        abbr: 'd',
        help: 'The device node name to use. '
            'If not specified, the first discoverable device will be used.')
    ..addOption('ffx-path',
        defaultsTo: './ffx', help: 'The path to the ffx executable.')
    ..addFlag('help', defaultsTo: false, help: 'Prints help.');

  /// This is a blocking command and will run until exited.
  parser.addCommand('emu')
    ..addOption('image', help: 'Fuchsia image to run')
    ..addOption('zbi', help: 'Bootloader image to sign and run')
    ..addOption('qemu-kernel', help: 'QEMU kernel to run')
    ..addOption('window-size', help: 'Emulator window size formatted "WxH"')
    ..addOption('aemu', help: 'AEMU executable path')
    ..addOption('sdk',
        help: 'Location to Fuchsia SDK containing tools and images')
    ..addOption('public-key',
        defaultsTo: '.fuchsia/authorized_keys',
        help: 'Path to the authorized_keys to sign zbi image with')
    ..addFlag('headless', help: 'Run FEMU without graphical window');

  parser.addCommand('ssh')
    ..addFlag('interactive',
        abbr: 'i',
        help: 'Whether to ssh in interactive mode. '
            'If --comand is specified, this is ignored.')
    ..addOption('command',
        abbr: 'c',
        help: 'The command to run on the device. '
            'If specified, --interactive is ignored.')
    ..addOption('identity-file',
        defaultsTo: '.ssh/pkey', help: 'The key to use when SSHing.')
    ..addOption('timeout-seconds',
        defaultsTo: '120', help: 'Ssh command timeout in seconds.')
    ..addOption('log-file',
        defaultsTo: '', help: 'The file to write stdout and stderr.');
  parser.addCommand('pave')
    ..addOption('public-key',
        abbr: 'p', help: 'The public key to add to authorized_keys.')
    ..addOption('image',
        abbr: 'i', help: 'The system image tgz to unpack and pave.');

  final ArgParser pmSubCommand = parser.addCommand('pm')
    ..addOption('pm-path',
        defaultsTo: './pm', help: 'The path to the pm executable.')
    ..addOption('repo',
        abbr: 'r',
        help: 'The location of the repository folder to create, '
            'publish, or serve.')
    ..addCommand('serve')
    ..addCommand('newRepo');
  pmSubCommand
      .addCommand('publishRepo')
      .addMultiOption('far', abbr: 'f', help: 'The .far files to publish.');

  parser.addCommand('push-packages')
    ..addOption('pm-path',
        defaultsTo: './pm', help: 'The path to the pm executable.')
    ..addOption('repoArchive', help: 'The path to the repo tar.gz archive.')
    ..addOption('identity-file',
        defaultsTo: '.ssh/pkey', help: 'The key to use when SSHing.')
    ..addMultiOption('packages',
        abbr: 'p',
        help: 'Packages from the repo that need to be pushed to the device.');

  parser.addCommand('test')
    ..addOption('pm-path',
        defaultsTo: './pm', help: 'The path to the pm executable.')
    ..addOption('identity-file',
        defaultsTo: '.ssh/pkey', help: 'The key to use when SSHing.')
    ..addOption('target',
        abbr: 't', help: 'The name of the target to pass to runtests.')
    ..addOption('arguments',
        abbr: 'a',
        help: 'Command line arguments to pass when invoking the tests')
    ..addMultiOption('far',
        abbr: 'f', help: 'The .far files to include for the test.')
    ..addOption('timeout-seconds',
        defaultsTo: '120', help: 'Test timeout in seconds.')
    ..addOption('packages-directory', help: 'amber files directory.');

  final ArgResults results = parser.parse(args);

  if (results.command == null) {
    stderr.writeln('Unknown command, expected one of: ${parser.commands.keys}');
    stderr.writeln(parser.usage);
    exit(-1);
  }

  if (results['help']) {
    stderr.writeln(parser.commands[results.command.name].usage);
    exit(0);
  }

  final AsyncResult command = commands[results.command.name];
  if (command == null) {
    stderr.writeln('Unknown command ${results.command.name}.');
    stderr.writeln(parser.usage);
    exit(-1);
  }
  final OperationResult result = await command(
    results['device-name'],
    FFX(results['ffx-path']),
    results.command,
  );
  if (!result.success) {
    exit(-1);
  }
}

Future<OperationResult> emulator(
  String deviceName,
  FFX ffx,
  ArgResults args,
) async {
  final Emulator emulator = Emulator(
    aemuPath: args['aemu'],
    fuchsiaImagePath: args['image'],
    fuchsiaSdkPath: args['sdk'],
    qemuKernelPath: args['qemu-kernel'],
    sshKeyManager: SystemSshKeyManager.defaultProvider(
      publicKeyPath: args['public-key'],
    ),
    zbiPath: args['zbi'],
  );
  await emulator.prepareEnvironment();

  return emulator.start(
    headless: args['headless'],
    windowSize: args['window-size'],
  );
}

Future<OperationResult> ssh(
  String deviceName,
  FFX ffx,
  ArgResults args,
) async {
  const SshClient sshClient = SshClient();
  final String targetIp = await ffx.getTargetAddress(deviceName);
  final String identityFile = args['identity-file'];
  final String outputFile = args['log-file'];
  if (args['interactive']) {
    return sshClient.interactive(
      targetIp,
      identityFilePath: identityFile,
    );
  }
  final OperationResult result = await sshClient.runCommand(
    targetIp,
    identityFilePath: identityFile,
    command: (args['command'] as String).split(' '),
    timeoutMs:
        Duration(milliseconds: int.parse(args['timeout-seconds']) * 1000),
    logFilePath: outputFile,
  );
  stdout.writeln(
      '==================================== STDOUT ====================================');
  stdout.writeln(result.info);
  stderr.writeln(
      '==================================== STDERR ====================================');
  stderr.writeln(result.error);
  return result;
}

Future<OperationResult> pave(
  String deviceName,
  FFX ffx,
  ArgResults args,
) async {
  const ImagePaver paver = ImagePaver();
  const RetryOptions r = RetryOptions(
    maxAttempts: 3,
  );
  return r.retry(() async {
    final OperationResult result = await paver.pave(
      args['image'],
      deviceName,
      publicKeyPath: args['public-key'],
    );
    if (!result.success) {
      throw RetryException('Exit code different from 0', result);
    }
    return result;
  }, retryIf: (Exception e) => e is RetryException);
}

Future<OperationResult> pm(
  String deviceName,
  FFX ffx,
  ArgResults args,
) async {
  final PackageServer server = PackageServer(args['pm-path']);
  switch (args.command.name) {
    case 'serve':
      await server.serveRepo(args['repo']);
      await Future<void>.delayed(const Duration(seconds: 15));
      return server.close();
    case 'newRepo':
      return server.newRepo(args['repo']);
    case 'publishRepo':
      return server.publishRepo(args['repo'], args['far']);
    default:
      throw ArgumentError('Command ${args.command.name} unknown.');
  }
}

Future<OperationResult> pushPackages(
  String deviceName,
  FFX ffx,
  ArgResults args,
) async {
  final PackageServer server = PackageServer(args['pm-path']);
  final String repoArchive = args['repoArchive'];
  final List<String> packages = args['packages'];
  final String identityFile = args['identity-file'];

  const FileSystem fs = LocalFileSystem();
  final String uuid = const Uuid().v4();
  final Directory repo = fs.systemTempDirectory.childDirectory('repo_$uuid');
  const Tar tar = SystemTar();
  try {
    final String targetIp = await ffx.getTargetAddress(deviceName);
    final AmberCtl amberCtl = AmberCtl(targetIp, identityFile);

    stdout.writeln('Untaring $repoArchive to ${repo.path}');
    repo.createSync(recursive: true);
    final OperationResult result = await tar.untar(repoArchive, repo.path);
    if (!result.success) {
      stdout.writeln(
          'Error untarring $repoArchive \nstdout: ${result.info} \nstderr: ${result.error}');
      exit(-1);
    }

    final String repositoryBase = path.join(repo.path, 'amber-files');
    stdout.writeln('Serving $repositoryBase to $targetIp');
    await server.serveRepo(repositoryBase);
    await amberCtl.addSrc(server.serverPort);

    stdout.writeln('Pushing packages $packages to $targetIp');
    for (final String packageName in packages) {
      stdout.writeln('Attempting to add package $packageName.');
      await amberCtl.addPackage(packageName);
    }

    return OperationResult.success(
        info: 'Successfully pushed $packages to $targetIp.');
  } finally {
    // We may not have created the repo if ffx errored first.
    if (repo.existsSync()) {
      repo.deleteSync(recursive: true);
    }
    if (server.serving) {
      await server.close();
    }
  }
}

Future<OperationResult> test(
  String deviceName,
  FFX ffx,
  ArgResults args,
) async {
  const FileSystem fs = LocalFileSystem();
  final String identityFile = args['identity-file'];

  //final PackageServer server = PackageServer(args['pm-path']);
  PackageServer server;
  const SshClient ssh = SshClient();
  final List<String> farFiles = args['far'];
  final String target = args['target'];
  final String arguments = args['arguments'];
  Directory repo;
  if (args['packages-directory'] == null) {
    final String uuid = const Uuid().v4();
    repo = fs.systemTempDirectory.childDirectory('repo_$uuid');
    server = PackageServer(args['pm-path']);
  } else {
    final String amberFilesPath = path.join(
      args['packages-directory'],
      'amber-files',
    );
    final String pmPath = path.join(
      args['packages-directory'],
      'pm',
    );
    repo = fs.directory(amberFilesPath);
    server = PackageServer(pmPath);
  }

  try {
    final String targetIp = await ffx.getTargetAddress(deviceName);
    final AmberCtl amberCtl = AmberCtl(targetIp, identityFile);
    OperationResult result;
    stdout.writeln('Using ${repo.path} as repo to serve to $targetIp...');
    if (!repo.existsSync()) {
      repo.createSync(recursive: true);
      result = await server.newRepo(repo.path);
      if (!result.success) {
        stderr.writeln('Failed to create repo at $repo.');
        return result;
      }
    }
    await server.serveRepo(repo.path);
    await amberCtl.addSrc(server.serverPort);

    for (final String farFile in farFiles) {
      result = await server.publishRepo(repo.path, farFile);
      if (!result.success) {
        stderr.writeln('Failed to publish repo at $repo with $farFiles.');
        stderr.writeln(result.error);
        return result;
      }
      final RegExp r = RegExp(r'\-0.far|.far');
      final String packageName = fs.file(farFile).basename.replaceFirst(r, '');
      await amberCtl.addPackage(packageName);
    }

    final OperationResult testResult = await ssh.runCommand(
      targetIp,
      identityFilePath: identityFile,
      command: <String>[
        'run',
        'fuchsia-pkg://fuchsia.com/$target#meta/$target.cmx',
        arguments
      ],
      timeoutMs:
          Duration(milliseconds: int.parse(args['timeout-seconds']) * 1000),
    );
    stdout.writeln('Test results (passed: ${testResult.success}):');
    if (result.info != null) {
      stdout.writeln(testResult.info);
    }
    if (result.error != null) {
      stderr.writeln(testResult.error);
    }
    return testResult;
  } finally {
    // We may not have created the repo if ffx errored first.
    if (repo.existsSync() && args['packages-directory'] != null) {
      repo.deleteSync(recursive: true);
    }
    if (server.serving) {
      await server.close();
    }
  }
}

/// The exception thrown when an operation needs a retry.
class RetryException implements Exception {
  /// Creates a new [RetryException] using the specified [cause] and [result]
  /// to force a retry.
  const RetryException(this.cause, this.result);

  /// The user-facing message to display.
  final String cause;

  /// Contains the result of the executed target command.
  final OperationResult result;

  @override
  String toString() =>
      '$runtimeType, cause: "$cause", underlying exception: $result.';
}
