// 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 'package:file/memory.dart';
import 'package:flutter_tools/src/android/android_device.dart';
import 'package:flutter_tools/src/application_package.dart';
import 'package:flutter_tools/src/artifacts.dart';
import 'package:flutter_tools/src/base/common.dart';
import 'package:flutter_tools/src/base/dds.dart';
import 'package:flutter_tools/src/base/file_system.dart';
import 'package:flutter_tools/src/base/io.dart';
import 'package:flutter_tools/src/base/logger.dart';
import 'package:flutter_tools/src/base/platform.dart';
import 'package:flutter_tools/src/base/signals.dart';
import 'package:flutter_tools/src/base/terminal.dart';
import 'package:flutter_tools/src/build_info.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/attach.dart';
import 'package:flutter_tools/src/device.dart';
import 'package:flutter_tools/src/device_port_forwarder.dart';
import 'package:flutter_tools/src/ios/application_package.dart';
import 'package:flutter_tools/src/ios/devices.dart';
import 'package:flutter_tools/src/macos/macos_ipad_device.dart';
import 'package:flutter_tools/src/mdns_discovery.dart';
import 'package:flutter_tools/src/project.dart';
import 'package:flutter_tools/src/reporting/reporting.dart';
import 'package:flutter_tools/src/resident_runner.dart';
import 'package:flutter_tools/src/run_hot.dart';
import 'package:flutter_tools/src/vmservice.dart';
import 'package:multicast_dns/multicast_dns.dart';
import 'package:test/fake.dart';
import 'package:vm_service/vm_service.dart' as vm_service;

import '../../src/common.dart';
import '../../src/context.dart';
import '../../src/fake_devices.dart';
import '../../src/test_flutter_command_runner.dart';

class FakeStdio extends Fake implements Stdio {
  @override
  bool stdinHasTerminal = false;
}

class FakeProcessInfo extends Fake implements ProcessInfo {
  @override
  int maxRss = 0;
}

