// 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 'package:fuchsia_remote_debug_protocol/fuchsia_remote_debug_protocol.dart';
import 'package:test/fake.dart';
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart' as vms;

void main() {
  group('FuchsiaRemoteConnection.connect', () {
    late List<FakePortForwarder> forwardedPorts;
    List<FakeVmService> fakeVmServices;
    late List<Uri> uriConnections;

    setUp(() {
      final List<Map<String, dynamic>> flutterViewCannedResponses =
          <Map<String, dynamic>>[
        <String, dynamic>{
          'views': <Map<String, dynamic>>[
            <String, dynamic>{
              'type': 'FlutterView',
              'id': 'flutterView0',
            },
          ],
        },
        <String, dynamic>{
          'views': <Map<String, dynamic>>[
            <String, dynamic>{
              'type': 'FlutterView',
              'id': 'flutterView1',
              'isolate': <String, dynamic>{
                'type': '@Isolate',
                'fixedId': 'true',
                'id': 'isolates/1',
                'name': 'file://flutterBinary1',
                'number': '1',
              },
            },
          ],
        },
        <String, dynamic>{
          'views': <Map<String, dynamic>>[
            <String, dynamic>{
              'type': 'FlutterView',
              'id': 'flutterView2',
              'isolate': <String, dynamic>{
                'type': '@Isolate',
                'fixedId': 'true',
                'id': 'isolates/2',
                'name': 'file://flutterBinary2',
                'number': '2',
              },
            },
          ],
        },
      ];

      forwardedPorts = <FakePortForwarder>[];
      fakeVmServices = <FakeVmService>[];
      uriConnections = <Uri>[];
      Future<vms.VmService> fakeVmConnectionFunction(
        Uri uri, {
        Duration? timeout,
      }) {
        return Future<vms.VmService>(() async {
          final FakeVmService service = FakeVmService();
          fakeVmServices.add(service);
          uriConnections.add(uri);
          service.flutterListViews = vms.Response.parse(flutterViewCannedResponses[uri.port]);
          return service;
        });
      }

      fuchsiaVmServiceConnectionFunction = fakeVmConnectionFunction;
    });

    tearDown(() {
      /// Most tests will fake out the port forwarding and connection
      /// functions.
      restoreFuchsiaPortForwardingFunction();
      restoreVmServiceConnectionFunction();
    });

    test('end-to-end with one vm connection and flutter view query', () async {
      int port = 0;
      Future<PortForwarder> fakePortForwardingFunction(
        String address,
        int remotePort, [
        String? interface = '',
        String? configFile,
      ]) {
        return Future<PortForwarder>(() {
          final FakePortForwarder pf = FakePortForwarder();
          forwardedPorts.add(pf);
          pf.port = port++;
          pf.remotePort = remotePort;
          return pf;
        });
      }

      fuchsiaPortForwardingFunction = fakePortForwardingFunction;
      final FakeSshCommandRunner fakeRunner = FakeSshCommandRunner();
      // Adds some extra junk to make sure the strings will be cleaned up.
      fakeRunner.iqueryResponse = <String>[
        '[',
        '   {',
        '     "data_source": "Inspect",',
        '     "metadata": {',
        '       "filename": "fuchsia.inspect.Tree",',
        '       "component_url": "fuchsia-pkg://fuchsia.com/flutter_runner#meta/flutter_runner.cm",',
        '       "timestamp": 12345678901234',
        '     },',
        '     "moniker": "core/session-manager/session/flutter_runner",',
        '     "payload": {',
        '       "root": {',
        '         "vm_service_port": "12345",',
        '         "16859221": {',
        '           "empty_tree": "this semantic tree is empty"',
        '         },',
        '         "build_info": {',
        '           "dart_sdk_git_revision": "77e83fcc14fa94049f363d554579f48fbd6bb7a1",',
        '           "dart_sdk_semantic_version": "2.19.0-317.0.dev",',
        '           "flutter_engine_git_revision": "563b8e830c697a543bf0a8a9f4ae3edfad86ea86",',
        '           "fuchsia_sdk_version": "10.20221018.0.1"',
        '         },',
        '         "vm": {',
        '           "dst_status": 1,',
        '           "get_profile_status": 0,',
        '           "num_get_profile_calls": 1,',
        '           "num_intl_provider_errors": 0,',
        '           "num_on_change_calls": 0,',
        '           "timezone_content_status": 0,',
        '           "tz_data_close_status": -1,',
        '           "tz_data_status": -1',
        '         }',
        '       }',
        '     },',
        '     "version": 1',
        '   }',
        ' ]'
      ];
      fakeRunner.address = 'fe80::8eae:4cff:fef4:9247';
      fakeRunner.interface = 'eno1';

      final FuchsiaRemoteConnection connection =
          await FuchsiaRemoteConnection.connectWithSshCommandRunner(fakeRunner);

      expect(forwardedPorts.length, 1);
      expect(forwardedPorts[0].remotePort, 12345);

      // VMs should be accessed via localhost ports given by
      // [fakePortForwardingFunction].
      expect(uriConnections[0],
          Uri(scheme: 'ws', host: '[::1]', port: 0, path: '/ws'));

      final List<FlutterView> views = await connection.getFlutterViews();
      expect(views, isNot(null));
      expect(views.length, 1);
      // Since name can be null, check for the ID on all of them.
      expect(views[0].id, 'flutterView0');

      expect(views[0].name, equals(null));

      // Ensure the ports are all closed after stop was called.
      await connection.stop();
      expect(forwardedPorts[0].stopped, true);
    });

    test('end-to-end with one vm and remote open port', () async {
      int port = 0;
      Future<PortForwarder> fakePortForwardingFunction(
        String address,
        int remotePort, [
        String? interface = '',
        String? configFile,
      ]) {
        return Future<PortForwarder>(() {
          final FakePortForwarder pf = FakePortForwarder();
          forwardedPorts.add(pf);
          pf.port = port++;
          pf.remotePort = remotePort;
          pf.openPortAddress = 'fe80::1:2%eno2';
          return pf;
        });
      }

      fuchsiaPortForwardingFunction = fakePortForwardingFunction;
      final FakeSshCommandRunner fakeRunner = FakeSshCommandRunner();
      // Adds some extra junk to make sure the strings will be cleaned up.
      fakeRunner.iqueryResponse = <String>[
        '[',
        '   {',
        '     "data_source": "Inspect",',
        '     "metadata": {',
        '       "filename": "fuchsia.inspect.Tree",',
        '       "component_url": "fuchsia-pkg://fuchsia.com/flutter_runner#meta/flutter_runner.cm",',
        '       "timestamp": 12345678901234',
        '     },',
        '     "moniker": "core/session-manager/session/flutter_runner",',
        '     "payload": {',
        '       "root": {',
        '         "vm_service_port": "12345",',
        '         "16859221": {',
        '           "empty_tree": "this semantic tree is empty"',
        '         },',
        '         "build_info": {',
        '           "dart_sdk_git_revision": "77e83fcc14fa94049f363d554579f48fbd6bb7a1",',
        '           "dart_sdk_semantic_version": "2.19.0-317.0.dev",',
        '           "flutter_engine_git_revision": "563b8e830c697a543bf0a8a9f4ae3edfad86ea86",',
        '           "fuchsia_sdk_version": "10.20221018.0.1"',
        '         },',
        '         "vm": {',
        '           "dst_status": 1,',
        '           "get_profile_status": 0,',
        '           "num_get_profile_calls": 1,',
        '           "num_intl_provider_errors": 0,',
        '           "num_on_change_calls": 0,',
        '           "timezone_content_status": 0,',
        '           "tz_data_close_status": -1,',
        '           "tz_data_status": -1',
        '         }',
        '       }',
        '     },',
        '     "version": 1',
        '   }',
        ' ]'
      ];
      fakeRunner.address = 'fe80::8eae:4cff:fef4:9247';
      fakeRunner.interface = 'eno1';
      final FuchsiaRemoteConnection connection =
          await FuchsiaRemoteConnection.connectWithSshCommandRunner(fakeRunner);

      expect(forwardedPorts.length, 1);
      expect(forwardedPorts[0].remotePort, 12345);

      // VMs should be accessed via the alternate address given by
      // [fakePortForwardingFunction].
      expect(uriConnections[0],
          Uri(scheme: 'ws', host: '[fe80::1:2%25eno2]', port: 0, path: '/ws'));

      final List<FlutterView> views = await connection.getFlutterViews();
      expect(views, isNot(null));
      expect(views.length, 1);
      // Since name can be null, check for the ID on all of them.
      expect(views[0].id, 'flutterView0');

      expect(views[0].name, equals(null));

      // Ensure the ports are all closed after stop was called.
      await connection.stop();
      expect(forwardedPorts[0].stopped, true);
    });

    test('end-to-end with one vm and ipv4', () async {
      int port = 0;
      Future<PortForwarder> fakePortForwardingFunction(
        String address,
        int remotePort, [
        String? interface = '',
        String? configFile,
      ]) {
        return Future<PortForwarder>(() {
          final FakePortForwarder pf = FakePortForwarder();
          forwardedPorts.add(pf);
          pf.port = port++;
          pf.remotePort = remotePort;
          return pf;
        });
      }

      fuchsiaPortForwardingFunction = fakePortForwardingFunction;
      final FakeSshCommandRunner fakeRunner = FakeSshCommandRunner();
      // Adds some extra junk to make sure the strings will be cleaned up.
      fakeRunner.iqueryResponse = <String>[
        '[',
        '   {',
        '     "data_source": "Inspect",',
        '     "metadata": {',
        '       "filename": "fuchsia.inspect.Tree",',
        '       "component_url": "fuchsia-pkg://fuchsia.com/flutter_runner#meta/flutter_runner.cm",',
        '       "timestamp": 12345678901234',
        '     },',
        '     "moniker": "core/session-manager/session/flutter_runner",',
        '     "payload": {',
        '       "root": {',
        '         "vm_service_port": "12345",',
        '         "16859221": {',
        '           "empty_tree": "this semantic tree is empty"',
        '         },',
        '         "build_info": {',
        '           "dart_sdk_git_revision": "77e83fcc14fa94049f363d554579f48fbd6bb7a1",',
        '           "dart_sdk_semantic_version": "2.19.0-317.0.dev",',
        '           "flutter_engine_git_revision": "563b8e830c697a543bf0a8a9f4ae3edfad86ea86",',
        '           "fuchsia_sdk_version": "10.20221018.0.1"',
        '         },',
        '         "vm": {',
        '           "dst_status": 1,',
        '           "get_profile_status": 0,',
        '           "num_get_profile_calls": 1,',
        '           "num_intl_provider_errors": 0,',
        '           "num_on_change_calls": 0,',
        '           "timezone_content_status": 0,',
        '           "tz_data_close_status": -1,',
        '           "tz_data_status": -1',
        '         }',
        '       }',
        '     },',
        '     "version": 1',
        '   }',
        ' ]'
      ];
      fakeRunner.address = '196.168.1.4';

      final FuchsiaRemoteConnection connection =
          await FuchsiaRemoteConnection.connectWithSshCommandRunner(fakeRunner);

      expect(forwardedPorts.length, 1);
      expect(forwardedPorts[0].remotePort, 12345);

      // VMs should be accessed via the ipv4 loopback.
      expect(uriConnections[0],
          Uri(scheme: 'ws', host: '127.0.0.1', port: 0, path: '/ws'));

      final List<FlutterView> views = await connection.getFlutterViews();
      expect(views, isNot(null));
      expect(views.length, 1);
      // Since name can be null, check for the ID on all of them.
      expect(views[0].id, 'flutterView0');

      expect(views[0].name, equals(null));

      // Ensure the ports are all closed after stop was called.
      await connection.stop();
      expect(forwardedPorts[0].stopped, true);
    });

    test('env variable test without remote addr', () async {
      Future<void> failingFunction() async {
        await FuchsiaRemoteConnection.connect();
      }

      // Should fail as no env variable has been passed.
      expect(failingFunction,
          throwsA(isA<FuchsiaRemoteConnectionError>()));
    });
  });
}

