// 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 'dart:convert';
import 'dart:io';

import 'package:dds/src/dap/logging.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/debug_adapters/server.dart';
import 'package:flutter_tools/src/globals.dart' as globals;

/// Enable to run from local source when running out-of-process (useful in
/// development to avoid having to keep rebuilding the flutter tool).
const bool _runFromSource = false;

abstract class DapTestServer {
  Future<void> stop();
  StreamSink<List<int>> get sink;
  Stream<List<int>> get stream;
  Function(String message)? onStderrOutput;
}

/// An instance of a DAP server running in-process (to aid debugging).
///
/// All communication still goes over the socket to ensure all messages are
/// serialized and deserialized but it's not quite the same running out of
/// process.
class InProcessDapTestServer extends DapTestServer {
  InProcessDapTestServer._(List<String> args) {
    _server = DapServer(
      stdinController.stream,
      stdoutController.sink,
      fileSystem: globals.fs,
      platform: globals.platform,
      // Simulate flags based on the args to aid testing.
      enableDds: !args.contains('--no-dds'),
      ipv6: args.contains('--ipv6'),
      test: args.contains('--test'),
    );
  }

  late final DapServer _server;
  final StreamController<List<int>> stdinController = StreamController<List<int>>();
  final StreamController<List<int>> stdoutController = StreamController<List<int>>();

  @override
  StreamSink<List<int>> get sink => stdinController.sink;

  @override
  Stream<List<int>> get stream => stdoutController.stream;

  @override
  Future<void> stop() async {
    _server.stop();
  }

  static Future<InProcessDapTestServer> create({
    Logger? logger,
    List<String>? additionalArgs,
  }) async {
    return InProcessDapTestServer._(additionalArgs ?? <String>[]);
  }
}

/// An instance of a DAP server running out-of-process.
///
/// This is how an editor will usually consume DAP so is a more accurate test
/// but will be a little more difficult to debug tests as the debugger will not
/// be attached to the process.
class OutOfProcessDapTestServer extends DapTestServer {
  OutOfProcessDapTestServer._(
    this._process,
    Logger? logger,
  ) {
    // Unless we're given an error handler, treat anything written to stderr as
    // the DAP crashing and fail the test unless it's "Waiting for another
    // flutter command to release the startup lock" or we're tearing down.
    _process.stderr
        .transform(utf8.decoder)
        .where((String error) => !error.contains('Waiting for another flutter command to release the startup lock'))
        .listen((String error) {
      logger?.call(error);
      if (!_isShuttingDown) {
        final Function(String message)? stderrHandler = onStderrOutput;
        if (stderrHandler != null) {
          stderrHandler(error);
        } else {
          throw Exception(error);
        }
      }
    });
    unawaited(_process.exitCode.then((int code) {
      final String message = 'Out-of-process DAP server terminated with code $code';
      logger?.call(message);
      if (!_isShuttingDown && code != 0 && onStderrOutput == null) {
        throw Exception(message);
      }
    }));
  }

  bool _isShuttingDown = false;
  final Process _process;

  Future<int> get exitCode => _process.exitCode;

  @override
  StreamSink<List<int>> get sink => _process.stdin;

  @override
  Stream<List<int>> get stream => _process.stdout;

  @override
  Future<void> stop() async {
    _isShuttingDown = true;
    _process.kill();
    await _process.exitCode;
  }

  static Future<OutOfProcessDapTestServer> create({
    Logger? logger,
    List<String>? additionalArgs,
  }) async {
    // runFromSource=true will run "dart bin/flutter_tools.dart ..." to avoid
    // having to rebuild the flutter_tools snapshot.
    // runFromSource=false will run "flutter ..."

    final String flutterToolPath = globals.fs.path.join(Cache.flutterRoot!, 'bin', Platform.isWindows ? 'flutter.bat' : 'flutter');
    final String flutterToolsEntryScript = globals.fs.path.join(Cache.flutterRoot!, 'packages', 'flutter_tools', 'bin', 'flutter_tools.dart');

    // When running from source, run "dart bin/flutter_tools.dart debug_adapter"
    // instead of directly using "flutter debug_adapter".
    final String executable = _runFromSource
      ? Platform.resolvedExecutable
      : flutterToolPath;
    final List<String> args = <String>[
      if (_runFromSource) flutterToolsEntryScript,
      'debug-adapter',
      ...?additionalArgs,
    ];

    final Process process = await Process.start(executable, args);

    return OutOfProcessDapTestServer._(process, logger);
  }
}
