// 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 'package:pub_semver/pub_semver.dart';
import 'package:yaml/yaml.dart';

import 'base/common.dart';
import 'base/file_system.dart';
import 'platform_plugins.dart';

class Plugin {
  Plugin({
    required this.name,
    required this.path,
    required this.platforms,
    required this.defaultPackagePlatforms,
    required this.pluginDartClassPlatforms,
    this.flutterConstraint,
    required this.dependencies,
    required this.isDirectDependency,
    required this.isDevDependency,
    this.implementsPackage,
  });

  /// Parses [Plugin] specification from the provided pluginYaml.
  ///
  /// This currently supports two formats. Legacy and Multi-platform.
  ///
  /// Example of the deprecated Legacy format.
  ///
  ///     flutter:
  ///      plugin:
  ///        androidPackage: io.flutter.plugins.sample
  ///        iosPrefix: FLT
  ///        pluginClass: SamplePlugin
  ///
  /// Example Multi-platform format.
  ///
  ///     flutter:
  ///      plugin:
  ///        platforms:
  ///          android:
  ///            package: io.flutter.plugins.sample
  ///            pluginClass: SamplePlugin
  ///          ios:
  ///            # A plugin implemented through method channels.
  ///            pluginClass: SamplePlugin
  ///          linux:
  ///            # A plugin implemented purely in Dart code.
  ///            dartPluginClass: SamplePlugin
  ///            # Optional field to determine file containing dartPluginClass.
  ///            # This file will be used in imports in generated files, e.g.:
  ///            #   import 'package:{{pluginName}}/{{dartFileName}}'
  ///            # instead of default:
  ///            #    import 'package:{{pluginName}}/{{pluginName}}.dart'
  ///            dartFileName: src/sample_plugin.dart
  ///          macos:
  ///            # A plugin implemented with `dart:ffi`.
  ///            ffiPlugin: true
  ///          windows:
  ///            # A plugin using platform-specific Dart and method channels.
  ///            dartPluginClass: SamplePlugin
  ///            pluginClass: SamplePlugin
  factory Plugin.fromYaml(
    String name,
    String path,
    YamlMap? pluginYaml,
    VersionConstraint? flutterConstraint,
    List<String> dependencies, {
    required FileSystem fileSystem,
    required bool isDevDependency,
    Set<String>? appDependencies,
  }) {
    final List<String> errors = validatePluginYaml(pluginYaml);
    if (errors.isNotEmpty) {
      throwToolExit('Invalid plugin specification $name.\n${errors.join('\n')}');
    }
    if (pluginYaml?['platforms'] != null) {
      // SAFETY: Assumes that validatePluginYaml(pluginYaml) has been called.
      return Plugin._fromMultiPlatformYaml(
        name,
        path,
        pluginYaml!,
        flutterConstraint,
        dependencies,
        fileSystem,
        isDevDependency: isDevDependency,
        appDependencies != null && appDependencies.contains(name),
      );
    }
    return Plugin._fromLegacyYaml(
      name,
      path,
      pluginYaml,
      flutterConstraint,
      dependencies,
      fileSystem,
      isDevDependency: isDevDependency,
      appDependencies != null && appDependencies.contains(name),
    );
  }

