// 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:meta/meta.dart';
import 'package:multicast_dns/multicast_dns.dart';

import 'base/common.dart';
import 'base/context.dart';
import 'base/io.dart';
import 'base/logger.dart';
import 'build_info.dart';
import 'convert.dart';
import 'device.dart';
import 'reporting/reporting.dart';

/// A wrapper around [MDnsClient] to find a Dart VM Service instance.
class MDnsVmServiceDiscovery {
  /// Creates a new [MDnsVmServiceDiscovery] object.
  ///
  /// The [_client] parameter will be defaulted to a new [MDnsClient] if null.
  MDnsVmServiceDiscovery({
    MDnsClient? mdnsClient,
    MDnsClient? preliminaryMDnsClient,
    required Logger logger,
    required Usage flutterUsage,
  })  : _client = mdnsClient ?? MDnsClient(),
        _preliminaryClient = preliminaryMDnsClient,
        _logger = logger,
        _flutterUsage = flutterUsage;

  final MDnsClient _client;

  // Used when discovering VM services with `queryForAttach` to do a preliminary
  // check for already running services so that results are not cached in _client.
  final MDnsClient? _preliminaryClient;

  final Logger _logger;
  final Usage _flutterUsage;

  @visibleForTesting
  static const String dartVmServiceName = '_dartobservatory._tcp.local';

  static MDnsVmServiceDiscovery? get instance => context.get<MDnsVmServiceDiscovery>();

  /// Executes an mDNS query for Dart VM Services.
  /// Checks for services that have already been launched.
  /// If none are found, it will listen for new services to become active
  /// and return the first it finds that match the parameters.
  ///
  /// The [applicationId] parameter may be used to specify which application
  /// to find. For Android, it refers to the package name; on iOS, it refers to
  /// the bundle ID.
  ///
  /// The [deviceVmservicePort] parameter may be used to specify which port
  /// to find.
  ///
  /// The [isNetworkDevice] parameter flags whether to get the device IP
  /// and the [ipv6] parameter flags whether to get an iPv6 address
  /// (otherwise it will get iPv4).
  ///
  /// The [timeout] parameter determines how long to continue to wait for
  /// services to become active.
  ///
  /// If [applicationId] is not null, this method will find the port and authentication code
  /// of the Dart VM Service for that application. If it cannot find a service matching
  /// that application identifier after the [timeout], it will call [throwToolExit].
  ///
  /// If [applicationId] is null and there are multiple Dart VM Services available,
  /// the user will be prompted with a list of available services with the respective
  /// app-id and device-vmservice-port to use and asked to select one.
  ///
  /// If it is null and there is only one available or it's the first found instance
  /// of Dart VM Service, it will return that instance's information regardless of
  /// what application the service instance is for.
  @visibleForTesting
  Future<MDnsVmServiceDiscoveryResult?> queryForAttach({
    String? applicationId,
    int? deviceVmservicePort,
    bool ipv6 = false,
    bool isNetworkDevice = false,
    Duration timeout = const Duration(minutes: 10),
  }) async {
    // Poll for 5 seconds to see if there are already services running.
    // Use a new instance of MDnsClient so results don't get cached in _client.
    // If no results are found, poll for a longer duration to wait for connections.
    // If more than 1 result is found, throw an error since it can't be determined which to pick.
    // If only one is found, return it.
    final List<MDnsVmServiceDiscoveryResult> results = await _pollingVmService(
      _preliminaryClient ?? MDnsClient(),
      applicationId: applicationId,
      deviceVmservicePort: deviceVmservicePort,
      ipv6: ipv6,
      isNetworkDevice: isNetworkDevice,
      timeout: const Duration(seconds: 5),
    );
    if (results.isEmpty) {
      return firstMatchingVmService(
        _client,
        applicationId: applicationId,
        deviceVmservicePort: deviceVmservicePort,
        ipv6: ipv6,
        isNetworkDevice: isNetworkDevice,
        timeout: timeout,
      );
    } else if (results.length > 1) {
      final StringBuffer buffer = StringBuffer();
      buffer.writeln('There are multiple Dart VM Services available.');
      buffer.writeln('Rerun this command with one of the following passed in as the app-id and device-vmservice-port:');
      buffer.writeln();
      for (final MDnsVmServiceDiscoveryResult result in results) {
        buffer.writeln(
            '  flutter attach --app-id "${result.domainName.replaceAll('.$dartVmServiceName', '')}" --device-vmservice-port ${result.port}');
      }
      throwToolExit(buffer.toString());
    }
    return results.first;
  }

