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

import 'package:path/path.dart' as path;

import '../framework/framework.dart';
import '../framework/ios.dart';
import '../framework/task_result.dart';
import '../framework/utils.dart';

/// Combines several TaskFunctions with trivial success value into one.
TaskFunction combine(List<TaskFunction> tasks) {
  return () async {
    for (final task in tasks) {
      final TaskResult result = await task();
      if (result.failed) {
        return result;
      }
    }
    return TaskResult.success(null);
  };
}

/// Defines task that creates new Flutter project, adds a local and remote
/// plugin, and then builds the specified [buildTarget].
class PluginTest {
  PluginTest(
    this.buildTarget,
    this.options, {
    this.pluginCreateEnvironment,
    this.appCreateEnvironment,
    this.dartOnlyPlugin = false,
    this.template = 'plugin',
    this.cocoapodsTransitiveFlutterDependency = false,
  });

  final String buildTarget;
  final List<String> options;
  final Map<String, String>? pluginCreateEnvironment;
  final Map<String, String>? appCreateEnvironment;
  final bool dartOnlyPlugin;
  final String template;
  final bool cocoapodsTransitiveFlutterDependency;

  Future<TaskResult> call() async {
    final Directory tempDir = Directory.systemTemp.createTempSync('flutter_devicelab_plugin_test.');
    // FFI plugins do not have support for `flutter test`.
    // `flutter test` does not do a native build.
    // Supporting `flutter test` would require invoking a native build.
    final runFlutterTest = template != 'plugin_ffi';
    try {
      section('Create plugin');
      final _FlutterProject plugin = await _FlutterProject.create(
        tempDir,
        options,
        buildTarget,
        name: 'plugintest',
        template: template,
        environment: pluginCreateEnvironment,
      );
      if (dartOnlyPlugin) {
        await plugin.convertDefaultPluginToDartPlugin();
      }
      section('Test plugin');
      if (runFlutterTest) {
        await plugin.runFlutterTest();
        if (!dartOnlyPlugin) {
          await plugin.example.runNativeTests(buildTarget);
          if (buildTarget == 'ios') {
            var runResult = false;
            await testWithNewIOSSimulator('TestPluginExample', (String deviceId) async {
              runResult = await plugin.example.runApp(options: <String>['-d', deviceId]);
            });
            if (!runResult) {
              return TaskResult.failure('flutter run either failed or had an engine error.');
            }
          }
        }
      }
      section('Create Flutter app');
      final _FlutterProject app = await _FlutterProject.create(
        tempDir,
        options,
        buildTarget,
        name: 'plugintestapp',
        template: 'app',
        environment: appCreateEnvironment,
      );
      try {
        if (cocoapodsTransitiveFlutterDependency) {
          section('Disable Swift Package Manager');
          await app.disableSwiftPackageManager();
        }

        section('Add plugins');
        await app.addPlugin('plugintest', pluginPath: path.join('..', 'plugintest'));
        await app.addPlugin('path_provider');
        section('Build app');
        await app.build(buildTarget, validateNativeBuildProject: !dartOnlyPlugin);
        if (cocoapodsTransitiveFlutterDependency) {
          section('Test app with Flutter as a transitive CocoaPods dependency');
          await app.addCocoapodsTransitiveFlutterDependency();
          await app.build(buildTarget, validateNativeBuildProject: !dartOnlyPlugin);
        }
        if (runFlutterTest) {
          section('Test app');
          await app.runFlutterTest();
        }
        // Validate local engine handling. Currently only implemented for macOS.
        if (!dartOnlyPlugin) {
          section('Validate local engine configuration');
          final String fakeEngineSourcePath = path.join(tempDir.path, 'engine');
          await _testLocalEngineConfiguration(app, fakeEngineSourcePath);
        }
      } finally {
        await plugin.delete();
        await app.delete();
      }
      return TaskResult.success(null);
    } catch (e) {
      return TaskResult.failure(e.toString());
    } finally {
      rmTree(tempDir);
    }
  }