void main() {
  tearDown(() {
    MacOSDesignedForIPadDevices.allowDiscovery = false;
  });

  group('attach', () {
    late StreamLogger logger;
    late FileSystem testFileSystem;
    late TestDeviceManager testDeviceManager;
    late Artifacts artifacts;
    late Stdio stdio;
    late Terminal terminal;
    late Signals signals;
    late Platform platform;
    late ProcessInfo processInfo;

    setUp(() {
      Cache.disableLocking();
      logger = StreamLogger();
      platform = FakePlatform();
      testFileSystem = MemoryFileSystem.test();
      testFileSystem.directory('lib').createSync();
      testFileSystem.file(testFileSystem.path.join('lib', 'main.dart')).createSync();
      artifacts = Artifacts.test();
      stdio = FakeStdio();
      terminal = FakeTerminal();
      signals = Signals.test();
      processInfo = FakeProcessInfo();
      testDeviceManager = TestDeviceManager(logger: BufferLogger.test());
    });

    group('with one device and no specified target file', () {
      const int devicePort = 499;
      const int hostPort = 42;

      late FakeDeviceLogReader fakeLogReader;
      late RecordingPortForwarder portForwarder;
      late FakeDartDevelopmentService fakeDds;
      late FakeAndroidDevice device;

      setUp(() {
        fakeLogReader = FakeDeviceLogReader();
        portForwarder = RecordingPortForwarder(hostPort);
        fakeDds = FakeDartDevelopmentService();
        device = FakeAndroidDevice(id: '1')
          ..portForwarder = portForwarder
          ..dds = fakeDds;
      });

      tearDown(() {
        fakeLogReader.dispose();
      });

      testUsingContext('succeeds with iOS device', () async {
        final FakeIOSDevice device = FakeIOSDevice(
          logReader: fakeLogReader,
          portForwarder: portForwarder,
          onGetLogReader: () {
            fakeLogReader.addLine('Foo');
            fakeLogReader.addLine('The Dart VM service is listening on http://127.0.0.1:$devicePort');
            return fakeLogReader;
          },
        );

        testDeviceManager.devices = <Device>[device];
        final Completer<void> completer = Completer<void>();
        final StreamSubscription<String> loggerSubscription = logger.stream.listen((String message) {
          if (message == '[verbose] Observatory URL on device: http://127.0.0.1:$devicePort') {
            // The "Observatory URL on device" message is output by the ProtocolDiscovery when it found the observatory.
            completer.complete();
          }
        });
        final Future<void> task = createTestCommandRunner(AttachCommand(
          artifacts: artifacts,
          stdio: stdio,
          logger: logger,
          terminal: terminal,
          signals: signals,
          platform: platform,
          processInfo: processInfo,
          fileSystem: testFileSystem,
        )).run(<String>['attach']);
        await completer.future;

        expect(portForwarder.devicePort, devicePort);
        expect(portForwarder.hostPort, hostPort);

        await fakeLogReader.dispose();
        await expectLoggerInterruptEndsTask(task, logger);
        await loggerSubscription.cancel();
      }, overrides: <Type, Generator>{
        FileSystem: () => testFileSystem,
        ProcessManager: () => FakeProcessManager.any(),
        Logger: () => logger,
        DeviceManager: () => testDeviceManager,
        MDnsObservatoryDiscovery: () => MDnsObservatoryDiscovery(
          mdnsClient: FakeMDnsClient(<PtrResourceRecord>[], <String, List<SrvResourceRecord>>{}),
          logger: logger,
          flutterUsage: TestUsage(),
        ),
      });

      testUsingContext('finds observatory port and forwards', () async {
        device.onGetLogReader = () {
          fakeLogReader.addLine('Foo');
          fakeLogReader.addLine('The Dart VM service is listening on http://127.0.0.1:$devicePort');
          return fakeLogReader;
        };
        testDeviceManager.devices = <Device>[device];
        final Completer<void> completer = Completer<void>();
        final StreamSubscription<String> loggerSubscription = logger.stream.listen((String message) {
          if (message == '[verbose] Observatory URL on device: http://127.0.0.1:$devicePort') {
            // The "Observatory URL on device" message is output by the ProtocolDiscovery when it found the observatory.
            completer.complete();
          }
        });
        final Future<void> task = createTestCommandRunner(AttachCommand(
          artifacts: artifacts,
          stdio: stdio,
          logger: logger,
          terminal: terminal,
          signals: signals,
          platform: platform,
          processInfo: processInfo,
          fileSystem: testFileSystem,
        )).run(<String>['attach']);
        await completer.future;

        expect(portForwarder.devicePort, devicePort);
        expect(portForwarder.hostPort, hostPort);

        await fakeLogReader.dispose();
        await expectLoggerInterruptEndsTask(task, logger);
        await loggerSubscription.cancel();
      }, overrides: <Type, Generator>{
        FileSystem: () => testFileSystem,
        ProcessManager: () => FakeProcessManager.any(),
        Logger: () => logger,
        DeviceManager: () => testDeviceManager,
      });

      testUsingContext('Fails with tool exit on bad Observatory uri', () async {
        device.onGetLogReader = () {
          fakeLogReader.addLine('Foo');
          fakeLogReader.addLine('The Dart VM service is listening on http://127.0.0.1:$devicePort');
          fakeLogReader.dispose();
          return fakeLogReader;
        };
        testDeviceManager.devices = <Device>[device];
        expect(() => createTestCommandRunner(AttachCommand(
          artifacts: artifacts,
          stdio: stdio,
          logger: logger,
          terminal: terminal,
          signals: signals,
          platform: platform,
          processInfo: processInfo,
          fileSystem: testFileSystem,
        )).run(<String>['attach']), throwsToolExit());
      }, overrides: <Type, Generator>{
        FileSystem: () => testFileSystem,
        ProcessManager: () => FakeProcessManager.any(),
        Logger: () => logger,
        DeviceManager: () => testDeviceManager,
      });

      testUsingContext('accepts filesystem parameters', () async {
        device.onGetLogReader = () {
          fakeLogReader.addLine('Foo');
          fakeLogReader.addLine('The Dart VM service is listening on http://127.0.0.1:$devicePort');
          return fakeLogReader;
        };
        testDeviceManager.devices = <Device>[device];

        const String filesystemScheme = 'foo';
        const String filesystemRoot = '/build-output/';
        const String projectRoot = '/build-output/project-root';
        const String outputDill = '/tmp/output.dill';

        final FakeHotRunner hotRunner = FakeHotRunner();
        hotRunner.onAttach = (
          Completer<DebugConnectionInfo>? connectionInfoCompleter,
          Completer<void>? appStartedCompleter,
          bool allowExistingDdsInstance,
          bool enableDevTools,
        ) async => 0;
        hotRunner.exited = false;
        hotRunner.isWaitingForObservatory = false;

        final FakeHotRunnerFactory hotRunnerFactory = FakeHotRunnerFactory()
          ..hotRunner = hotRunner;

        final AttachCommand command = AttachCommand(
          hotRunnerFactory: hotRunnerFactory,
          artifacts: artifacts,
          stdio: stdio,
          logger: logger,
          terminal: terminal,
          signals: signals,
          platform: platform,
          processInfo: processInfo,
          fileSystem: testFileSystem,
        );
        await createTestCommandRunner(command).run(<String>[
          'attach',
          '--filesystem-scheme',
          filesystemScheme,
          '--filesystem-root',
          filesystemRoot,
          '--project-root',
          projectRoot,
          '--output-dill',
          outputDill,
          '-v', // enables verbose logging
        ]);

        // Validate the attach call built a fake runner with the right
        // project root and output dill.
        expect(hotRunnerFactory.projectRootPath, projectRoot);
        expect(hotRunnerFactory.dillOutputPath, outputDill);
        expect(hotRunnerFactory.devices, hasLength(1));

        // Validate that the attach call built a flutter device with the right
        // output dill, filesystem scheme, and filesystem root.
        final FlutterDevice flutterDevice = hotRunnerFactory.devices.first;

        expect(flutterDevice.buildInfo.fileSystemScheme, filesystemScheme);
        expect(flutterDevice.buildInfo.fileSystemRoots, const <String>[filesystemRoot]);
      }, overrides: <Type, Generator>{
        FileSystem: () => testFileSystem,
        ProcessManager: () => FakeProcessManager.any(),
        DeviceManager: () => testDeviceManager,
      });

      testUsingContext('exits when ipv6 is specified and debug-port is not', () async {
        testDeviceManager.devices = <Device>[device];

        final AttachCommand command = AttachCommand(
          artifacts: artifacts,
          stdio: stdio,
          logger: logger,
          terminal: terminal,
          signals: signals,
          platform: platform,
          processInfo: processInfo,
          fileSystem: testFileSystem,
        );
        await expectLater(
          createTestCommandRunner(command).run(<String>['attach', '--ipv6']),
          throwsToolExit(
            message: 'When the --debug-port or --debug-url is unknown, this command determines '
                     'the value of --ipv6 on its own.',
          ),
        );
      }, overrides: <Type, Generator>{
        FileSystem: () => testFileSystem,
        ProcessManager: () => FakeProcessManager.any(),
        DeviceManager: () => testDeviceManager,
      },);

      testUsingContext('exits when observatory-port is specified and debug-port is not', () async {
        device.onGetLogReader = () {
          fakeLogReader.addLine('Foo');
          fakeLogReader.addLine('The Dart VM service is listening on http://127.0.0.1:$devicePort');
          return fakeLogReader;
        };
        testDeviceManager.devices = <Device>[device];

        final AttachCommand command = AttachCommand(
          artifacts: artifacts,
          stdio: stdio,
          logger: logger,
          terminal: terminal,
          signals: signals,
          platform: platform,
          processInfo: processInfo,
          fileSystem: testFileSystem,
        );
        await expectLater(
          createTestCommandRunner(command).run(<String>['attach', '--observatory-port', '100']),
          throwsToolExit(
            message: 'When the --debug-port or --debug-url is unknown, this command does not use '
                     'the value of --observatory-port.',
          ),
        );
      }, overrides: <Type, Generator>{
        FileSystem: () => testFileSystem,
        ProcessManager: () => FakeProcessManager.any(),
        DeviceManager: () => testDeviceManager,
      },);
    });

    group('forwarding to given port', () {
      const int devicePort = 499;
      const int hostPort = 42;
      late RecordingPortForwarder portForwarder;
      late FakeAndroidDevice device;

      setUp(() {
        final FakeDartDevelopmentService fakeDds = FakeDartDevelopmentService();
        portForwarder = RecordingPortForwarder(hostPort);
        device = FakeAndroidDevice(id: '1')
          ..portForwarder = portForwarder
          ..dds = fakeDds;
      });

      testUsingContext('succeeds in ipv4 mode', () async {
        testDeviceManager.devices = <Device>[device];

        final Completer<void> completer = Completer<void>();
        final StreamSubscription<String> loggerSubscription = logger.stream.listen((String message) {
          if (message == '[verbose] Connecting to service protocol: http://127.0.0.1:42/') {
            // Wait until resident_runner.dart tries to connect.
            // There's nothing to connect _to_, so that's as far as we care to go.
            completer.complete();
          }
        });
        final Future<void> task = createTestCommandRunner(AttachCommand(
          artifacts: artifacts,
          stdio: stdio,
          logger: logger,
          terminal: terminal,
          signals: signals,
          platform: platform,
          processInfo: processInfo,
          fileSystem: testFileSystem,
        ))
          .run(<String>['attach', '--debug-port', '$devicePort']);
        await completer.future;
        expect(portForwarder.devicePort, devicePort);
        expect(portForwarder.hostPort, hostPort);

        await expectLoggerInterruptEndsTask(task, logger);
        await loggerSubscription.cancel();
      }, overrides: <Type, Generator>{
        FileSystem: () => testFileSystem,
        ProcessManager: () => FakeProcessManager.any(),
        Logger: () => logger,
        DeviceManager: () => testDeviceManager,
      });

      testUsingContext('succeeds in ipv6 mode', () async {
        testDeviceManager.devices = <Device>[device];

        final Completer<void> completer = Completer<void>();
        final StreamSubscription<String> loggerSubscription = logger.stream.listen((String message) {
          if (message == '[verbose] Connecting to service protocol: http://[::1]:42/') {
            // Wait until resident_runner.dart tries to connect.
            // There's nothing to connect _to_, so that's as far as we care to go.
            completer.complete();
          }
        });
        final Future<void> task = createTestCommandRunner(AttachCommand(
          artifacts: artifacts,
          stdio: stdio,
          logger: logger,
          terminal: terminal,
          signals: signals,
          platform: platform,
          processInfo: processInfo,
          fileSystem: testFileSystem,
        ))
          .run(<String>['attach', '--debug-port', '$devicePort', '--ipv6']);
        await completer.future;

        expect(portForwarder.devicePort, devicePort);
        expect(portForwarder.hostPort, hostPort);

        await expectLoggerInterruptEndsTask(task, logger);
        await loggerSubscription.cancel();
      }, overrides: <Type, Generator>{
        FileSystem: () => testFileSystem,
        ProcessManager: () => FakeProcessManager.any(),
        Logger: () => logger,
        DeviceManager: () => testDeviceManager,
      });

      testUsingContext('skips in ipv4 mode with a provided observatory port', () async {
        testDeviceManager.devices = <Device>[device];

        final Completer<void> completer = Completer<void>();
        final StreamSubscription<String> loggerSubscription = logger.stream.listen((String message) {
          if (message == '[verbose] Connecting to service protocol: http://127.0.0.1:42/') {
            // Wait until resident_runner.dart tries to connect.
            // There's nothing to connect _to_, so that's as far as we care to go.
            completer.complete();
          }
        });
        final Future<void> task = createTestCommandRunner(AttachCommand(
          artifacts: artifacts,
          stdio: stdio,
          logger: logger,
          terminal: terminal,
          signals: signals,
          platform: platform,
          processInfo: processInfo,
          fileSystem: testFileSystem,
        )).run(
          <String>[
            'attach',
            '--debug-port',
            '$devicePort',
            '--observatory-port',
            '$hostPort',
            // Ensure DDS doesn't use hostPort by binding to a random port.
            '--dds-port',
            '0',
          ],
        );
        await completer.future;
        expect(portForwarder.devicePort, null);
        expect(portForwarder.hostPort, 42);

        await expectLoggerInterruptEndsTask(task, logger);
        await loggerSubscription.cancel();
      }, overrides: <Type, Generator>{
        FileSystem: () => testFileSystem,
        ProcessManager: () => FakeProcessManager.any(),
        Logger: () => logger,
        DeviceManager: () => testDeviceManager,
      });

      testUsingContext('skips in ipv6 mode with a provided observatory port', () async {
        testDeviceManager.devices = <Device>[device];

        final Completer<void> completer = Completer<void>();
        final StreamSubscription<String> loggerSubscription = logger.stream.listen((String message) {
          if (message == '[verbose] Connecting to service protocol: http://[::1]:42/') {
            // Wait until resident_runner.dart tries to connect.
            // There's nothing to connect _to_, so that's as far as we care to go.
            completer.complete();
          }
        });
        final Future<void> task = createTestCommandRunner(AttachCommand(
          artifacts: artifacts,
          stdio: stdio,
          logger: logger,
          terminal: terminal,
          signals: signals,
          platform: platform,
          processInfo: processInfo,
          fileSystem: testFileSystem,
        )).run(
          <String>[
            'attach',
            '--debug-port',
            '$devicePort',
            '--observatory-port',
            '$hostPort',
            '--ipv6',
            // Ensure DDS doesn't use hostPort by binding to a random port.
            '--dds-port',
            '0',
          ],
        );
        await completer.future;
        expect(portForwarder.devicePort, null);
        expect(portForwarder.hostPort, 42);

        await expectLoggerInterruptEndsTask(task, logger);
        await loggerSubscription.cancel();
      }, overrides: <Type, Generator>{
        FileSystem: () => testFileSystem,
        ProcessManager: () => FakeProcessManager.any(),
        Logger: () => logger,
        DeviceManager: () => testDeviceManager,
      });
    });

    testUsingContext('exits when no device connected', () async {
      final AttachCommand command = AttachCommand(
        artifacts: artifacts,
        stdio: stdio,
        logger: logger,
        terminal: terminal,
        signals: signals,
        platform: platform,
        processInfo: processInfo,
        fileSystem: testFileSystem,
      );
      await expectLater(
        createTestCommandRunner(command).run(<String>['attach']),
        throwsToolExit(),
      );
      expect(testLogger.statusText, containsIgnoringWhitespace('No supported devices connected'));
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
      ProcessManager: () => FakeProcessManager.any(),
      DeviceManager: () => testDeviceManager,
    });

    testUsingContext('fails when targeted device is not Android with --device-user', () async {
      final FakeIOSDevice device = FakeIOSDevice();
      testDeviceManager.devices = <Device>[device];
      expect(createTestCommandRunner(AttachCommand(
        artifacts: artifacts,
        stdio: stdio,
        logger: logger,
        terminal: terminal,
        signals: signals,
        platform: platform,
        processInfo: processInfo,
        fileSystem: testFileSystem,
      )).run(<String>[
        'attach',
        '--device-user',
        '10',
      ]), throwsToolExit(message: '--device-user is only supported for Android'));
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
      ProcessManager: () => FakeProcessManager.any(),
      DeviceManager: () => testDeviceManager,
    });

    testUsingContext('exits when multiple devices connected', () async {
      final AttachCommand command = AttachCommand(
        artifacts: artifacts,
        stdio: stdio,
        logger: logger,
        terminal: terminal,
        signals: signals,
        platform: platform,
        processInfo: processInfo,
        fileSystem: testFileSystem,
      );
      testDeviceManager.devices = <Device>[
        FakeAndroidDevice(id: 'xx1'),
        FakeAndroidDevice(id: 'yy2'),
      ];
      await expectLater(
        createTestCommandRunner(command).run(<String>['attach']),
        throwsToolExit(),
      );
      expect(testLogger.statusText, containsIgnoringWhitespace('More than one device'));
      expect(testLogger.statusText, contains('xx1'));
      expect(testLogger.statusText, contains('yy2'));
      expect(MacOSDesignedForIPadDevices.allowDiscovery, isTrue);
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
      ProcessManager: () => FakeProcessManager.any(),
      DeviceManager: () => testDeviceManager,
      AnsiTerminal: () => FakeTerminal(stdinHasTerminal: false),
    });

    testUsingContext('Catches service disappeared error', () async {
      final FakeAndroidDevice device = FakeAndroidDevice(id: '1')
        ..portForwarder = const NoOpDevicePortForwarder()
        ..onGetLogReader = () => NoOpDeviceLogReader('test');
      final FakeHotRunner hotRunner = FakeHotRunner();
      final FakeHotRunnerFactory hotRunnerFactory = FakeHotRunnerFactory()
        ..hotRunner = hotRunner;
      hotRunner.onAttach = (
        Completer<DebugConnectionInfo>? connectionInfoCompleter,
        Completer<void>? appStartedCompleter,
        bool allowExistingDdsInstance,
        bool enableDevTools,
      ) async {
        await null;
        throw vm_service.RPCError('flutter._listViews', RPCErrorCodes.kServiceDisappeared, '');
      };

      testDeviceManager.devices = <Device>[device];
      testFileSystem.file('lib/main.dart').createSync();

      final AttachCommand command = AttachCommand(
        hotRunnerFactory: hotRunnerFactory,
        artifacts: artifacts,
        stdio: stdio,
        logger: logger,
        terminal: terminal,
        signals: signals,
        platform: platform,
        processInfo: processInfo,
        fileSystem: testFileSystem,
      );
      await expectLater(createTestCommandRunner(command).run(<String>[
        'attach',
      ]), throwsToolExit(message: 'Lost connection to device.'));
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
      ProcessManager: () => FakeProcessManager.any(),
      DeviceManager: () => testDeviceManager,
    });

    testUsingContext('Does not catch generic RPC error', () async {
      final FakeAndroidDevice device = FakeAndroidDevice(id: '1')
        ..portForwarder = const NoOpDevicePortForwarder()
        ..onGetLogReader = () => NoOpDeviceLogReader('test');
      final FakeHotRunner hotRunner = FakeHotRunner();
      final FakeHotRunnerFactory hotRunnerFactory = FakeHotRunnerFactory()
        ..hotRunner = hotRunner;

      hotRunner.onAttach = (
        Completer<DebugConnectionInfo>? connectionInfoCompleter,
        Completer<void>? appStartedCompleter,
        bool allowExistingDdsInstance,
        bool enableDevTools,
      ) async {
        await null;
        throw vm_service.RPCError('flutter._listViews', RPCErrorCodes.kInvalidParams, '');
      };

      testDeviceManager.devices = <Device>[device];
      testFileSystem.file('lib/main.dart').createSync();

      final AttachCommand command = AttachCommand(
        hotRunnerFactory: hotRunnerFactory,
        artifacts: artifacts,
        stdio: stdio,
        logger: logger,
        terminal: terminal,
        signals: signals,
        platform: platform,
        processInfo: processInfo,
        fileSystem: testFileSystem,
      );
      await expectLater(createTestCommandRunner(command).run(<String>[
        'attach',
      ]), throwsA(isA<vm_service.RPCError>()));
    }, overrides: <Type, Generator>{
      FileSystem: () => testFileSystem,
      ProcessManager: () => FakeProcessManager.any(),
      DeviceManager: () => testDeviceManager,
    });
  });
}