class FakeSshCommandRunner extends Fake implements SshCommandRunner {
  List<String>? iqueryResponse;
  @override
  Future<List<String>> run(String command) async {
    if (command.startsWith('iquery --format json show')) {
      return iqueryResponse!;
    }
    throw UnimplementedError(command);
  }

  @override
  String interface = '';

  @override
  String address = '';

  @override
  String get sshConfigPath => '~/.ssh';
}

class FakePortForwarder extends Fake implements PortForwarder {
  @override
  int port = 0;

  @override
  int remotePort = 0;

  @override
  String? openPortAddress;

  bool stopped = false;
  @override
  Future<void> stop() async {
    stopped = true;
  }
}

class FakeVmService extends Fake implements vms.VmService {
  bool disposed = false;
  vms.Response? flutterListViews;

  @override
  Future<void> dispose() async {
    disposed = true;
  }

  @override
  Future<vms.Response> callMethod(String method, {String? isolateId, Map<String, dynamic>? args}) async {
    if (method == '_flutter.listViews') {
      return flutterListViews!;
    }
    throw UnimplementedError(method);
  }

  @override
  Future<void> onDone = Future<void>.value();

  @override
  Future<vms.Version> getVersion() async {
    return vms.Version(major: -1, minor: -1);
  }
}
