// Copyright (c) 2021, 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 file.

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:path/path.dart' as path;
import 'package:pedantic/pedantic.dart';
import 'package:vm_service/vm_service.dart' as vm;

import '../logging.dart';
import '../protocol_generated.dart';
import '../protocol_stream.dart';
import 'dart.dart';
import 'mixins.dart';

/// A DAP Debug Adapter for running and debugging Dart CLI scripts.
class DartCliDebugAdapter extends DartDebugAdapter<DartLaunchRequestArguments,
        DartAttachRequestArguments>
    with PidTracker, VmServiceInfoFileUtils, PackageConfigUtils {
  Process? _process;

  @override
  final parseLaunchArgs = DartLaunchRequestArguments.fromJson;

  @override
  final parseAttachArgs = DartAttachRequestArguments.fromJson;

  DartCliDebugAdapter(
    ByteStreamServerChannel channel, {
    bool ipv6 = false,
    bool enableDds = true,
    bool enableAuthCodes = true,
    Logger? logger,
  }) : super(
          channel,
          ipv6: ipv6,
          enableDds: enableDds,
          enableAuthCodes: enableAuthCodes,
          logger: logger,
        ) {
    channel.closed.then((_) => shutdown());
  }

  /// Whether the VM Service closing should be used as a signal to terminate the
  /// debug session.
  ///
  /// If we have a process, we will instead use its termination as a signal to
  /// terminate the debug session. Otherwise, we will use the VM Service close.
  bool get terminateOnVmServiceClose => _process == null;

  Future<void> debuggerConnected(vm.VM vmInfo) async {
    if (!isAttach) {
      // Capture the PID from the VM Service so that we can terminate it when
      // cleaning up. Terminating the process might not be enough as it could be
      // just a shell script (e.g. pub on Windows) and may not pass the
      // signal on correctly.
      // See: https://github.com/Dart-Code/Dart-Code/issues/907
      final pid = vmInfo.pid;
      if (pid != null) {
        pidsToTerminate.add(pid);
      }
    }
  }

  /// Called by [disconnectRequest] to request that we forcefully shut down the
  /// app being run (or in the case of an attach, disconnect).
  Future<void> disconnectImpl() async {
    terminatePids(ProcessSignal.sigkill);
  }

  /// Called by [launchRequest] to request that we actually start the app to be
  /// run/debugged.
  ///
  /// For debugging, this should start paused, connect to the VM Service, set
  /// breakpoints, and resume.
  Future<void> launchImpl() async {
    final args = this.args as DartLaunchRequestArguments;
    final vmPath = Platform.resolvedExecutable;
    File? vmServiceInfoFile;

    final debug = !(args.noDebug ?? false);
    if (debug) {
      vmServiceInfoFile = generateVmServiceInfoFile();
      unawaited(waitForVmServiceInfoFile(logger, vmServiceInfoFile)
          .then((uri) => connectDebugger(uri, resumeIfStarting: true)));
    }

    final vmArgs = <String>[
      if (debug) ...[
        '--enable-vm-service=${args.vmServicePort ?? 0}${ipv6 ? '/::1' : ''}',
        '--pause_isolates_on_start',
        if (!enableAuthCodes) '--disable-service-auth-codes'
      ],
      '--disable-dart-dev',
      if (debug && vmServiceInfoFile != null) ...[
        '-DSILENT_OBSERVATORY=true',
        '--write-service-info=${Uri.file(vmServiceInfoFile.path)}'
      ],
      // Default to asserts on, this seems like the most useful behaviour for
      // editor-spawned debug sessions.
      if (args.enableAsserts ?? true) '--enable-asserts',
    ];
    final processArgs = [
      ...vmArgs,
      ...?args.toolArgs,
      args.program,
      ...?args.args,
    ];

    // Find the package_config file for this script.
    // TODO(dantup): Remove this once
    //   https://github.com/dart-lang/sdk/issues/45530 is done as it will not be
    //   necessary.
    var possibleRoot = path.isAbsolute(args.program)
        ? path.dirname(args.program)
        : path.dirname(path.normalize(path.join(args.cwd ?? '', args.program)));
    final packageConfig = findPackageConfigFile(possibleRoot);
    if (packageConfig != null) {
      this.usePackageConfigFile(packageConfig);
    }

    // If the client supports runInTerminal and args.console is set to either
    // 'terminal' or 'runInTerminal' we won't run the process ourselves, but
    // instead call the client to run it for us (this allows it to run in a
    // terminal where the user can interact with `stdin`).
    final canRunInTerminal =
        initializeArgs?.supportsRunInTerminalRequest ?? false;

    // The terminal kinds used by DAP are 'integrated' and 'external'.
    final terminalKind = canRunInTerminal
        ? args.console == 'terminal'
            ? 'integrated'
            : args.console == 'externalTerminal'
                ? 'external'
                : null
        : null;

    // TODO(dantup): Support passing env to both of these.

    if (terminalKind != null) {
      await launchInEditorTerminal(debug, terminalKind, vmPath, processArgs);
    } else {
      await launchAsProcess(vmPath, processArgs);
    }
  }

  /// Called by [attachRequest] to request that we actually connect to the app
  /// to be debugged.
  Future<void> attachImpl() async {
    final args = this.args as DartAttachRequestArguments;
    final vmServiceUri = args.vmServiceUri;
    final vmServiceInfoFile = args.vmServiceInfoFile;

    if ((vmServiceUri == null) == (vmServiceInfoFile == null)) {
      sendOutput(
        'console',
        '\nTo attach, provide exactly one of vmServiceUri/vmServiceInfoFile',
      );
      handleSessionTerminate();
      return;
    }

    // Find the package_config file for this script.
    // TODO(dantup): Remove this once
    //   https://github.com/dart-lang/sdk/issues/45530 is done as it will not be
    //   necessary.
    final cwd = args.cwd;
    if (cwd != null) {
      final packageConfig = findPackageConfigFile(cwd);
      if (packageConfig != null) {
        this.usePackageConfigFile(packageConfig);
      }
    }

    final uri = vmServiceUri != null
        ? Uri.parse(vmServiceUri)
        : await waitForVmServiceInfoFile(logger, File(vmServiceInfoFile!));

    unawaited(connectDebugger(uri, resumeIfStarting: false));
  }

  /// Calls the client (via a `runInTerminal` request) to spawn the process so
  /// that it can run in a local terminal that the user can interact with.
  Future<void> launchInEditorTerminal(
    bool debug,
    String terminalKind,
    String vmPath,
    List<String> processArgs,
  ) async {
    final args = this.args as DartLaunchRequestArguments;
    logger?.call('Spawning $vmPath with $processArgs in ${args.cwd}'
        ' via client ${terminalKind} terminal');

    // runInTerminal is a DAP request that goes from server-to-client that
    // allows the DA to ask the client editor to run the debugee for us. In this
    // case we will have no access to the process (although we get the PID) so
    // for debugging will rely on the process writing the service-info file that
    // we can detect with the normal watching code.
    final requestArgs = RunInTerminalRequestArguments(
      args: [vmPath, ...processArgs],
      cwd: args.cwd ?? path.dirname(args.program),
      kind: terminalKind,
      title: args.name ?? 'Dart',
    );
    try {
      final response = await sendRequest(requestArgs);
      final body =
          RunInTerminalResponseBody.fromJson(response as Map<String, Object?>);
      logger?.call(
        'Client spawned process'
        ' (proc: ${body.processId}, shell: ${body.shellProcessId})',
      );
    } catch (e) {
      logger?.call('Client failed to spawn process $e');
      sendOutput('console', '\nFailed to spawn process: $e');
      handleSessionTerminate();
    }

    // When using `runInTerminal` and `noDebug`, we will not connect to the VM
    // Service so we will have no way of knowing when the process completes, so
    // we just send the termination event right away.
    if (!debug) {
      handleSessionTerminate();
    }
  }

  /// Launches the program as a process controlled by the debug adapter.
  ///
  /// Output to `stdout`/`stderr` will be sent to the editor using
  /// [OutputEvent]s.
  Future<void> launchAsProcess(String vmPath, List<String> processArgs) async {
    logger?.call('Spawning $vmPath with $processArgs in ${args.cwd}');
    final process = await Process.start(
      vmPath,
      processArgs,
      workingDirectory: args.cwd,
    );
    _process = process;
    pidsToTerminate.add(process.pid);

    process.stdout.listen(_handleStdout);
    process.stderr.listen(_handleStderr);
    unawaited(process.exitCode.then(_handleExitCode));
  }

  /// Called by [terminateRequest] to request that we gracefully shut down the
  /// app being run (or in the case of an attach, disconnect).
  Future<void> terminateImpl() async {
    terminatePids(ProcessSignal.sigint);
    await _process?.exitCode;
  }

  void _handleExitCode(int code) {
    final codeSuffix = code == 0 ? '' : ' ($code)';
    logger?.call('Process exited ($code)');
    handleSessionTerminate(codeSuffix);
  }

  void _handleStderr(List<int> data) {
    sendOutput('stderr', utf8.decode(data));
  }

  void _handleStdout(List<int> data) {
    sendOutput('stdout', utf8.decode(data));
  }
}