class FakeHotRunner extends Fake implements HotRunner {
  late Future<int> Function(Completer<DebugConnectionInfo>?, Completer<void>?, bool, bool) onAttach;

  @override
  bool exited = false;

  @override
  bool isWaitingForObservatory = true;

  @override
  Future<int> attach({
    Completer<DebugConnectionInfo>? connectionInfoCompleter,
    Completer<void>? appStartedCompleter,
    bool allowExistingDdsInstance = false,
    bool enableDevTools = false,
    bool needsFullRestart = true,
  }) {
    return onAttach(connectionInfoCompleter, appStartedCompleter, allowExistingDdsInstance, enableDevTools);
  }
}

class FakeHotRunnerFactory extends Fake implements HotRunnerFactory {
  late HotRunner hotRunner;
  String? dillOutputPath;
  String? projectRootPath;
  late List<FlutterDevice> devices;

  @override
  HotRunner build(
    List<FlutterDevice> devices, {
    required String target,
    required DebuggingOptions debuggingOptions,
    bool benchmarkMode = false,
    File? applicationBinary,
    bool hostIsIde = false,
    String? projectRootPath,
    String? packagesFilePath,
    String? dillOutputPath,
    bool stayResident = true,
    bool ipv6 = false,
    FlutterProject? flutterProject,
  }) {
    this.devices = devices;
    this.dillOutputPath = dillOutputPath;
    this.projectRootPath = projectRootPath;
    return hotRunner;
  }
}