  factory Plugin._fromMultiPlatformYaml(
    String name,
    String path,
    YamlMap pluginYaml,
    VersionConstraint? flutterConstraint,
    List<String> dependencies,
    FileSystem fileSystem,
    bool isDirectDependency, {
    required bool isDevDependency,
  }) {
    // SAFETY: This constructor is only invoked from .fromYaml, which validates.
    final platformsYaml = pluginYaml['platforms'] as YamlMap;
    assert(
      _validateMultiPlatformYaml(parentMap: pluginYaml).isEmpty,
      'Invalid multi-platform plugin specification $name.',
    );

    final platforms = <String, PluginPlatform>{};

    if (_providesImplementationForPlatform(platformsYaml, AndroidPlugin.kConfigKey)) {
      platforms[AndroidPlugin.kConfigKey] = AndroidPlugin.fromYaml(
        name,
        platformsYaml[AndroidPlugin.kConfigKey] as YamlMap,
        path,
        fileSystem,
      );
    }

    if (_providesImplementationForPlatform(platformsYaml, IOSPlugin.kConfigKey)) {
      platforms[IOSPlugin.kConfigKey] = IOSPlugin.fromYaml(
        name,
        platformsYaml[IOSPlugin.kConfigKey] as YamlMap,
      );
    }

    if (_providesImplementationForPlatform(platformsYaml, LinuxPlugin.kConfigKey)) {
      platforms[LinuxPlugin.kConfigKey] = LinuxPlugin.fromYaml(
        name,
        platformsYaml[LinuxPlugin.kConfigKey] as YamlMap,
      );
    }

    if (_providesImplementationForPlatform(platformsYaml, MacOSPlugin.kConfigKey)) {
      platforms[MacOSPlugin.kConfigKey] = MacOSPlugin.fromYaml(
        name,
        platformsYaml[MacOSPlugin.kConfigKey] as YamlMap,
      );
    }

    if (_providesImplementationForPlatform(platformsYaml, WebPlugin.kConfigKey)) {
      platforms[WebPlugin.kConfigKey] = WebPlugin.fromYaml(
        name,
        platformsYaml[WebPlugin.kConfigKey] as YamlMap,
      );
    }

    if (_providesImplementationForPlatform(platformsYaml, WindowsPlugin.kConfigKey)) {
      platforms[WindowsPlugin.kConfigKey] = WindowsPlugin.fromYaml(
        name,
        platformsYaml[WindowsPlugin.kConfigKey] as YamlMap,
      );
    }

    // TODO(stuartmorgan): Consider merging web into this common handling; the
    //  fact that its implementation of Dart-only plugins and default packages
    //  are separate is legacy.
    final sharedHandlingPlatforms = <String>[
      AndroidPlugin.kConfigKey,
      IOSPlugin.kConfigKey,
      LinuxPlugin.kConfigKey,
      MacOSPlugin.kConfigKey,
      WindowsPlugin.kConfigKey,
    ];
    final defaultPackages = <String, String>{};
    final dartPluginClasses = <String, DartPluginClassAndFilePair>{};
    for (final platform in sharedHandlingPlatforms) {
      final String? defaultPackage = _getDefaultPackageForPlatform(platformsYaml, platform);
      if (defaultPackage != null) {
        defaultPackages[platform] = defaultPackage;
      }
      final DartPluginClassAndFilePair? dartPair = _getPluginDartClassForPlatform(
        platformsYaml,
        platformKey: platform,
        pluginName: name,
      );
      if (dartPair != null) {
        dartPluginClasses[platform] = dartPair;
      }
    }

    return Plugin(
      name: name,
      path: path,
      platforms: platforms,
      defaultPackagePlatforms: defaultPackages,
      pluginDartClassPlatforms: dartPluginClasses,
      flutterConstraint: flutterConstraint,
      dependencies: dependencies,
      isDirectDependency: isDirectDependency,
      implementsPackage: pluginYaml['implements'] != null ? pluginYaml['implements'] as String : '',
      isDevDependency: isDevDependency,
    );
  }

  factory Plugin._fromLegacyYaml(
    String name,
    String path,
    dynamic pluginYaml,
    VersionConstraint? flutterConstraint,
    List<String> dependencies,
    FileSystem fileSystem,
    bool isDirectDependency, {
    required bool isDevDependency,
  }) {
    final platforms = <String, PluginPlatform>{};
    final pluginClass = (pluginYaml as Map<dynamic, dynamic>)['pluginClass'] as String?;
    if (pluginClass != null) {
      final androidPackage = pluginYaml['androidPackage'] as String?;
      if (androidPackage != null) {
        platforms[AndroidPlugin.kConfigKey] = AndroidPlugin(
          name: name,
          package: androidPackage,
          pluginClass: pluginClass,
          pluginPath: path,
          fileSystem: fileSystem,
        );
      }

      final String iosPrefix = pluginYaml['iosPrefix'] as String? ?? '';
      platforms[IOSPlugin.kConfigKey] = IOSPlugin(
        name: name,
        classPrefix: iosPrefix,
        pluginClass: pluginClass,
      );
    }
    return Plugin(
      name: name,
      path: path,
      platforms: platforms,
      defaultPackagePlatforms: <String, String>{},
      pluginDartClassPlatforms: <String, DartPluginClassAndFilePair>{},
      flutterConstraint: flutterConstraint,
      dependencies: dependencies,
      isDirectDependency: isDirectDependency,
      isDevDependency: isDevDependency,
    );
  }

  /// Create a YamlMap that represents the supported platforms.
  ///
  /// For example, if the `platforms` contains 'ios' and 'android', the return map looks like:
  ///
  ///     android:
  ///       package: io.flutter.plugins.sample
  ///       pluginClass: SamplePlugin
  ///     ios:
  ///       pluginClass: SamplePlugin
  static YamlMap createPlatformsYamlMap(
    List<String> platforms,
    String pluginClass,
    String androidPackage,
  ) {
    final map = <String, dynamic>{};
    for (final platform in platforms) {
      map[platform] = <String, String>{
        'pluginClass': pluginClass,
        ...platform == 'android' ? <String, String>{'package': androidPackage} : <String, String>{},
      };
    }
    return YamlMap.wrap(map);
  }

