// 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: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);
        }
      }
      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);
  }
}