class RecordingPortForwarder implements DevicePortForwarder {
  RecordingPortForwarder([this.hostPort]);

  int? devicePort;
  int? hostPort;

  @override
  Future<void> dispose() async { }

  @override
  Future<int> forward(int devicePort, {int? hostPort}) async {
    this.devicePort = devicePort;
    this.hostPort ??= hostPort;
    return this.hostPort!;
  }

  @override
  List<ForwardedPort> get forwardedPorts => <ForwardedPort>[];

  @override
  Future<void> unforward(ForwardedPort forwardedPort) async { }
}

class StreamLogger extends Logger {
  @override
  bool get isVerbose => true;

  @override
  void printError(
    String message, {
    StackTrace? stackTrace,
    bool? emphasis,
    TerminalColor? color,
    int? indent,
    int? hangingIndent,
    bool? wrap,
  }) {
    hadErrorOutput = true;
    _log('[stderr] $message');
  }

  @override
  void printWarning(
    String message, {
    bool? emphasis,
    TerminalColor? color,
    int? indent,
    int? hangingIndent,
    bool? wrap,
  }) {
    hadWarningOutput = true;
    _log('[stderr] $message');
  }

  @override
  void printStatus(
    String message, {
    bool? emphasis,
    TerminalColor? color,
    bool? newline,
    int? indent,
    int? hangingIndent,
    bool? wrap,
  }) {
    _log('[stdout] $message');
  }