  /// Executes an mDNS query for Dart VM Services.
  /// Listens for new services to become active and returns the first it finds that
  /// match the parameters.
  ///
  /// The [applicationId] parameter must be set to specify which application
  /// to find. For Android, it refers to the package name; on iOS, it refers to
  /// the bundle ID.
  ///
  /// The [deviceVmservicePort] parameter must be set to specify which port
  /// to find.
  ///
  /// [applicationId] and [deviceVmservicePort] are required for launch so that
  /// if multiple flutter apps are running on different devices, it will
  /// only match with the device running the desired app.
  ///
  /// The [isNetworkDevice] parameter flags whether to get the device IP
  /// and the [ipv6] parameter flags whether to get an iPv6 address
  /// (otherwise it will get iPv4).
  ///
  /// The [timeout] parameter determines how long to continue to wait for
  /// services to become active.
  ///
  /// If a Dart VM Service matching the [applicationId] and [deviceVmservicePort]
  /// cannot be found after the [timeout], it will call [throwToolExit].
  @visibleForTesting
  Future<MDnsVmServiceDiscoveryResult?> queryForLaunch({
    required String applicationId,
    required int deviceVmservicePort,
    bool ipv6 = false,
    bool isNetworkDevice = false,
    Duration timeout = const Duration(minutes: 10),
  }) async {
    // Query for a specific application and device port.
    return firstMatchingVmService(
      _client,
      applicationId: applicationId,
      deviceVmservicePort: deviceVmservicePort,
      ipv6: ipv6,
      isNetworkDevice: isNetworkDevice,
      timeout: timeout,
    );
  }

  /// Polls for Dart VM Services and returns the first it finds that match
  /// the [applicationId]/[deviceVmservicePort] (if applicable).
  /// Returns null if no results are found.
  @visibleForTesting
  Future<MDnsVmServiceDiscoveryResult?> firstMatchingVmService(
    MDnsClient client, {
    String? applicationId,
    int? deviceVmservicePort,
    bool ipv6 = false,
    bool isNetworkDevice = false,
    Duration timeout = const Duration(minutes: 10),
  }) async {
    final List<MDnsVmServiceDiscoveryResult> results = await _pollingVmService(
      client,
      applicationId: applicationId,
      deviceVmservicePort: deviceVmservicePort,
      ipv6: ipv6,
      isNetworkDevice: isNetworkDevice,
      timeout: timeout,
      quitOnFind: true,
    );
    if (results.isEmpty) {
      return null;
    }
    return results.first;
  }