  static List<String> validatePluginYaml(YamlMap? yaml) {
    if (yaml == null) {
      return <String>['Invalid "plugin" specification.'];
    }

    final bool usesOldPluginFormat = const <String>{
      'androidPackage',
      'iosPrefix',
      'pluginClass',
    }.any(yaml.containsKey);

    final bool usesNewPluginFormat = yaml.containsKey('platforms');

    if (usesOldPluginFormat && usesNewPluginFormat) {
      const errorMessage =
          'The flutter.plugin.platforms key cannot be used in combination with the old '
          'flutter.plugin.{androidPackage,iosPrefix,pluginClass} keys. '
          'See: https://flutter.dev/to/pubspec-plugin-platforms';
      return <String>[errorMessage];
    }
    if (!usesOldPluginFormat && !usesNewPluginFormat) {
      const errorMessage =
          'Cannot find the `flutter.plugin.platforms` key in the `pubspec.yaml` file. '
          'An instruction to format the `pubspec.yaml` can be found here: '
          'https://flutter.dev/to/pubspec-plugin-platforms';
      return <String>[errorMessage];
    }

    if (usesNewPluginFormat) {
      return _validateMultiPlatformYaml(parentMap: yaml);
    } else {
      return _validateLegacyYaml(yaml);
    }
  }

  static List<String> _validateMultiPlatformYaml({required YamlMap parentMap}) {
    final Object? platforms = parentMap['platforms'];
    if (platforms is! YamlMap?) {
      const errorMessage =
          'flutter.plugin.platforms should be a map with the platform name as the key';
      return <String>[errorMessage];
    }
    if (platforms == null) {
      return <String>['Invalid "platforms" specification.'];
    }
    final YamlMap yaml = platforms;

    bool isInvalid(String key, bool Function(YamlMap) validate) {
      if (!yaml.containsKey(key)) {
        return false;
      }
      final dynamic yamlValue = yaml[key];
      if (yamlValue is! YamlMap) {
        return true;
      }
      if (yamlValue.containsKey('default_package')) {
        return false;
      }
      return !validate(yamlValue);
    }

    return <String>[
      if (isInvalid(AndroidPlugin.kConfigKey, AndroidPlugin.validate))
        'Invalid "android" plugin specification.',
      if (isInvalid(IOSPlugin.kConfigKey, IOSPlugin.validate))
        'Invalid "ios" plugin specification.',
      if (isInvalid(LinuxPlugin.kConfigKey, LinuxPlugin.validate))
        'Invalid "linux" plugin specification.',
      if (isInvalid(MacOSPlugin.kConfigKey, MacOSPlugin.validate))
        'Invalid "macos" plugin specification.',
      if (isInvalid(WindowsPlugin.kConfigKey, WindowsPlugin.validate))
        'Invalid "windows" plugin specification.',
    ];
  }

  static List<String> _validateLegacyYaml(YamlMap yaml) {
    return <String>[
      if (yaml['androidPackage'] is! String?)
        'The "androidPackage" must either be null or a string.',
      if (yaml['iosPrefix'] is! String?) 'The "iosPrefix" must either be null or a string.',
      if (yaml['pluginClass'] is! String?) 'The "pluginClass" must either be null or a string.',
    ];
  }

  static bool _supportsPlatform(YamlMap platformsYaml, String platformKey) {
    if (!platformsYaml.containsKey(platformKey)) {
      return false;
    }
    if (platformsYaml[platformKey] is YamlMap) {
      return true;
    }
    return false;
  }

  static String? _getDefaultPackageForPlatform(YamlMap platformsYaml, String platformKey) {
    if (!_supportsPlatform(platformsYaml, platformKey)) {
      return null;
    }
    if ((platformsYaml[platformKey] as YamlMap).containsKey(kDefaultPackage)) {
      return (platformsYaml[platformKey] as YamlMap)[kDefaultPackage] as String;
    }
    return null;
  }

  static DartPluginClassAndFilePair? _getPluginDartClassForPlatform(
    YamlMap platformsYaml, {
    required String platformKey,
    required String pluginName,
  }) {
    if (!_supportsPlatform(platformsYaml, platformKey)) {
      return null;
    }
    if ((platformsYaml[platformKey] as YamlMap).containsKey(kDartPluginClass)) {
      final dartClass = (platformsYaml[platformKey] as YamlMap)[kDartPluginClass] as String;
      final String dartFileName =
          (platformsYaml[platformKey] as YamlMap)[kDartFileName] as String? ?? '$pluginName.dart';
      return (dartClass: dartClass, dartFileName: dartFileName);
    }
    return null;
  }

  static bool _providesImplementationForPlatform(YamlMap platformsYaml, String platformKey) {
    if (!_supportsPlatform(platformsYaml, platformKey)) {
      return false;
    }
    if ((platformsYaml[platformKey] as YamlMap).containsKey(kDefaultPackage)) {
      return false;
    }
    return true;
  }