  @override
  void printBox(
    String message, {
    String? title,
  }) {
    if (title == null) {
      _log('[stdout] $message');
    } else {
      _log('[stdout] $title: $message');
    }
  }

  @override
  void printTrace(String message) {
    _log('[verbose] $message');
  }

  @override
  Status startProgress(
    String message, {
    Duration? timeout,
    String? progressId,
    bool multilineOutput = false,
    bool includeTiming = true,
    int progressIndicatorPadding = kDefaultStatusPadding,
  }) {
    _log('[progress] $message');
    return SilentStatus(
      stopwatch: Stopwatch(),
    )..start();
  }

  @override
  Status startSpinner({
    VoidCallback? onFinish,
    Duration? timeout,
    SlowWarningCallback? slowWarningCallback,
  }) {
    return SilentStatus(
      stopwatch: Stopwatch(),
      onFinish: onFinish,
    )..start();
  }

  bool _interrupt = false;

  void interrupt() {
    _interrupt = true;
  }

  final StreamController<String> _controller = StreamController<String>.broadcast();

  void _log(String message) {
    _controller.add(message);
    if (_interrupt) {
      _interrupt = false;
      throw const LoggerInterrupted();
    }
  }

  Stream<String> get stream => _controller.stream;

  @override
  void sendEvent(String name, [Map<String, dynamic>? args]) { }