  Future<List<MDnsVmServiceDiscoveryResult>> _pollingVmService(
    MDnsClient client, {
    String? applicationId,
    int? deviceVmservicePort,
    bool ipv6 = false,
    bool isNetworkDevice = false,
    required Duration timeout,
    bool quitOnFind = false,
  }) async {
    _logger.printTrace('Checking for advertised Dart VM Services...');
    try {
      await client.start();

      final List<MDnsVmServiceDiscoveryResult> results =
          <MDnsVmServiceDiscoveryResult>[];

      // uniqueDomainNames is used to track all domain names of Dart VM services
      // It is later used in this function to determine whether or not to throw an error.
      // We do not want to throw the error if it was unable to find any domain
      // names because that indicates it may be a problem with mDNS, which has
      // a separate error message in _checkForIPv4LinkLocal.
      final Set<String> uniqueDomainNames = <String>{};
      // uniqueDomainNamesInResults is used to filter out duplicates with exactly
      // the same domain name from the results.
      final Set<String> uniqueDomainNamesInResults = <String>{};

      // Listen for mDNS connections until timeout.
      final Stream<PtrResourceRecord> ptrResourceStream = client.lookup<PtrResourceRecord>(
        ResourceRecordQuery.serverPointer(dartVmServiceName),
        timeout: timeout
      );
      await for (final PtrResourceRecord ptr in ptrResourceStream) {
        uniqueDomainNames.add(ptr.domainName);

        String? domainName;
        if (applicationId != null) {
          // If applicationId is set, only use records that match it
          if (ptr.domainName.toLowerCase().startsWith(applicationId.toLowerCase())) {
            domainName = ptr.domainName;
          } else {
            continue;
          }
        } else {
          domainName = ptr.domainName;
        }

        // Result with same domain name was already found, skip it.
        if (uniqueDomainNamesInResults.contains(domainName)) {
          continue;
        }

        _logger.printTrace('Checking for available port on $domainName');
        final List<SrvResourceRecord> srvRecords = await client
          .lookup<SrvResourceRecord>(
            ResourceRecordQuery.service(domainName),
          )
          .toList();
        if (srvRecords.isEmpty) {
          continue;
        }

        // If more than one SrvResourceRecord found, it should just be a duplicate.
        final SrvResourceRecord srvRecord = srvRecords.first;
        if (srvRecords.length > 1) {
          _logger.printWarning(
              'Unexpectedly found more than one Dart VM Service report for $domainName '
              '- using first one (${srvRecord.port}).');
        }

        // If deviceVmservicePort is set, only use records that match it
        if (deviceVmservicePort != null && srvRecord.port != deviceVmservicePort) {
          continue;
        }

        // Get the IP address of the service if using a network device.
        InternetAddress? ipAddress;
        if (isNetworkDevice) {
          List<IPAddressResourceRecord> ipAddresses = await client
            .lookup<IPAddressResourceRecord>(
              ipv6
                  ? ResourceRecordQuery.addressIPv6(srvRecord.target)
                  : ResourceRecordQuery.addressIPv4(srvRecord.target),
            )
            .toList();
          if (ipAddresses.isEmpty) {
            throwToolExit('Did not find IP for service ${srvRecord.target}.');
          }

          // Filter out link-local addresses.
          if (ipAddresses.length > 1) {
            ipAddresses = ipAddresses.where((IPAddressResourceRecord element) => !element.address.isLinkLocal).toList();
          }

          ipAddress = ipAddresses.first.address;
          if (ipAddresses.length > 1) {
            _logger.printWarning(
                'Unexpectedly found more than one IP for Dart VM Service ${srvRecord.target} '
                '- using first one ($ipAddress).');
          }
        }

        _logger.printTrace('Checking for authentication code for $domainName');
        final List<TxtResourceRecord> txt = await client
          .lookup<TxtResourceRecord>(
              ResourceRecordQuery.text(domainName),
          )
          .toList();

        String authCode = '';
        if (txt.isNotEmpty) {
          authCode = _getAuthCode(txt.first.text);
        }
        results.add(MDnsVmServiceDiscoveryResult(
          domainName,
          srvRecord.port,
          authCode,
          ipAddress: ipAddress
        ));
        uniqueDomainNamesInResults.add(domainName);
        if (quitOnFind) {
          return results;
        }
      }

      // If applicationId is set and quitOnFind is true and no results matching
      // the applicationId were found but other results were found, throw an error.
      if (applicationId != null &&
          quitOnFind &&
          results.isEmpty &&
          uniqueDomainNames.isNotEmpty) {
        String message = 'Did not find a Dart VM Service advertised for $applicationId';
        if (deviceVmservicePort != null) {
          message += ' on port $deviceVmservicePort';
        }
        throwToolExit('$message.');
      }

      return results;
    } finally {
      client.stop();
    }
  }

