// Copyright 2014 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:async';

import '../base/file_system.dart';
import '../base/io.dart';
import '../base/platform.dart';
import '../convert.dart';
import '../globals.dart' as globals;

import 'fuchsia_ffx.dart';
import 'fuchsia_kernel_compiler.dart';
import 'fuchsia_pm.dart';

/// Returns [true] if the current platform supports Fuchsia targets.
bool isFuchsiaSupportedPlatform(Platform platform) {
  return platform.isLinux || platform.isMacOS;
}

/// The Fuchsia SDK shell commands.
///
/// This workflow assumes development within the fuchsia source tree,
/// including a working fx command-line tool in the user's PATH.
class FuchsiaSdk {
  /// Interface to the 'pm' tool.
  late final FuchsiaPM fuchsiaPM = FuchsiaPM();

  /// Interface to the 'kernel_compiler' tool.
  late final FuchsiaKernelCompiler fuchsiaKernelCompiler = FuchsiaKernelCompiler();

  /// Interface to the 'ffx' tool.
  late final FuchsiaFfx fuchsiaFfx = FuchsiaFfx();

  /// Returns any attached devices is a newline-denominated String.
  ///
  /// Example output: abcd::abcd:abc:abcd:abcd%qemu scare-cable-skip-joy
  Future<String?> listDevices({Duration? timeout}) async {
    final File? ffx = globals.fuchsiaArtifacts?.ffx;
    if (ffx == null || !ffx.existsSync()) {
      return null;
    }
    final List<String>? devices = await fuchsiaFfx.list(timeout: timeout);
    if (devices == null) {
      return null;
    }
    return devices.isNotEmpty ? devices.join('\n') : null;
  }

  /// Returns the fuchsia system logs for an attached device where
  /// [id] is the IP address of the device.
  Stream<String>? syslogs(String id) {
    Process? process;
    try {
      final StreamController<String> controller = StreamController<String>(onCancel: () {
        process?.kill();
      });
      final File? sshConfig = globals.fuchsiaArtifacts?.sshConfig;
      if (sshConfig == null || !sshConfig.existsSync()) {
        globals.printError('Cannot read device logs: No ssh config.');
        globals.printError('Have you set FUCHSIA_SSH_CONFIG or FUCHSIA_BUILD_DIR?');
        return null;
      }
      const String remoteCommand = 'log_listener --clock Local';
      final List<String> cmd = <String>[
        'ssh',
        '-F',
        sshConfig.absolute.path,
        id, // The device's IP.
        remoteCommand,
      ];
      globals.processManager.start(cmd).then((Process newProcess) {
        if (controller.isClosed) {
          return;
        }
        process = newProcess;
        process?.exitCode.whenComplete(controller.close);
        controller.addStream(process!.stdout
            .transform(utf8.decoder)
            .transform(const LineSplitter()));
      });
      return controller.stream;
    } on Exception catch (exception) {
      globals.printTrace('$exception');
    }
    return const Stream<String>.empty();
  }
}

/// Fuchsia-specific artifacts used to interact with a device.
class FuchsiaArtifacts {
  /// Creates a new [FuchsiaArtifacts].
  FuchsiaArtifacts({
    this.sshConfig,
    this.ffx,
    this.pm,
  });

  /// Creates a new [FuchsiaArtifacts] using the cached Fuchsia SDK.
  ///
  /// Finds tools under bin/cache/artifacts/fuchsia/tools.
  /// Queries environment variables (first FUCHSIA_BUILD_DIR, then
  /// FUCHSIA_SSH_CONFIG) to find the ssh configuration needed to talk to
  /// a device.
  factory FuchsiaArtifacts.find() {
    if (!isFuchsiaSupportedPlatform(globals.platform)) {
      // Don't try to find the artifacts on platforms that are not supported.
      return FuchsiaArtifacts();
    }
    // If FUCHSIA_BUILD_DIR is defined, then look for the ssh_config dir
    // relative to it. Next, if FUCHSIA_SSH_CONFIG is defined, then use it.
    // TODO(zanderso): Consider passing the ssh config path in with a flag.
    File? sshConfig;
    if (globals.platform.environment.containsKey(_kFuchsiaBuildDir)) {
      sshConfig = globals.fs.file(globals.fs.path.join(
          globals.platform.environment[_kFuchsiaBuildDir]!, 'ssh-keys', 'ssh_config'));
    } else if (globals.platform.environment.containsKey(_kFuchsiaSshConfig)) {
      sshConfig = globals.fs.file(globals.platform.environment[_kFuchsiaSshConfig]);
    }

    final String fuchsia = globals.cache.getArtifactDirectory('fuchsia').path;
    final String tools = globals.fs.path.join(fuchsia, 'tools');
    final File ffx = globals.fs.file(globals.fs.path.join(tools, 'x64/ffx'));
    final File pm = globals.fs.file(globals.fs.path.join(tools, 'pm'));

    return FuchsiaArtifacts(
      sshConfig: sshConfig,
      ffx: ffx.existsSync() ? ffx : null,
      pm: pm.existsSync() ? pm : null,
    );
  }

  static const String _kFuchsiaSshConfig = 'FUCHSIA_SSH_CONFIG';
  static const String _kFuchsiaBuildDir = 'FUCHSIA_BUILD_DIR';

  /// The location of the SSH configuration file used to interact with a
  /// Fuchsia device.
  final File? sshConfig;

  /// The location of the ffx tool used to locate connected
  /// Fuchsia devices.
  final File? ffx;

  /// The pm tool.
  final File? pm;

  /// Returns true if the [sshConfig] file is not null and exists.
  bool get hasSshConfig => sshConfig != null && sshConfig!.existsSync();
}