  @override
  bool get supportsColor => throw UnimplementedError();

  @override
  bool get hasTerminal => false;

  @override
  void clear() => _log('[stdout] ${terminal.clearScreen()}\n');

  @override
  Terminal get terminal => Terminal.test();
}

class LoggerInterrupted implements Exception {
  const LoggerInterrupted();
}

Future<void> expectLoggerInterruptEndsTask(Future<void> task, StreamLogger logger) async {
  logger.interrupt(); // an exception during the task should cause it to fail...
  await expectLater(
    () => task,
    throwsA(isA<ToolExit>().having((ToolExit error) => error.exitCode, 'exitCode', 2)),
  );
}

class FakeDartDevelopmentService extends Fake implements DartDevelopmentService {
  @override
  Future<void> get done => noopCompleter.future;
  final Completer<void> noopCompleter = Completer<void>();

  @override
  Future<void> startDartDevelopmentService(
    Uri observatoryUri, {
    required Logger logger,
    int? hostPort,
    bool? ipv6,
    bool? disableServiceAuthCodes,
    bool cacheStartupProfile = false,
  }) async {}

  @override
  Uri get uri => Uri.parse('http://localhost:8181');
}

// Unfortunately Device, despite not being immutable, has an `operator ==`.
// Until we fix that, we have to also ignore related lints here.
// ignore: avoid_implementing_value_types
class FakeAndroidDevice extends Fake implements AndroidDevice {
  FakeAndroidDevice({required this.id});

