// 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 TaskFunction 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.sharedDarwinSource = 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 bool sharedDarwinSource;
  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 bool 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();
      }
      if (sharedDarwinSource) {
        await plugin.convertDefaultPluginToSharedDarwinPlugin();
      }
      section('Test plugin');
      if (runFlutterTest) {
        await plugin.runFlutterTest();
        if (!dartOnlyPlugin) {
          await plugin.example.runNativeTests(buildTarget);
          if (buildTarget == 'ios') {
            bool 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 Directory 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 String 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 String 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 File 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 List<String> platforms = <String>['android', 'ios', 'linux', 'macos', 'windows'];
    for (final String platform in platforms) {
      final Directory platformDir = Directory(path.join(rootPath, platform));
      if (platformDir.existsSync()) {
        await platformDir.delete(recursive: true);
      }
    }
  }

  /// Converts an iOS/macOS plugin created from the standard template to a shared
  /// darwin directory plugin.
  Future<void> convertDefaultPluginToSharedDarwinPlugin() async {
    // Convert the metadata.
    final File pubspec = pubspecFile;
    String pubspecContent = await pubspec.readAsString();
    const String originalIOSKey = '\n      ios:\n';
    const String originalMacOSKey = '\n      macos:\n';
    if (!pubspecContent.contains(originalIOSKey) || !pubspecContent.contains(originalMacOSKey)) {
      print(pubspecContent);
      throw TaskResult.failure('Missing expected darwin platform plugin keys');
    }
    pubspecContent = pubspecContent.replaceAll(
      originalIOSKey,
      '$originalIOSKey        sharedDarwinSource: true\n',
    );
    pubspecContent = pubspecContent.replaceAll(
      originalMacOSKey,
      '$originalMacOSKey        sharedDarwinSource: true\n',
    );
    await pubspec.writeAsString(pubspecContent, flush: true);

    // Copy ios to darwin, and delete macos.
    final Directory iosDir = Directory(path.join(rootPath, 'ios'));
    final Directory darwinDir = Directory(path.join(rootPath, 'darwin'));
    recursiveCopy(iosDir, darwinDir);

    await iosDir.delete(recursive: true);
    await Directory(path.join(rootPath, 'macos')).delete(recursive: true);

    final File podspec = File(path.join(darwinDir.path, '$name.podspec'));
    String podspecContent = await podspec.readAsString();
    if (!podspecContent.contains('s.platform =')) {
      print(podspecContent);
      throw TaskResult.failure('Missing expected podspec platform');
    }

    // Remove "s.platform = :ios" to work on all platforms, including macOS.
    podspecContent = podspecContent.replaceFirst(RegExp(r'.*s\.platform.*'), '');
    podspecContent = podspecContent.replaceFirst(
      "s.dependency 'Flutter'",
      "s.ios.dependency 'Flutter'\ns.osx.dependency 'FlutterMacOS'",
    );

    await podspec.writeAsString(podspecContent, flush: true);

    // Make PlugintestPlugin.swift compile on iOS and macOS with target conditionals.
    // If SwiftPM is disabled, the file will be in `darwin/Classes/`.
    // Otherwise, the file will be in `darwin/<plugin>/Sources/<plugin>/`.
    final String pluginClass = '${name[0].toUpperCase()}${name.substring(1)}Plugin';
    print('pluginClass: $pluginClass');
    File pluginRegister = File(path.join(darwinDir.path, 'Classes', '$pluginClass.swift'));
    if (!pluginRegister.existsSync()) {
      pluginRegister = File(path.join(darwinDir.path, name, 'Sources', name, '$pluginClass.swift'));
    }
    final String pluginRegisterContent =
        '''
#if os(macOS)
import FlutterMacOS
#elseif os(iOS)
import Flutter
#endif

public class $pluginClass: NSObject, FlutterPlugin {
  public static func register(with registrar: FlutterPluginRegistrar) {
#if os(macOS)
    let channel = FlutterMethodChannel(name: "$name", binaryMessenger: registrar.messenger)
#elseif os(iOS)
    let channel = FlutterMethodChannel(name: "$name", binaryMessenger: registrar.messenger())
#endif
    let instance = $pluginClass()
    registrar.addMethodCallDelegate(instance, channel: channel)
  }

  public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
#if os(macOS)
    result("macOS " + ProcessInfo.processInfo.operatingSystemVersionString)
#elseif os(iOS)
    result("iOS " + UIDevice.current.systemVersion)
#endif
  }
}
''';
    await pluginRegister.writeAsString(pluginRegisterContent, flush: 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 String 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';
    if (template != 'plugin' && isDarwin) {
      // ios-language option is only supported for plugins. Remove the -i flag and the next parameter, "swift" or
      // "objc". This isn't proper arg parsing (for example doesn't handle -i=objc, but good enough for these tests
      // since they blow up if -i is passed incorrectly.
      final int indexOfIOSLanguage = options.indexOf('-i');
      if (indexOfIOSLanguage != -1) {
        options.removeRange(indexOfIOSLanguage, indexOfIOSLanguage + 2);
      }
    }
    await inDirectory(directory, () async {
      await flutter(
        'create',
        options: <String>[
          '--template=$template',
          '--org',
          'io.flutter.devicelab',
          ...options,
          name,
        ],
        environment: environment,
      );
    });

    final _FlutterProject 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 File 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'
end
''');

    final File 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 File 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) {
    final File podspec = File(path.join(rootPath, target, '$plugin.podspec'));
    if (!podspec.existsSync()) {
      throw TaskResult.failure('podspec file missing at ${podspec.path}');
    }
    final String versionString = target == 'ios'
        ? "s.platform = :ios, '13.0'"
        : "s.platform = :osx, '10.11'";
    String podspecContent = podspec.readAsStringSync();
    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.
    const String iosContent = '''
s.platform = :ios, '10.0'
s.dependency 'AppAuth', '1.6.0'
''';

    const String macosContent = '''
s.platform = :osx, '10.8'
s.dependency 'AppAuth', '1.6.0'
''';

    podspecContent = podspecContent.replaceFirst(
      versionString,
      target == 'ios' ? iosContent : macosContent,
    );
    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 File generatedSwiftManifest = File(
            path.join(
              rootPath,
              target,
              'Flutter',
              'ephemeral',
              'Packages',
              'FlutterGeneratedPluginSwiftPackage',
              'Package.swift',
            ),
          );
          final bool swiftPackageManagerEnabled = generatedSwiftManifest.existsSync();

          if (!swiftPackageManagerEnabled) {
            final File 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 RegExp 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 Completer<void> stdoutDone = Completer<void>();
      final Completer<void> stderrDone = Completer<void>();

      bool 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;
    });
  }
}
