// 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.

// @dart = 2.8

import 'dart:async';

import 'package:dds/dds.dart' as dds;
import 'package:file/file.dart';
import 'package:meta/meta.dart';
import 'package:package_config/package_config_types.dart';
import 'package:vm_service/vm_service.dart' as vm_service;

import '../application_package.dart';
import '../base/common.dart';
import '../base/logger.dart';
import '../base/process.dart';
import '../build_info.dart';
import '../device.dart';
import '../resident_runner.dart';
import '../sksl_writer.dart';
import '../vmservice.dart';
import 'web_driver_service.dart';

class FlutterDriverFactory {
  FlutterDriverFactory({
    @required ApplicationPackageFactory applicationPackageFactory,
    @required Logger logger,
    @required ProcessUtils processUtils,
    @required String dartSdkPath,
    @required DevtoolsLauncher devtoolsLauncher,
  }) : _applicationPackageFactory = applicationPackageFactory,
       _logger = logger,
       _processUtils = processUtils,
       _dartSdkPath = dartSdkPath,
       _devtoolsLauncher = devtoolsLauncher;

  final ApplicationPackageFactory _applicationPackageFactory;
  final Logger _logger;
  final ProcessUtils _processUtils;
  final String _dartSdkPath;
  final DevtoolsLauncher _devtoolsLauncher;

  /// Create a driver service for running `flutter drive`.
  DriverService createDriverService(bool web) {
    if (web) {
      return WebDriverService(
        logger: _logger,
        processUtils: _processUtils,
        dartSdkPath: _dartSdkPath,
      );
    }
    return FlutterDriverService(
      logger: _logger,
      processUtils: _processUtils,
      dartSdkPath: _dartSdkPath,
      applicationPackageFactory: _applicationPackageFactory,
      devtoolsLauncher: _devtoolsLauncher,
    );
  }
}

/// An interface for the `flutter driver` integration test operations.
abstract class DriverService {
  /// Install and launch the application for the provided [device].
  Future<void> start(
    BuildInfo buildInfo,
    Device device,
    DebuggingOptions debuggingOptions,
    bool ipv6, {
    File applicationBinary,
    String route,
    String userIdentifier,
    String mainPath,
    Map<String, Object> platformArgs = const <String, Object>{},
  });

  /// If --use-existing-app is provided, configured the correct VM Service URI.
  Future<void> reuseApplication(
    Uri vmServiceUri,
    Device device,
    DebuggingOptions debuggingOptions,
    bool ipv6,
  );

  /// Start the test file with the provided [arguments] and [environment], returning
  /// the test process exit code.
  ///
  /// if [profileMemory] is provided, it will be treated as a file path to write a
  /// devtools memory profile.
  Future<int> startTest(
    String testFile,
    List<String> arguments,
    Map<String, String> environment,
    PackageConfig packageConfig, {
    bool headless,
    String chromeBinary,
    String browserName,
    bool androidEmulator,
    int driverPort,
    List<String> browserDimension,
    String profileMemory,
  });

  /// Stop the running application and uninstall it from the device.
  ///
  /// If [writeSkslOnExit] is non-null, will connect to the VM Service
  /// and write SkSL to the file. This is only supported on mobile and
  /// desktop devices.
  Future<void> stop({
    File writeSkslOnExit,
    String userIdentifier,
  });
}

/// An implementation of the driver service that connects to mobile and desktop
/// applications.
class FlutterDriverService extends DriverService {
  FlutterDriverService({
    @required ApplicationPackageFactory applicationPackageFactory,
    @required Logger logger,
    @required ProcessUtils processUtils,
    @required String dartSdkPath,
    @required DevtoolsLauncher devtoolsLauncher,
    @visibleForTesting VMServiceConnector vmServiceConnector = connectToVmService,
  }) : _applicationPackageFactory = applicationPackageFactory,
       _logger = logger,
       _processUtils = processUtils,
       _dartSdkPath = dartSdkPath,
       _vmServiceConnector = vmServiceConnector,
       _devtoolsLauncher = devtoolsLauncher;

  static const int _kLaunchAttempts = 3;

  final ApplicationPackageFactory _applicationPackageFactory;
  final Logger _logger;
  final ProcessUtils _processUtils;
  final String _dartSdkPath;
  final VMServiceConnector _vmServiceConnector;
  final DevtoolsLauncher _devtoolsLauncher;

  Device _device;
  ApplicationPackage _applicationPackage;
  String _vmServiceUri;
  FlutterVmService _vmService;