  Future<void> _testLocalEngineConfiguration(
    _FlutterProject app,
    String fakeEngineSourcePath,
  ) async {
    // The tool requires that a directory that looks like an engine build
    // actually exists when passing --local-engine, so create a fake skeleton.
    final buildDir = Directory(path.join(fakeEngineSourcePath, 'out', 'foo'));
    buildDir.createSync(recursive: true);
    // Currently this test is only implemented for macOS; it can be extended to
    // others as needed.
    if (buildTarget == 'macos') {
      // When using a local engine, podhelper.rb will search for a "macos-"
      // directory within the FlutterMacOS.xcframework, so create a dummy one.
      Directory(path.join(buildDir.path, 'FlutterMacOS.xcframework/macos-arm64_x86_64'))
          .createSync(recursive: true);

      // Clean before regenerating the config to ensure that the pod steps run.
      await inDirectory(Directory(app.rootPath), () async {
        await evalFlutter('clean');
      });
      await app.build(buildTarget, configOnly: true, localEngine: buildDir);
    }
  }
}

class _FlutterProject {
  _FlutterProject(this.parent, this.name);

  final Directory parent;
  final String name;

  String get rootPath => path.join(parent.path, name);

  File get pubspecFile => File(path.join(rootPath, 'pubspec.yaml'));

  _FlutterProject get example {
    return _FlutterProject(Directory(path.join(rootPath)), 'example');
  }

  Future<void> disableSwiftPackageManager() async {
    final File pubspec = pubspecFile;
    String content = await pubspec.readAsString();
    content = content.replaceFirst(
      '# The following section is specific to Flutter packages.\n'
          'flutter:\n',
      '# The following section is specific to Flutter packages.\n'
          'flutter:\n'
          '\n'
          '  config:\n'
          '    enable-swift-package-manager: false\n',
    );
    await pubspec.writeAsString(content, flush: true);
  }

  Future<void> addPlugin(String plugin, {String? pluginPath}) async {
    final File pubspec = pubspecFile;
    String content = await pubspec.readAsString();
    final dependency = pluginPath != null ? '$plugin:\n    path: $pluginPath' : '$plugin:';
    content = content.replaceFirst('\ndependencies:\n', '\ndependencies:\n  $dependency\n');
    await pubspec.writeAsString(content, flush: true);
  }

  /// Converts a plugin created from the standard template to a Dart-only
  /// plugin.
  Future<void> convertDefaultPluginToDartPlugin() async {
    final dartPluginClass = 'DartClassFor$name';
    // Convert the metadata.
    final File pubspec = pubspecFile;
    String content = await pubspec.readAsString();
    content = content.replaceAll(
      RegExp(r' pluginClass: .*?\n'),
      ' dartPluginClass: $dartPluginClass\n',
    );
    await pubspec.writeAsString(content, flush: true);

    // Add the Dart registration hook that the build will generate a call to.
    final dartCode = File(path.join(rootPath, 'lib', '$name.dart'));
    content = await dartCode.readAsString();
    content =
        '''
$content

class $dartPluginClass {
  static void registerWith() {}
}
''';
    await dartCode.writeAsString(content, flush: true);

    // Remove any native plugin code.
    const platforms = <String>['android', 'ios', 'linux', 'macos', 'windows'];
    for (final platform in platforms) {
      final platformDir = Directory(path.join(rootPath, platform));
      if (platformDir.existsSync()) {
        await platformDir.delete(recursive: true);
      }
    }
  }

  Future<void> runFlutterTest() async {
    await inDirectory(Directory(rootPath), () async {
      await flutter('test');
    });
  }