  String _getAuthCode(String txtRecord) {
    const String authCodePrefix = 'authCode=';
    final Iterable<String> matchingRecords =
        LineSplitter.split(txtRecord).where((String record) => record.startsWith(authCodePrefix));
    if (matchingRecords.isEmpty) {
      return '';
    }
    String authCode = matchingRecords.first.substring(authCodePrefix.length);
    // The Dart VM Service currently expects a trailing '/' as part of the
    // URI, otherwise an invalid authentication code response is given.
    if (!authCode.endsWith('/')) {
      authCode += '/';
    }
    return authCode;
  }

  /// Gets Dart VM Service Uri for `flutter attach`.
  /// Executes an mDNS query and waits until a Dart VM Service is found.
  ///
  /// Differs from `getVMServiceUriForLaunch` because it can search for any available Dart VM Service.
  /// Since [applicationId] and [deviceVmservicePort] are optional, it can either look for any service
  /// or a specific service matching [applicationId]/[deviceVmservicePort].
  /// It may find more than one service, which will throw an error listing the found services.
  Future<Uri?> getVMServiceUriForAttach(
    String? applicationId,
    Device device, {
    bool usesIpv6 = false,
    int? hostVmservicePort,
    int? deviceVmservicePort,
    bool isNetworkDevice = false,
    Duration timeout = const Duration(minutes: 10),
  }) async {
    final MDnsVmServiceDiscoveryResult? result = await queryForAttach(
      applicationId: applicationId,
      deviceVmservicePort: deviceVmservicePort,
      ipv6: usesIpv6,
      isNetworkDevice: isNetworkDevice,
      timeout: timeout,
    );
    return _handleResult(
      result,
      device,
      applicationId: applicationId,
      deviceVmservicePort: deviceVmservicePort,
      hostVmservicePort: hostVmservicePort,
      usesIpv6: usesIpv6,
      isNetworkDevice: isNetworkDevice
    );
  }

  /// Gets Dart VM Service Uri for `flutter run`.
  /// Executes an mDNS query and waits until the Dart VM Service service is found.
  ///
  /// Differs from `getVMServiceUriForAttach` because it only searches for a specific service.
  /// This is enforced by [applicationId] and [deviceVmservicePort] being required.
  Future<Uri?> getVMServiceUriForLaunch(
    String applicationId,
    Device device, {
    bool usesIpv6 = false,
    int? hostVmservicePort,
    required int deviceVmservicePort,
    bool isNetworkDevice = false,
    Duration timeout = const Duration(minutes: 10),
  }) async {
    final MDnsVmServiceDiscoveryResult? result = await queryForLaunch(
      applicationId: applicationId,
      deviceVmservicePort: deviceVmservicePort,
      ipv6: usesIpv6,
      isNetworkDevice: isNetworkDevice,
      timeout: timeout,
    );
    return _handleResult(
      result,
      device,
      applicationId: applicationId,
      deviceVmservicePort: deviceVmservicePort,
      hostVmservicePort: hostVmservicePort,
      usesIpv6: usesIpv6,
      isNetworkDevice: isNetworkDevice
    );
  }

  Future<Uri?> _handleResult(
    MDnsVmServiceDiscoveryResult? result,
    Device device, {
    String? applicationId,
    int? deviceVmservicePort,
    int? hostVmservicePort,
    bool usesIpv6 = false,
    bool isNetworkDevice = false,
  }) async {
    if (result == null) {
      await _checkForIPv4LinkLocal(device);
      return null;
    }
    final String host;

    final InternetAddress? ipAddress = result.ipAddress;
    if (isNetworkDevice && ipAddress != null) {
      host = ipAddress.address;
    } else {
      host = usesIpv6
      ? InternetAddress.loopbackIPv6.address
      : InternetAddress.loopbackIPv4.address;
    }
    return buildVMServiceUri(
      device,
      host,
      result.port,
      hostVmservicePort,
      result.authCode,
      isNetworkDevice,
    );
  }