  @override
  Future<void> start(
    BuildInfo buildInfo,
    Device device,
    DebuggingOptions debuggingOptions,
    bool ipv6, {
    File applicationBinary,
    String route,
    String userIdentifier,
    Map<String, Object> platformArgs = const <String, Object>{},
    String mainPath,
  }) async {
    if (buildInfo.isRelease) {
      throwToolExit(
        'Flutter Driver (non-web) does not support running in release mode.\n'
        '\n'
        'Use --profile mode for testing application performance.\n'
        'Use --debug (default) mode for testing correctness (with assertions).'
      );
    }
    _device = device;
    final TargetPlatform targetPlatform = await device.targetPlatform;
    _applicationPackage = await _applicationPackageFactory.getPackageForPlatform(
      targetPlatform,
      buildInfo: buildInfo,
      applicationBinary: applicationBinary,
    );
    int attempt = 0;
    LaunchResult result;
    bool prebuiltApplication = applicationBinary != null;
    while (attempt < _kLaunchAttempts) {
      result = await device.startApp(
        _applicationPackage,
        mainPath: mainPath,
        route: route,
        debuggingOptions: debuggingOptions,
        platformArgs: platformArgs,
        userIdentifier: userIdentifier,
        prebuiltApplication: prebuiltApplication,
      );
      if (result != null && result.started) {
        break;
      }
      // On attempts past 1, assume the application is built correctly and re-use it.
      attempt += 1;
      prebuiltApplication = true;
      _logger.printError('Application failed to start on attempt: $attempt');
    }
    if (result == null || !result.started) {
      throwToolExit('Application failed to start. Will not run test. Quitting.', exitCode: 1);
    }
    return reuseApplication(
      result.observatoryUri,
      device,
      debuggingOptions,
      ipv6,
    );
  }

  @override
  Future<void> reuseApplication(
    Uri vmServiceUri,
    Device device,
    DebuggingOptions debuggingOptions,
    bool ipv6,
  ) async {
    Uri uri;
    if (vmServiceUri.scheme == 'ws') {
      final List<String> segments = vmServiceUri.pathSegments.toList();
      segments.remove('ws');
      uri = vmServiceUri.replace(scheme: 'http', path: segments.join('/'));
    } else {
      uri = vmServiceUri;
    }
    _vmServiceUri = uri.toString();
    _device = device;
    if (debuggingOptions.enableDds) {
      try {
        await device.dds.startDartDevelopmentService(
          uri,
          debuggingOptions.ddsPort,
          ipv6,
          debuggingOptions.disableServiceAuthCodes,
          logger: _logger,
        );
        _vmServiceUri = device.dds.uri.toString();
      } on dds.DartDevelopmentServiceException {
        // If there's another flutter_tools instance still connected to the target
        // application, DDS will already be running remotely and this call will fail.
        // This can be ignored to continue to use the existing remote DDS instance.
      }
    }
    _vmService = await _vmServiceConnector(uri, device: _device, logger: _logger);
    final DeviceLogReader logReader = await device.getLogReader(app: _applicationPackage);
    logReader.logLines.listen(_logger.printStatus);

    final vm_service.VM vm = await _vmService.service.getVM();
    logReader.appPid = vm.pid;
  }

  @override
  Future<int> startTest(
    String testFile,
    List<String> arguments,
    Map<String, String> environment,
    PackageConfig packageConfig, {
    bool headless,
    String chromeBinary,
    String browserName,
    bool androidEmulator,
    int driverPort,
    List<String> browserDimension,
    String profileMemory,
  }) async {
    if (profileMemory != null) {
      unawaited(_devtoolsLauncher.launch(
        Uri.parse(_vmServiceUri),
        additionalArguments: <String>['--record-memory-profile=$profileMemory'],
      ));
      // When profiling memory the original launch future will never complete.
      await _devtoolsLauncher.processStart;
    }
    try {
      final int result = await _processUtils.stream(<String>[
        _dartSdkPath,
        ...<String>[...arguments, testFile, '-rexpanded'],
      ], environment: <String, String>{
        'VM_SERVICE_URL': _vmServiceUri,
        ...environment,
      });
      return result;
    } finally {
      if (profileMemory != null) {
        await _devtoolsLauncher.close();
      }
    }
  }

  @override
  Future<void> stop({
    File writeSkslOnExit,
    String userIdentifier,
  }) async {
    if (writeSkslOnExit != null) {
      final FlutterView flutterView = (await _vmService.getFlutterViews()).first;
      final Map<String, Object> result = await _vmService.getSkSLs(
        viewId: flutterView.id
      );
      await sharedSkSlWriter(_device, result, outputFile: writeSkslOnExit, logger: _logger);
    }
    // If the application package is available, stop and uninstall.
    if (_applicationPackage != null) {
      if (!await _device.stopApp(_applicationPackage, userIdentifier: userIdentifier)) {
        _logger.printError('Failed to stop app');
      }
      if (!await _device.uninstallApp(_applicationPackage, userIdentifier: userIdentifier)) {
        _logger.printError('Failed to uninstall app');
      }
    } else if (_device.supportsFlutterExit) {
      // Otherwise use the VM Service URI to stop the app as a best effort approach.
      final vm_service.VM vm = await _vmService.service.getVM();
      final vm_service.IsolateRef isolateRef = vm.isolates
        .firstWhere((vm_service.IsolateRef element) {
          return !element.isSystemIsolate;
        }, orElse: () => null);
      unawaited(_vmService.flutterExit(isolateId: isolateRef.id));
    } else {
      _logger.printTrace('No application package for $_device, leaving app running');
    }
    await _device.dispose();
  }
}
