// 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,
    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
  ///          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,
    Set<String>? appDependencies,
  }) {
    final List<String> errors = validatePluginYaml(pluginYaml);
    if (errors.isNotEmpty) {
      throwToolExit('Invalid plugin specification $name.\n${errors.join('\n')}');
    }
    if (pluginYaml != null && pluginYaml['platforms'] != null) {
      return Plugin._fromMultiPlatformYaml(
        name,
        path,
        pluginYaml,
        flutterConstraint,
        dependencies,
        fileSystem,
        appDependencies != null && appDependencies.contains(name),
      );
    }
    return Plugin._fromLegacyYaml(
      name,
      path,
      pluginYaml,
      flutterConstraint,
      dependencies,
      fileSystem,
      appDependencies != null && appDependencies.contains(name),
    );
  }

  factory Plugin._fromMultiPlatformYaml(
    String name,
    String path,
    YamlMap pluginYaml,
    VersionConstraint? flutterConstraint,
    List<String> dependencies,
    FileSystem fileSystem,
    bool isDirectDependency,
  ) {
    assert (pluginYaml['platforms'] != null, 'Invalid multi-platform plugin specification $name.');
    final YamlMap platformsYaml = pluginYaml['platforms'] as YamlMap;

    assert (_validateMultiPlatformYaml(platformsYaml).isEmpty,
            'Invalid multi-platform plugin specification $name.');

    final Map<String, PluginPlatform> 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 List<String> sharedHandlingPlatforms = <String>[
      AndroidPlugin.kConfigKey,
      IOSPlugin.kConfigKey,
      LinuxPlugin.kConfigKey,
      MacOSPlugin.kConfigKey,
      WindowsPlugin.kConfigKey,
    ];
    final Map<String, String> defaultPackages = <String, String>{};
    final Map<String, String> dartPluginClasses = <String, String>{};
    for (final String platform in sharedHandlingPlatforms) {
        final String? defaultPackage = _getDefaultPackageForPlatform(platformsYaml, platform);
        if (defaultPackage != null) {
          defaultPackages[platform] = defaultPackage;
        }
        final String? dartClass = _getPluginDartClassForPlatform(platformsYaml, platform);
        if (dartClass != null) {
          dartPluginClasses[platform] = dartClass;
        }
    }

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

  factory Plugin._fromLegacyYaml(
    String name,
    String path,
    dynamic pluginYaml,
    VersionConstraint? flutterConstraint,
    List<String> dependencies,
    FileSystem fileSystem,
    bool isDirectDependency,
  ) {
    final Map<String, PluginPlatform> platforms = <String, PluginPlatform>{};
    final String? pluginClass = (pluginYaml as Map<dynamic, dynamic>)['pluginClass'] as String?;
    if (pluginClass != null) {
      final String? 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, String>{},
      flutterConstraint: flutterConstraint,
      dependencies: dependencies,
      isDirectDependency: isDirectDependency,
    );
  }

  /// 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> map = <String, dynamic>{};
    for (final String 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 String errorMessage =
          'The flutter.plugin.platforms key cannot be used in combination with the old '
          'flutter.plugin.{androidPackage,iosPrefix,pluginClass} keys. '
          'See: https://flutter.dev/docs/development/packages-and-plugins/developing-packages#plugin';
      return <String>[errorMessage];
    }

    if (!usesOldPluginFormat && !usesNewPluginFormat) {
      const String 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/docs/development/packages-and-plugins/developing-packages#plugin-platforms';
      return <String>[errorMessage];
    }

    if (usesNewPluginFormat) {
      if (yaml['platforms'] != null && yaml['platforms'] is! YamlMap) {
        const String errorMessage = 'flutter.plugin.platforms should be a map with the platform name as the key';
        return <String>[errorMessage];
      }
      return _validateMultiPlatformYaml(yaml['platforms'] as YamlMap?);
    } else {
      return _validateLegacyYaml(yaml);
    }
  }

  static List<String> _validateMultiPlatformYaml(YamlMap? yaml) {
    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);
    }

    if (yaml == null) {
      return <String>['Invalid "platforms" specification.'];
    }
    final List<String> errors = <String>[];
    if (isInvalid(AndroidPlugin.kConfigKey, AndroidPlugin.validate)) {
      errors.add('Invalid "android" plugin specification.');
    }
    if (isInvalid(IOSPlugin.kConfigKey, IOSPlugin.validate)) {
      errors.add('Invalid "ios" plugin specification.');
    }
    if (isInvalid(LinuxPlugin.kConfigKey, LinuxPlugin.validate)) {
      errors.add('Invalid "linux" plugin specification.');
    }
    if (isInvalid(MacOSPlugin.kConfigKey, MacOSPlugin.validate)) {
      errors.add('Invalid "macos" plugin specification.');
    }
    if (isInvalid(WindowsPlugin.kConfigKey, WindowsPlugin.validate)) {
      errors.add('Invalid "windows" plugin specification.');
    }
    return errors;
  }

  static List<String> _validateLegacyYaml(YamlMap yaml) {
    final List<String> errors = <String>[];

    if (yaml['androidPackage'] != null && yaml['androidPackage'] is! String) {
      errors.add('The "androidPackage" must either be null or a string.');
    }
    if (yaml['iosPrefix'] != null && yaml['iosPrefix'] is! String) {
      errors.add('The "iosPrefix" must either be null or a string.');
    }
    if (yaml['pluginClass'] != null && yaml['pluginClass'] is! String) {
      errors.add('The "pluginClass" must either be null or a string..');
    }
    return errors;
  }

  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 String? _getPluginDartClassForPlatform(YamlMap platformsYaml, String platformKey) {
    if (!_supportsPlatform(platformsYaml, platformKey)) {
      return null;
    }
    if ((platformsYaml[platformKey] as YamlMap).containsKey(kDartPluginClass)) {
      return (platformsYaml[platformKey] as YamlMap)[kDartPluginClass] as String;
    }
    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 plugin class for the given platform.
  final Map<String, String> pluginDartClassPlatforms;

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

  /// 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? platformDirectoryName = _darwinPluginDirectoryName(platform);
    if (platformDirectoryName == null) {
      return null;
    }
    return fileSystem.path.join(
      path,
      platformDirectoryName,
      name,
      '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] ?? '',
    };
  }

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