  @override
  late DartDevelopmentService dds;

  @override
  final String id;

  @override
  String get name => 'd$id';

  @override
  Future<bool> get isLocalEmulator async => false;

  @override
  Future<String> get sdkNameAndVersion async => 'Android 46';

  @override
  Future<String> get targetPlatformDisplayName async => 'android';

  @override
  Future<TargetPlatform> get targetPlatform async => TargetPlatform.android_arm;

  @override
  bool isSupported() => true;

  @override
  bool get supportsHotRestart => true;

  @override
  bool get supportsFlutterExit => false;

  @override
  bool isSupportedForProject(FlutterProject flutterProject) => true;

  @override
  DevicePortForwarder? portForwarder;

  DeviceLogReader Function()? onGetLogReader;

  @override
  FutureOr<DeviceLogReader> getLogReader({
    ApplicationPackage? app,
    bool includePastLogs = false,
  }) {
    if (onGetLogReader == null) {
      throw UnimplementedError(
        'Called getLogReader but no onGetLogReader callback was supplied in the constructor to FakeAndroidDevice.',
      );
    }
    return onGetLogReader!();
  }

  @override
  OverrideArtifacts? get artifactOverrides => null;

  @override
  final PlatformType platformType = PlatformType.android;

  @override
  Category get category => Category.mobile;