  Future<void> runNativeTests(String buildTarget) async {
    // Native unit tests rely on building the app first to generate necessary
    // build files.
    await build(buildTarget, validateNativeBuildProject: false, buildMode: 'debug');

    switch (buildTarget) {
      case 'apk':
        if (await exec(
              path.join('.', 'gradlew'),
              <String>['testDebugUnitTest'],
              workingDirectory: path.join(rootPath, 'android'),
              canFail: true,
            ) !=
            0) {
          throw TaskResult.failure('Platform unit tests failed');
        }
      case 'ios':
        String? simulatorDeviceId;
        try {
          await testWithNewIOSSimulator('TestNativeUnitTests', (String deviceId) async {
            simulatorDeviceId = deviceId;
            if (!await runXcodeTests(
              platformDirectory: path.join(rootPath, 'ios'),
              destination: 'id=$deviceId',
              configuration: 'Debug',
              testName: 'native_plugin_unit_tests_ios',
              skipCodesign: true,
            )) {
              throw TaskResult.failure('Platform unit tests failed');
            }
          });
        } finally {
          await removeIOSSimulator(simulatorDeviceId);
        }
      case 'linux':
        if (await exec(
              path.join(
                rootPath,
                'build',
                'linux',
                'x64',
                'debug',
                'plugins',
                'plugintest',
                'plugintest_test',
              ),
              <String>[],
              canFail: true,
            ) !=
            0) {
          throw TaskResult.failure('Platform unit tests failed');
        }
      case 'macos':
        if (!await runXcodeTests(
          platformDirectory: path.join(rootPath, 'macos'),
          destination: 'platform=macOS',
          configuration: 'Debug',
          testName: 'native_plugin_unit_tests_macos',
          extraOptions: <String>['-parallel-testing-enabled', 'NO'],
          skipCodesign: true,
        )) {
          throw TaskResult.failure('Platform unit tests failed');
        }
      case 'windows':
        final arch = Abi.current() == Abi.windowsX64 ? 'x64' : 'arm64';
        if (await exec(
              path.join(
                rootPath,
                'build',
                'windows',
                arch,
                'plugins',
                'plugintest',
                'Debug',
                'plugintest_test.exe',
              ),
              <String>[],
              canFail: true,
            ) !=
            0) {
          throw TaskResult.failure('Platform unit tests failed');
        }
    }
  }

  static Future<_FlutterProject> create(
    Directory directory,
    List<String> options,
    String target, {
    required String name,
    required String template,
    Map<String, String>? environment,
  }) async {
    final bool isDarwin = target == 'ios' || target == 'macos';
    await inDirectory(directory, () async {
      await flutter(
        'create',
        options: <String>[
          '--template=$template',
          '--org',
          'io.flutter.devicelab',
          if (template == 'app' && isDarwin) '--platforms=$target' else ...options,
          name,
        ],
        environment: environment,
      );
    });

    final project = _FlutterProject(directory, name);
    if (template == 'plugin' && isDarwin) {
      project._reduceDarwinPluginMinimumVersion(name, target);
    }
    return project;
  }

  /// Creates a Pod that uses a Flutter plugin as a dependency and therefore
  /// Flutter as a transitive dependency.
  Future<void> addCocoapodsTransitiveFlutterDependency() async {
    final String iosDirectoryPath = path.join(rootPath, 'ios');

    final nativePod = File(path.join(iosDirectoryPath, 'NativePod', 'NativePod.podspec'));
    nativePod.createSync(recursive: true);
    nativePod.writeAsStringSync('''
Pod::Spec.new do |s|
  s.name             = 'NativePod'
  s.version          = '1.0.0'
  s.summary          = 'A pod to test Flutter as a transitive dependency.'
  s.homepage         = 'https://flutter.dev'
  s.license          = { :type => 'BSD' }
  s.author           = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
  s.source           = { :path => '.' }
  s.source_files = "Classes", "Classes/**/*.{h,m}"
  s.dependency 'plugintest'
  s.ios.deployment_target = '15.0'
  s.osx.deployment_target = '12.0'
end
''');

    final nativePodClass = File(
      path.join(iosDirectoryPath, 'NativePod', 'Classes', 'NativePodTest.m'),
    );
    nativePodClass.createSync(recursive: true);
    nativePodClass.writeAsStringSync('''
#import <Flutter/Flutter.h>

@interface NativePodTest : NSObject

@end

@implementation NativePodTest

@end
''');

    final podfileFile = File(path.join(iosDirectoryPath, 'Podfile'));
    final List<String> podfileContents = podfileFile.readAsLinesSync();
    final int index = podfileContents.indexWhere(
      (String line) => line.contains('flutter_install_all_ios_pods'),
    );
    podfileContents.insert(index, "pod 'NativePod', :path => 'NativePod'");
    podfileFile.writeAsStringSync(podfileContents.join('\n'));
  }