  // If there's not an ipv4 link local address in `NetworkInterfaces.list`,
  // then request user interventions with a `printError()` if possible.
  Future<void> _checkForIPv4LinkLocal(Device device) async {
    _logger.printTrace(
      'mDNS query failed. Checking for an interface with a ipv4 link local address.'
    );
    final List<NetworkInterface> interfaces = await listNetworkInterfaces(
      includeLinkLocal: true,
      type: InternetAddressType.IPv4,
    );
    if (_logger.isVerbose) {
      _logInterfaces(interfaces);
    }
    final bool hasIPv4LinkLocal = interfaces.any(
      (NetworkInterface interface) => interface.addresses.any(
        (InternetAddress address) => address.isLinkLocal,
      ),
    );
    if (hasIPv4LinkLocal) {
      _logger.printTrace('An interface with an ipv4 link local address was found.');
      return;
    }
    final TargetPlatform targetPlatform = await device.targetPlatform;
    switch (targetPlatform) {
      case TargetPlatform.ios:
        UsageEvent('ios-mdns', 'no-ipv4-link-local', flutterUsage: _flutterUsage).send();
        _logger.printError(
          'The mDNS query for an attached iOS device failed. It may '
          'be necessary to disable the "Personal Hotspot" on the device, and '
          'to ensure that the "Disable unless needed" setting is unchecked '
          'under System Preferences > Network > iPhone USB. '
          'See https://github.com/flutter/flutter/issues/46698 for details.'
        );
        break;
      case TargetPlatform.android:
      case TargetPlatform.android_arm:
      case TargetPlatform.android_arm64:
      case TargetPlatform.android_x64:
      case TargetPlatform.android_x86:
      case TargetPlatform.darwin:
      case TargetPlatform.fuchsia_arm64:
      case TargetPlatform.fuchsia_x64:
      case TargetPlatform.linux_arm64:
      case TargetPlatform.linux_x64:
      case TargetPlatform.tester:
      case TargetPlatform.web_javascript:
      case TargetPlatform.windows_x64:
        _logger.printTrace('No interface with an ipv4 link local address was found.');
        break;
    }
  }

  void _logInterfaces(List<NetworkInterface> interfaces) {
    for (final NetworkInterface interface in interfaces) {
      if (_logger.isVerbose) {
        _logger.printTrace('Found interface "${interface.name}":');
        for (final InternetAddress address in interface.addresses) {
          final String linkLocal = address.isLinkLocal ? 'link local' : '';
          _logger.printTrace('\tBound address: "${address.address}" $linkLocal');
        }
      }
    }
  }
}

class MDnsVmServiceDiscoveryResult {
  MDnsVmServiceDiscoveryResult(
    this.domainName,
    this.port,
    this.authCode, {
    this.ipAddress
  });
  final String domainName;
  final int port;
  final String authCode;
  final InternetAddress? ipAddress;
}

Future<Uri> buildVMServiceUri(
  Device device,
  String host,
  int devicePort, [
  int? hostVmservicePort,
  String? authCode,
  bool isNetworkDevice = false,
]) async {
  String path = '/';
  if (authCode != null) {
    path = authCode;
  }
  // Not having a trailing slash can cause problems in some situations.
  // Ensure that there's one present.
  if (!path.endsWith('/')) {
    path += '/';
  }
  hostVmservicePort ??= 0;

  final int? actualHostPort;
  if (isNetworkDevice) {
    // When debugging with a network device, port forwarding is not required
    // so just use the device's port.
    actualHostPort = devicePort;
  } else {
    actualHostPort = hostVmservicePort == 0 ?
    await device.portForwarder?.forward(devicePort) :
    hostVmservicePort;
  }
  return Uri(scheme: 'http', host: host, port: actualHostPort, path: path);
}
