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

import 'package:file/file.dart';
import 'package:platform/platform.dart';

import 'common/core.dart';
import 'common/package_looping_command.dart';
import 'common/plugin_utils.dart';
import 'common/process_runner.dart';
import 'common/repository_package.dart';

const int _exitNoPlatformFlags = 2;
const int _exitNoAvailableDevice = 3;

/// A command to run the example applications for packages via Flutter driver.
class DriveExamplesCommand extends PackageLoopingCommand {
  /// Creates an instance of the drive command.
  DriveExamplesCommand(
    Directory packagesDir, {
    ProcessRunner processRunner = const ProcessRunner(),
    Platform platform = const LocalPlatform(),
  }) : super(packagesDir, processRunner: processRunner, platform: platform) {
    argParser.addFlag(platformAndroid,
        help: 'Runs the Android implementation of the examples');
    argParser.addFlag(platformIOS,
        help: 'Runs the iOS implementation of the examples');
    argParser.addFlag(platformLinux,
        help: 'Runs the Linux implementation of the examples');
    argParser.addFlag(platformMacOS,
        help: 'Runs the macOS implementation of the examples');
    argParser.addFlag(platformWeb,
        help: 'Runs the web implementation of the examples');
    argParser.addFlag(platformWindows,
        help: 'Runs the Windows implementation of the examples');
    argParser.addOption(
      kEnableExperiment,
      defaultsTo: '',
      help:
          'Runs the driver tests in Dart VM with the given experiments enabled.',
    );
  }

  @override
  final String name = 'drive-examples';

  @override
  final String description = 'Runs driver tests for plugin example apps.\n\n'
      'For each *_test.dart in test_driver/ it drives an application with '
      'either the corresponding test in test_driver (for example, '
      'test_driver/app_test.dart would match test_driver/app.dart), or the '
      '*_test.dart files in integration_test/.\n\n'
      'This command requires "flutter" to be in your path.';

  Map<String, List<String>> _targetDeviceFlags = const <String, List<String>>{};

  @override
  Future<void> initializeRun() async {
    final List<String> platformSwitches = <String>[
      platformAndroid,
      platformIOS,
      platformLinux,
      platformMacOS,
      platformWeb,
      platformWindows,
    ];
    final int platformCount = platformSwitches
        .where((String platform) => getBoolArg(platform))
        .length;
    // The flutter tool currently doesn't accept multiple device arguments:
    // https://github.com/flutter/flutter/issues/35733
    // If that is implemented, this check can be relaxed.
    if (platformCount != 1) {
      printError(
          'Exactly one of ${platformSwitches.map((String platform) => '--$platform').join(', ')} '
          'must be specified.');
      throw ToolExit(_exitNoPlatformFlags);
    }

    String? androidDevice;
    if (getBoolArg(platformAndroid)) {
      final List<String> devices = await _getDevicesForPlatform('android');
      if (devices.isEmpty) {
        printError('No Android devices available');
        throw ToolExit(_exitNoAvailableDevice);
      }
      androidDevice = devices.first;
    }

    String? iOSDevice;
    if (getBoolArg(platformIOS)) {
      final List<String> devices = await _getDevicesForPlatform('ios');
      if (devices.isEmpty) {
        printError('No iOS devices available');
        throw ToolExit(_exitNoAvailableDevice);
      }
      iOSDevice = devices.first;
    }

    _targetDeviceFlags = <String, List<String>>{
      if (getBoolArg(platformAndroid))
        platformAndroid: <String>['-d', androidDevice!],
      if (getBoolArg(platformIOS)) platformIOS: <String>['-d', iOSDevice!],
      if (getBoolArg(platformLinux)) platformLinux: <String>['-d', 'linux'],
      if (getBoolArg(platformMacOS)) platformMacOS: <String>['-d', 'macos'],
      if (getBoolArg(platformWeb))
        platformWeb: <String>[
          '-d',
          'web-server',
          '--web-port=7357',
          '--browser-name=chrome',
          if (platform.environment.containsKey('CHROME_EXECUTABLE'))
            '--chrome-binary=${platform.environment['CHROME_EXECUTABLE']}',
        ],
      if (getBoolArg(platformWindows))
        platformWindows: <String>['-d', 'windows'],
    };
  }