  // Make the platform version artificially low to test that the "deployment
  // version too low" warning is never emitted.
  void _reduceDarwinPluginMinimumVersion(String plugin, String target) {
    var podspec = File(path.join(rootPath, target, '$plugin.podspec'));
    if (!podspec.existsSync()) {
      // Fallback to darwin directory for shared darwin plugins
      podspec = File(path.join(rootPath, 'darwin', '$plugin.podspec'));
    }
    if (!podspec.existsSync()) {
      throw TaskResult.failure('podspec file missing at ${podspec.path}');
    }
    String podspecContent = podspec.readAsStringSync();
    final bool isMultiPlatform = podspecContent.contains('s.osx.deployment_target');
    final String versionString;
    if (isMultiPlatform) {
      versionString = target == 'ios'
          ? "s.ios.deployment_target = '15.0'"
          : "s.osx.deployment_target = '12.0'";
    } else {
      versionString = target == 'ios' ? "s.platform = :ios, '15.0'" : "s.platform = :osx, '12.0'";
    }

    if (!podspecContent.contains(versionString)) {
      throw TaskResult.failure(
        'Update this test to match plugin minimum $target deployment version',
      );
    }
    // Add transitive dependency on AppAuth 1.6 targeting iOS 8 and macOS 10.9, which no longer builds in Xcode
    // to test the version is forced higher and builds.
    final String replacementContent;
    if (isMultiPlatform) {
      replacementContent = target == 'ios'
          ? "s.ios.deployment_target = '10.0'\n  s.dependency 'AppAuth', '1.6.0'"
          : "s.osx.deployment_target = '10.8'\n  s.dependency 'AppAuth', '1.6.0'";
    } else {
      replacementContent = target == 'ios'
          ? "s.platform = :ios, '10.0'\ns.dependency 'AppAuth', '1.6.0'"
          : "s.platform = :osx, '10.8'\ns.dependency 'AppAuth', '1.6.0'";
    }

    podspecContent = podspecContent.replaceFirst(versionString, replacementContent);
    podspec.writeAsStringSync(podspecContent, flush: true);
  }

  Future<void> build(
    String target, {
    bool validateNativeBuildProject = true,
    bool configOnly = false,
    String buildMode = 'release',
    Directory? localEngine,
  }) async {
    assert(const <String>{'debug', 'release', 'profile'}.contains(buildMode));
    await inDirectory(Directory(rootPath), () async {
      final String buildOutput = await evalFlutter(
        'build',
        options: <String>[
          target,
          '-v',
          if (target == 'ios') '--no-codesign',
          if (configOnly) '--config-only',
          if (buildMode != 'release') '--$buildMode',
          if (localEngine != null)
          // The engine directory is of the form <fake-source-path>/out/<fakename>,
          // which has to be broken up into the component flags.
          ...<String>[
            '--local-engine-src-path=${localEngine.parent.parent.path}',
            '--local-engine=${path.basename(localEngine.path)}',
            '--local-engine-host=${path.basename(localEngine.path)}',
          ],
        ],
      );

      if (target == 'ios' || target == 'macos') {
        // This warning is confusing and shouldn't be emitted. Plugins often support lower versions than the
        // Flutter app, but as long as they support the minimum it will work.
        // warning: The iOS deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0,
        // but the range of supported deployment target versions is 9.0 to 14.0.99.
        //
        // (or "The macOS deployment target 'MACOSX_DEPLOYMENT_TARGET'"...)
        if (buildOutput.contains(
              'is set to 10.0, but the range of supported deployment target versions',
            ) ||
            buildOutput.contains(
              'is set to 10.8, but the range of supported deployment target versions',
            )) {
          throw TaskResult.failure('Minimum plugin version warning present');
        }

        if (validateNativeBuildProject) {
          final generatedSwiftManifest = File(
            path.join(
              rootPath,
              target,
              'Flutter',
              'ephemeral',
              'Packages',
              'FlutterGeneratedPluginSwiftPackage',
              'Package.swift',
            ),
          );
          final bool swiftPackageManagerEnabled = generatedSwiftManifest.existsSync();

          if (!swiftPackageManagerEnabled) {
            final podsProject = File(
              path.join(rootPath, target, 'Pods', 'Pods.xcodeproj', 'project.pbxproj'),
            );
            if (!podsProject.existsSync()) {
              throw TaskResult.failure('Xcode Pods project file missing at ${podsProject.path}');
            }

            final String podsProjectContent = podsProject.readAsStringSync();
            if (target == 'ios') {
              // Plugins with versions lower than the app version should not have IPHONEOS_DEPLOYMENT_TARGET set.
              // The plugintest plugin target should not have IPHONEOS_DEPLOYMENT_TARGET set since it has been lowered
              // in _reduceDarwinPluginMinimumVersion to 10, which is below the target version of 11.
              if (podsProjectContent.contains('IPHONEOS_DEPLOYMENT_TARGET = 10')) {
                throw TaskResult.failure(
                  'Plugin build setting IPHONEOS_DEPLOYMENT_TARGET not removed',
                );
              }
              // Transitive dependency AppAuth targeting too-low 8.0 was not fixed.
              if (podsProjectContent.contains('IPHONEOS_DEPLOYMENT_TARGET = 8')) {
                throw TaskResult.failure(
                  'Transitive dependency build setting IPHONEOS_DEPLOYMENT_TARGET=8 not removed',
                );
              }
              if (!podsProjectContent.contains(
                r'"EXCLUDED_ARCHS[sdk=iphonesimulator*]" = "$(inherited) i386";',
              )) {
                throw TaskResult.failure(r'EXCLUDED_ARCHS is not "$(inherited) i386"');
              }
            } else if (target == 'macos') {
              // Same for macOS deployment target, but 10.8.
              // The plugintest target should not have MACOSX_DEPLOYMENT_TARGET set.
              if (podsProjectContent.contains('MACOSX_DEPLOYMENT_TARGET = 10.8')) {
                throw TaskResult.failure(
                  'Plugin build setting MACOSX_DEPLOYMENT_TARGET not removed',
                );
              }
              // Transitive dependency AppAuth targeting too-low 10.9 was not fixed.
              if (podsProjectContent.contains('MACOSX_DEPLOYMENT_TARGET = 10.9')) {
                throw TaskResult.failure(
                  'Transitive dependency build setting MACOSX_DEPLOYMENT_TARGET=10.9 not removed',
                );
              }
            }

            if (localEngine != null) {
              final localEngineSearchPath = RegExp(
                'FRAMEWORK_SEARCH_PATHS\\s*=[^;]*${localEngine.path}',
              );
              if (!localEngineSearchPath.hasMatch(podsProjectContent)) {
                throw TaskResult.failure(
                  'FRAMEWORK_SEARCH_PATHS does not contain the --local-engine path',
                );
              }
            }
          }
        }
      }
    });
  }