  final String name;
  final String path;

  /// The name of the interface package that this plugin implements.
  /// If `null`, this plugin doesn't implement an interface.
  final String? implementsPackage;

  /// The required version of Flutter, if specified.
  final VersionConstraint? flutterConstraint;

  /// The name of the packages this plugin depends on.
  final List<String> dependencies;

  /// This is a mapping from platform config key to the plugin platform spec.
  final Map<String, PluginPlatform> platforms;

  /// This is a mapping from platform config key to the default package implementation.
  final Map<String, String> defaultPackagePlatforms;

  /// This is a mapping from platform config key to the Dart plugin class for the given platform.
  final Map<String, DartPluginClassAndFilePair> pluginDartClassPlatforms;

  /// Whether this plugin is a direct dependency of the app.
  /// If `false`, the plugin is a dependency of another plugin.
  final bool isDirectDependency;

  /// Whether this plugin is exclusively used as a dev dependency of the app.
  ///
  /// If `false`, the plugin is either:
  /// - _Not_ a dev dependency
  /// - _Not_ a dev dependency of some dependency that itself is not a dev
  ///   dependency
  ///
  /// Dev dependencies are intended to be stripped out in release builds.
  final bool isDevDependency;

  /// Expected path to the plugin's swift package, which contains the Package.swift.
  ///
  /// This path should be `/path/to/[package_name]/[platform]/[package_name]`
  /// (e.g. `/path/to/my_plugin/ios/my_plugin`).
  ///
  /// Returns null if the plugin does not support the [platform] or the
  /// [platform] is not iOS or macOS.
  String? pluginSwiftPackagePath(FileSystem fileSystem, String platform) {
    final String? platformDirectoryName = _darwinPluginDirectoryName(platform);
    if (platformDirectoryName == null) {
      return null;
    }
    return fileSystem.path.join(path, platformDirectoryName, name);
  }

  /// Expected path to the plugin's Package.swift. Returns null if the plugin
  /// does not support the [platform] or the [platform] is not iOS or macOS.
  String? pluginSwiftPackageManifestPath(FileSystem fileSystem, String platform) {
    final String? packagePath = pluginSwiftPackagePath(fileSystem, platform);
    if (packagePath == null) {
      return null;
    }
    return fileSystem.path.join(packagePath, 'Package.swift');
  }

  /// Expected path to the plugin's podspec. Returns null if the plugin does
  /// not support the [platform] or the [platform] is not iOS or macOS.
  String? pluginPodspecPath(FileSystem fileSystem, String platform) {
    final String? platformDirectoryName = _darwinPluginDirectoryName(platform);
    if (platformDirectoryName == null) {
      return null;
    }
    return fileSystem.path.join(path, platformDirectoryName, '$name.podspec');
  }

  String? _darwinPluginDirectoryName(String platform) {
    final PluginPlatform? platformPlugin = platforms[platform];
    if (platformPlugin == null ||
        (platform != IOSPlugin.kConfigKey && platform != MacOSPlugin.kConfigKey)) {
      return null;
    }

    // iOS and macOS code can be shared in "darwin" directory, otherwise
    // respectively in "ios" or "macos" directories.
    if (platformPlugin is DarwinPlugin && (platformPlugin as DarwinPlugin).sharedDarwinSource) {
      return 'darwin';
    }
    return platform;
  }
}

/// Metadata associated with the resolution of a platform interface of a plugin.
class PluginInterfaceResolution {
  PluginInterfaceResolution({required this.plugin, required this.platform});

  /// The plugin.
  final Plugin plugin;

  /// The name of the platform that this plugin implements.
  final String platform;

  Map<String, String> toMap() {
    return <String, String>{
      'pluginName': plugin.name,
      'platform': platform,
      'dartClass': plugin.pluginDartClassPlatforms[platform]?.dartClass ?? '',
      'dartFileName': plugin.pluginDartClassPlatforms[platform]?.dartFileName ?? '',
    };
  }

  @override
  String toString() {
    return '<PluginInterfaceResolution ${plugin.name} for $platform>';
  }
}

/// A record representing pair of dartPluginClass and dartFileName used as metadata
/// in [PluginInterfaceResolution].
///
/// The `dartClass` and `dartFileName` fields are guaranteed to be non-null:
///
/// - record should be created only if dartClassName exists in plugin configuration.
/// - dartFileName either taken from configuration, or, if absent, should be
///   constructed from plugin name.
///
/// See also:
/// - [PluginInterfaceResolution], which uses this record to create Map with metadata.
typedef DartPluginClassAndFilePair = ({String dartClass, String dartFileName});