  @override
  bool get ephemeral => true;
}

// Unfortunately Device, despite not being immutable, has an `operator ==`.
// Until we fix that, we have to also ignore related lints here.
// ignore: avoid_implementing_value_types
class FakeIOSDevice extends Fake implements IOSDevice {
  FakeIOSDevice({
    DevicePortForwarder? portForwarder,
    DeviceLogReader? logReader,
    this.onGetLogReader,
  }) : _portForwarder = portForwarder, _logReader = logReader;

  final DevicePortForwarder? _portForwarder;

  @override
  DevicePortForwarder get portForwarder => _portForwarder!;

  @override
  DartDevelopmentService get dds => throw UnimplementedError('getter dds not implemented');

  final DeviceLogReader? _logReader;
  DeviceLogReader get logReader => _logReader!;

  final DeviceLogReader Function()? onGetLogReader;

  @override
  DeviceLogReader getLogReader({
    IOSApp? app,
    bool includePastLogs = false,
  }) {
    if (onGetLogReader == null) {
      throw UnimplementedError(
        'Called getLogReader but no onGetLogReader callback was supplied in the constructor to FakeIOSDevice',
      );
    }
    return onGetLogReader!();
  }

  @override
  OverrideArtifacts? get artifactOverrides => null;

  @override
  final String name = 'name';

  @override
  Future<TargetPlatform> get targetPlatform async => TargetPlatform.ios;

  @override
  final PlatformType platformType = PlatformType.ios;

  @override
  bool isSupported() => true;

  @override
  bool isSupportedForProject(FlutterProject project) => true;
}

class FakeMDnsClient extends Fake implements MDnsClient {
  FakeMDnsClient(this.ptrRecords, this.srvResponse, {
    this.txtResponse = const <String, List<TxtResourceRecord>>{},
    this.osErrorOnStart = false,
  });

  final List<PtrResourceRecord> ptrRecords;
  final Map<String, List<SrvResourceRecord>> srvResponse;
  final Map<String, List<TxtResourceRecord>> txtResponse;
  final bool osErrorOnStart;

  @override
  Future<void> start({
    InternetAddress? listenAddress,
    NetworkInterfacesFactory? interfacesFactory,
    int mDnsPort = 5353,
    InternetAddress? mDnsAddress,
  }) async {
    if (osErrorOnStart) {
      throw const OSError('Operation not supported on socket', 102);
    }
  }

  @override
  Stream<T> lookup<T extends ResourceRecord>(
    ResourceRecordQuery query, {
    Duration timeout = const Duration(seconds: 5),
  }) {
    if (T == PtrResourceRecord && query.fullyQualifiedName == MDnsObservatoryDiscovery.dartObservatoryName) {
      return Stream<PtrResourceRecord>.fromIterable(ptrRecords) as Stream<T>;
    }
    if (T == SrvResourceRecord) {
      final String key = query.fullyQualifiedName;
      return Stream<SrvResourceRecord>.fromIterable(srvResponse[key] ?? <SrvResourceRecord>[]) as Stream<T>;
    }
    if (T == TxtResourceRecord) {
      final String key = query.fullyQualifiedName;
      return Stream<TxtResourceRecord>.fromIterable(txtResponse[key] ?? <TxtResourceRecord>[]) as Stream<T>;
    }
    throw UnsupportedError('Unsupported query type $T');
  }

  @override
  void stop() {}
}

class TestDeviceManager extends DeviceManager {
  TestDeviceManager({required this.logger}) : super(logger: logger);
  List<Device> devices = <Device>[];

  final BufferLogger logger;

  @override
  List<DeviceDiscovery> get deviceDiscoverers {
    final FakePollingDeviceDiscovery discoverer = FakePollingDeviceDiscovery();
    devices.forEach(discoverer.addDevice);
    return <DeviceDiscovery>[discoverer];
  }
}

class FakeTerminal extends Fake implements AnsiTerminal {
  FakeTerminal({this.stdinHasTerminal = true});

  @override
  final bool stdinHasTerminal;

  @override
  bool usesTerminalUi = false;
}