  Future<void> delete() async {
    if (Platform.isWindows) {
      // A running Gradle daemon might prevent us from deleting the project
      // folder on Windows.
      final String wrapperPath = path.absolute(path.join(rootPath, 'android', 'gradlew.bat'));
      if (File(wrapperPath).existsSync()) {
        await exec(wrapperPath, <String>['--stop'], canFail: true);
      }
      // TODO(ianh): Investigating if flakiness is timing dependent.
      await Future<void>.delayed(const Duration(seconds: 10));
    }
    rmTree(parent);
  }

  Future<bool> runApp({required List<String> options}) async {
    return inDirectory(Directory(rootPath), () async {
      final Process process = await startFlutter('run', options: options);
      final stdoutDone = Completer<void>();
      final stderrDone = Completer<void>();

      var engineError = false;

      void onStdout(String line) {
        print('stdout: $line');
        if (line.contains('The Flutter DevTools debugger and profiler')) {
          process.stdin.writeln('R');
        }
        if (line.contains('Restarted application')) {
          // Do a hot restart.
          process.stdin.writeln('q');
        }
        if (line.contains('ERROR:')) {
          engineError = true;
          // Quit the app. This makes the 'flutter run' process exit.
          process.stdin.writeln('q');
        }
      }

      process.stdout
          .transform<String>(utf8.decoder)
          .transform<String>(const LineSplitter())
          .listen(onStdout, onDone: stdoutDone.complete);

      process.stderr
          .transform<String>(utf8.decoder)
          .transform<String>(const LineSplitter())
          .listen((String line) => print('stderr: $line'), onDone: stderrDone.complete);

      await Future.wait<void>(<Future<void>>[stdoutDone.future, stderrDone.future]);
      if (engineError) {
        return false;
      }
      final int exitCode = await process.exitCode;
      return exitCode == 0;
    });
  }
}