  @override
  Future<PackageResult> runForPackage(RepositoryPackage package) async {
    if (package.isPlatformInterface &&
        !package.getSingleExampleDeprecated().directory.existsSync()) {
      // Platform interface packages generally aren't intended to have
      // examples, and don't need integration tests, so skip rather than fail.
      return PackageResult.skip(
          'Platform interfaces are not expected to have integration tests.');
    }

    final List<String> deviceFlags = <String>[];
    for (final MapEntry<String, List<String>> entry
        in _targetDeviceFlags.entries) {
      final String platform = entry.key;
      if (pluginSupportsPlatform(platform, package)) {
        deviceFlags.addAll(entry.value);
      } else {
        print('Skipping unsupported platform ${entry.key}...');
      }
    }
    // If there is no supported target platform, skip the plugin.
    if (deviceFlags.isEmpty) {
      return PackageResult.skip(
          '${package.displayName} does not support any requested platform.');
    }

    int examplesFound = 0;
    bool testsRan = false;
    final List<String> errors = <String>[];
    for (final RepositoryPackage example in package.getExamples()) {
      ++examplesFound;
      final String exampleName =
          getRelativePosixPath(example.directory, from: packagesDir);

      final List<File> drivers = await _getDrivers(example);
      if (drivers.isEmpty) {
        print('No driver tests found for $exampleName');
        continue;
      }

      for (final File driver in drivers) {
        final List<File> testTargets = <File>[];

        // Try to find a matching app to drive without the _test.dart
        // TODO(stuartmorgan): Migrate all remaining uses of this legacy
        // approach (currently only video_player) and remove support for it:
        // https://github.com/flutter/flutter/issues/85224.
        final File? legacyTestFile = _getLegacyTestFileForTestDriver(driver);
        if (legacyTestFile != null) {
          testTargets.add(legacyTestFile);
        } else {
          (await _getIntegrationTests(example)).forEach(testTargets.add);
        }

        if (testTargets.isEmpty) {
          final String driverRelativePath =
              getRelativePosixPath(driver, from: package.directory);
          printError(
              'Found $driverRelativePath, but no integration_test/*_test.dart files.');
          errors.add('No test files for $driverRelativePath');
          continue;
        }

        testsRan = true;
        final List<File> failingTargets = await _driveTests(
            example, driver, testTargets,
            deviceFlags: deviceFlags);
        for (final File failingTarget in failingTargets) {
          errors.add(
              getRelativePosixPath(failingTarget, from: package.directory));
        }
      }
    }
    if (!testsRan) {
      printError('No driver tests were run ($examplesFound example(s) found).');
      errors.add('No tests ran (use --exclude if this is intentional).');
    }
    return errors.isEmpty
        ? PackageResult.success()
        : PackageResult.fail(errors);
  }

  Future<List<String>> _getDevicesForPlatform(String platform) async {
    final List<String> deviceIds = <String>[];

    final ProcessResult result = await processRunner.run(
        flutterCommand, <String>['devices', '--machine'],
        stdoutEncoding: utf8);
    if (result.exitCode != 0) {
      return deviceIds;
    }

    String output = result.stdout as String;
    // --machine doesn't currently prevent the tool from printing banners;
    // see https://github.com/flutter/flutter/issues/86055. This workaround
    // can be removed once that is fixed.
    output = output.substring(output.indexOf('['));

    final List<Map<String, dynamic>> devices =
        (jsonDecode(output) as List<dynamic>).cast<Map<String, dynamic>>();
    for (final Map<String, dynamic> deviceInfo in devices) {
      final String targetPlatform =
          (deviceInfo['targetPlatform'] as String?) ?? '';
      if (targetPlatform.startsWith(platform)) {
        final String? deviceId = deviceInfo['id'] as String?;
        if (deviceId != null) {
          deviceIds.add(deviceId);
        }
      }
    }
    return deviceIds;
  }

  Future<List<File>> _getDrivers(RepositoryPackage example) async {
    final List<File> drivers = <File>[];

    final Directory driverDir = example.directory.childDirectory('test_driver');
    if (driverDir.existsSync()) {
      await for (final FileSystemEntity driver in driverDir.list()) {
        if (driver is File && driver.basename.endsWith('_test.dart')) {
          drivers.add(driver);
        }
      }
    }
    return drivers;
  }

  File? _getLegacyTestFileForTestDriver(File testDriver) {
    final String testName = testDriver.basename.replaceAll(
      RegExp(r'_test.dart$'),
      '.dart',
    );
    final File testFile = testDriver.parent.childFile(testName);

    return testFile.existsSync() ? testFile : null;
  }

  Future<List<File>> _getIntegrationTests(RepositoryPackage example) async {
    final List<File> tests = <File>[];
    final Directory integrationTestDir =
        example.directory.childDirectory('integration_test');

    if (integrationTestDir.existsSync()) {
      await for (final FileSystemEntity file in integrationTestDir.list()) {
        if (file is File && file.basename.endsWith('_test.dart')) {
          tests.add(file);
        }
      }
    }
    return tests;
  }

  /// For each file in [targets], uses
  /// `flutter drive --driver [driver] --target <target>`
  /// to drive [example], returning a list of any failing test targets.
  ///
  /// [deviceFlags] should contain the flags to run the test on a specific
  /// target device (plus any supporting device-specific flags). E.g.:
  ///   - `['-d', 'macos']` for driving for macOS.
  ///   - `['-d', 'web-server', '--web-port=<port>', '--browser-name=<browser>]`
  ///     for web
  Future<List<File>> _driveTests(
    RepositoryPackage example,
    File driver,
    List<File> targets, {
    required List<String> deviceFlags,
  }) async {
    final List<File> failures = <File>[];

    final String enableExperiment = getStringArg(kEnableExperiment);

    for (final File target in targets) {
      final int exitCode = await processRunner.runAndStream(
          flutterCommand,
          <String>[
            'drive',
            ...deviceFlags,
            if (enableExperiment.isNotEmpty)
              '--enable-experiment=$enableExperiment',
            '--driver',
            getRelativePosixPath(driver, from: example.directory),
            '--target',
            getRelativePosixPath(target, from: example.directory),
          ],
          workingDir: example.directory);
      if (exitCode != 0) {
        failures.add(target);
      }
    }
    return failures;
  }
}
