// 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:collection';

import 'package:meta/meta.dart';
import 'package:xml/xml.dart';
import 'package:yaml/yaml.dart';

import '../src/convert.dart';
import 'android/android_builder.dart';
import 'android/gradle_utils.dart' as gradle;
import 'base/common.dart';
import 'base/error_handling_io.dart';
import 'base/file_system.dart';
import 'base/logger.dart';
import 'base/utils.dart';
import 'base/version.dart';
import 'base/yaml.dart';
import 'bundle.dart' as bundle;
import 'cmake_project.dart';
import 'dart/package_map.dart';
import 'features.dart';
import 'flutter_manifest.dart';
import 'flutter_plugins.dart';
import 'globals.dart' as globals;
import 'platform_plugins.dart';
import 'project_validator_result.dart';
import 'template.dart';
import 'xcode_project.dart';

export 'cmake_project.dart';
export 'xcode_project.dart';

/// Enum for each officially supported platform.
enum SupportedPlatform {
  android,
  ios,
  linux,
  macos,
  web,
  windows,
  fuchsia,
  root, // Special platform to represent the root project directory
}

class FlutterProjectFactory {
  FlutterProjectFactory({required Logger logger, required FileSystem fileSystem})
    : _logger = logger,
      _fileSystem = fileSystem;

  final Logger _logger;
  final FileSystem _fileSystem;

  @visibleForTesting
  final projects = <String, FlutterProject>{};

  /// Returns a [FlutterProject] view of the given directory or a ToolExit error,
  /// if `pubspec.yaml` or `example/pubspec.yaml` is invalid.
  FlutterProject fromDirectory(Directory directory) {
    return projects.putIfAbsent(directory.path, () {
      final FlutterManifest manifest = FlutterProject._readManifest(
        directory.childFile(bundle.defaultManifestPath).path,
        logger: _logger,
        fileSystem: _fileSystem,
      );
      final FlutterManifest exampleManifest = FlutterProject._readManifest(
        FlutterProject._exampleDirectory(directory).childFile(bundle.defaultManifestPath).path,
        logger: _logger,
        fileSystem: _fileSystem,
      );
      return FlutterProject(directory, manifest, exampleManifest);
    });
  }
}

/// Represents the contents of a Flutter project at the specified [directory].
///
/// [FlutterManifest] information is read from `pubspec.yaml` and
/// `example/pubspec.yaml` files on construction of a [FlutterProject] instance.
/// The constructed instance carries an immutable snapshot representation of the
/// presence and content of those files. Accordingly, [FlutterProject] instances
/// should be discarded upon changes to the `pubspec.yaml` files, but can be
/// used across changes to other files, as no other file-level information is
/// cached.
class FlutterProject {
  @visibleForTesting
  FlutterProject(this.directory, this._manifest, this._exampleManifest);

  /// Returns a [FlutterProject] view of the given directory or a ToolExit error,
  /// if `pubspec.yaml` or `example/pubspec.yaml` is invalid.
  static FlutterProject fromDirectory(Directory directory) =>
      globals.projectFactory.fromDirectory(directory);

  /// Returns a [FlutterProject] view of the current directory or a ToolExit error,
  /// if `pubspec.yaml` or `example/pubspec.yaml` is invalid.
  static FlutterProject current() =>
      globals.projectFactory.fromDirectory(globals.fs.currentDirectory);

  /// Create a [FlutterProject] and bypass the project caching.
  @visibleForTesting
  static FlutterProject fromDirectoryTest(Directory directory, [Logger? logger]) {
    final FileSystem fileSystem = directory.fileSystem;
    logger ??= BufferLogger.test();
    final FlutterManifest manifest = FlutterProject._readManifest(
      directory.childFile(bundle.defaultManifestPath).path,
      logger: logger,
      fileSystem: fileSystem,
    );
    final FlutterManifest exampleManifest = FlutterProject._readManifest(
      FlutterProject._exampleDirectory(directory).childFile(bundle.defaultManifestPath).path,
      logger: logger,
      fileSystem: fileSystem,
    );
    return FlutterProject(directory, manifest, exampleManifest);
  }

  /// The location of this project.
  final Directory directory;

  /// The location of the build folder.
  Directory get buildDirectory => directory.childDirectory('build');

  /// The manifest of this project.
  FlutterManifest get manifest => _manifest;
  late FlutterManifest _manifest;

  /// The manifest of the example sub-project of this project.
  final FlutterManifest _exampleManifest;

  /// List of [FlutterProject]s corresponding to the workspace entries.
  List<FlutterProject> get workspaceProjects => manifest.workspace
      .map(
        (String entry) => FlutterProject.fromDirectory(
          directory.childDirectory(directory.fileSystem.path.normalize(entry)),
        ),
      )
      .toList();

  /// The set of organization names found in this project as
  /// part of iOS product bundle identifier, Android application ID, or
  /// Gradle group ID.
  Future<Set<String>> get organizationNames async {
    final candidates = <String>[];

    if (ios.existsSync()) {
      // Don't require iOS build info, this method is only
      // used during create as best-effort, use the
      // default target bundle identifier.
      try {
        final String? bundleIdentifier = await ios.productBundleIdentifier(null);
        if (bundleIdentifier != null) {
          candidates.add(bundleIdentifier);
        }
      } on ToolExit {
        // It's possible that while parsing the build info for the ios project
        // that the bundleIdentifier can't be resolve. However, we would like
        // skip parsing that id in favor of searching in other place. We can
        // consider a tool exit in this case to be non fatal for the program.
      }
    }
    if (android.existsSync()) {
      final String? applicationId = android.applicationId;
      final String? group = android.group;
      candidates.addAll(<String>[?applicationId, ?group]);
    }
    if (example.android.existsSync()) {
      final String? applicationId = example.android.applicationId;
      if (applicationId != null) {
        candidates.add(applicationId);
      }
    }
    if (example.ios.existsSync()) {
      final String? bundleIdentifier = await example.ios.productBundleIdentifier(null);
      if (bundleIdentifier != null) {
        candidates.add(bundleIdentifier);
      }
    }
    return Set<String>.of(
      candidates.map<String?>(_organizationNameFromPackageName).whereType<String>(),
    );
  }

  String? _organizationNameFromPackageName(String packageName) {
    if (0 <= packageName.lastIndexOf('.')) {
      return packageName.substring(0, packageName.lastIndexOf('.'));
    }
    return null;
  }

  /// The iOS sub project of this project.
  late final ios = IosProject.fromFlutter(this);

  /// The Android sub project of this project.
  late final android = AndroidProject._(this);

  /// The web sub project of this project.
  late final web = WebProject._(this);

  /// The MacOS sub project of this project.
  late final macos = MacOSProject.fromFlutter(this);

  /// The Linux sub project of this project.
  late final linux = LinuxProject.fromFlutter(this);

  /// The Windows sub project of this project.
  late final windows = WindowsProject.fromFlutter(this);

  /// The Fuchsia sub project of this project.
  late final fuchsia = FuchsiaProject._(this);

  /// The `pubspec.yaml` file of this project.
  File get pubspecFile => directory.childFile('pubspec.yaml');

  /// The `.metadata` file of this project.
  File get metadataFile => directory.childFile('.metadata');

  /// The `.flutter-plugins-dependencies` file of this project.
  ///
  /// Contains the dependencies each plugin depends on.
  File get flutterPluginsDependenciesFile => directory.childFile('.flutter-plugins-dependencies');

  /// The `.gitignore` file of this project.
  File get gitignoreFile => directory.childFile('.gitignore');

  File get packageConfig => findPackageConfigFileOrDefault(directory);

  /// The `.dart-tool` directory of this project.
  Directory get dartTool => directory.childDirectory('.dart_tool');

  /// The location of the generated scaffolding project for hosting widget
  /// previews from this project.
  // TODO(bkonyi): don't create this project in $TMP.
  // See https://github.com/flutter/flutter/issues/179036
  late final Directory widgetPreviewScaffold = directory.fileSystem.systemTempDirectory
      .createTempSync('widget_preview_scaffold');

  /// The directory containing the generated code for this project.
  Directory get generated => directory.absolute
      .childDirectory('.dart_tool')
      .childDirectory('build')
      .childDirectory('generated')
      .childDirectory(manifest.appName);

  /// The set of directories created by the tool containing ephemeral state.
  // TODO(bkonyi): provide getters for each project type that returns the set
  // of known ephemeral files / directories.
  Set<Directory> get ephemeralDirectories => UnmodifiableSetView(_ephemeralDirectories);
  late final _ephemeralDirectories = <Directory>{
    buildDirectory,
    android.ephemeralDirectory,
    ios.ephemeralDirectory,
    ios.ephemeralModuleDirectory,
    ios.symlinks,
    linux.ephemeralDirectory,
    macos.ephemeralDirectory,
    windows.ephemeralDirectory,
  };

  /// The generated Dart plugin registrant for non-web platforms.
  File get dartPluginRegistrant =>
      dartTool.childDirectory('flutter_build').childFile('dart_plugin_registrant.dart');

  /// The example sub-project of this project.
  FlutterProject get example => FlutterProject(
    _exampleDirectory(directory),
    _exampleManifest,
    FlutterManifest.empty(logger: globals.logger),
  );

  /// The generated scaffolding project for hosting widget previews from this
  /// project.
  late final FlutterProject widgetPreviewScaffoldProject = FlutterProject.fromDirectory(
    widgetPreviewScaffold,
  );

  /// True if this project is a Flutter module project.
  bool get isModule => manifest.isModule;

  /// True if this project is a Flutter plugin project.
  bool get isPlugin => manifest.isPlugin;

  /// True if the Flutter project is using the AndroidX support library.
  bool get usesAndroidX => manifest.usesAndroidX;

  /// True if this project has an example application.
  bool get hasExampleApp => _exampleDirectory(directory).existsSync();

  /// Returns a list of platform names that are supported by the project.
  List<SupportedPlatform> getSupportedPlatforms({bool includeRoot = false}) {
    return <SupportedPlatform>[
      if (includeRoot) SupportedPlatform.root,
      if (android.existsSync()) SupportedPlatform.android,
      if (ios.exists) SupportedPlatform.ios,
      if (web.existsSync()) SupportedPlatform.web,
      if (macos.existsSync()) SupportedPlatform.macos,
      if (linux.existsSync()) SupportedPlatform.linux,
      if (windows.existsSync()) SupportedPlatform.windows,
      if (fuchsia.existsSync()) SupportedPlatform.fuchsia,
    ];
  }

  /// The directory that will contain the example if an example exists.
  static Directory _exampleDirectory(Directory directory) => directory.childDirectory('example');

  /// Reads and validates the `pubspec.yaml` file at [path], asynchronously
  /// returning a [FlutterManifest] representation of the contents.
  ///
  /// Completes with an empty [FlutterManifest], if the file does not exist.
  /// Completes with a ToolExit on validation error.
  static FlutterManifest _readManifest(
    String path, {
    required Logger logger,
    required FileSystem fileSystem,
  }) {
    FlutterManifest? manifest;
    try {
      manifest = FlutterManifest.createFromPath(path, logger: logger, fileSystem: fileSystem);
    } on YamlException catch (e) {
      logger.printStatus('Error detected in pubspec.yaml:', emphasis: true);
      logger.printError('$e');
    } on FormatException catch (e) {
      logger.printError('Error detected while parsing pubspec.yaml:', emphasis: true);
      logger.printError('$e');
    } on FileSystemException catch (e) {
      logger.printError('Error detected while reading pubspec.yaml:', emphasis: true);
      logger.printError('$e');
    }
    if (manifest == null) {
      throwToolExit('Please correct the pubspec.yaml file at $path');
    }
    return manifest;
  }

  /// Reloads the content of [pubspecFile] and updates the contents of [manifest].
  void reloadManifest({required Logger logger, required FileSystem fs}) {
    _manifest = _readManifest(pubspecFile.path, logger: logger, fileSystem: fs);
  }

  /// Returns the MD5 hash of the contents of [manifest], ensuring [manifest] is up to date before
  /// calculating the hash.
  String computeManifestMD5Hash({required Logger logger, required FileSystem fs}) {
    reloadManifest(logger: logger, fs: fs);
    return _manifest.computeMD5Hash();
  }

  /// Replaces the content of [pubspecFile] with the contents of [updated] and
  /// sets [manifest] to the [updated] manifest.
  void replacePubspec(FlutterManifest updated) {
    final YamlMap updatedPubspecContents = updated.toYaml();
    pubspecFile.writeAsStringSync(encodeYamlAsString(updatedPubspecContents));
    _manifest = updated;
  }

  /// Reapplies template files and regenerates project files and plugin
  /// registrants for app and module projects only.
  ///
  /// Will not create project platform directories if they do not already exist.
  ///
  /// If [releaseMode] is `true`, platform-specific tooling and metadata generated
  /// may apply optimizations or changes that are only specific to release builds,
  /// such as not including dev-only dependencies.
  Future<void> regeneratePlatformSpecificTooling({
    DeprecationBehavior deprecationBehavior = DeprecationBehavior.none,
    required bool releaseMode,
  }) async {
    return ensureReadyForPlatformSpecificTooling(
      androidPlatform: android.existsSync(),
      iosPlatform: ios.existsSync(),
      // TODO(stuartmorgan): Revisit the conditions here once the plans for handling
      // desktop in existing projects are in place.
      linuxPlatform: featureFlags.isLinuxEnabled && linux.existsSync(),
      macOSPlatform: featureFlags.isMacOSEnabled && macos.existsSync(),
      windowsPlatform: featureFlags.isWindowsEnabled && windows.existsSync(),
      webPlatform: featureFlags.isWebEnabled && web.existsSync(),
      deprecationBehavior: deprecationBehavior,
      releaseMode: releaseMode,
    );
  }

  /// Applies template files and generates project files and plugin
  /// registrants for app and module projects only for the specified platforms.
  ///
  /// If [releaseMode] is `true`, platform-specific tooling and metadata generated
  /// may apply optimizations or changes that are only specific to release builds,
  /// such as not including dev-only dependencies.
  Future<void> ensureReadyForPlatformSpecificTooling({
    required bool releaseMode,
    bool androidPlatform = false,
    bool iosPlatform = false,
    bool linuxPlatform = false,
    bool macOSPlatform = false,
    bool windowsPlatform = false,
    bool webPlatform = false,
    DeprecationBehavior deprecationBehavior = DeprecationBehavior.none,
  }) async {
    if (!directory.existsSync() || isPlugin) {
      return;
    }
    await refreshPluginsList(this, iosPlatform: iosPlatform, macOSPlatform: macOSPlatform);
    if (androidPlatform) {
      await android.ensureReadyForPlatformSpecificTooling(deprecationBehavior: deprecationBehavior);
    }
    if (iosPlatform) {
      await ios.ensureReadyForPlatformSpecificTooling();
    }
    if (linuxPlatform) {
      await linux.ensureReadyForPlatformSpecificTooling();
    }
    if (macOSPlatform) {
      await macos.ensureReadyForPlatformSpecificTooling();
    }
    if (windowsPlatform) {
      await windows.ensureReadyForPlatformSpecificTooling();
    }
    if (webPlatform) {
      await web.ensureReadyForPlatformSpecificTooling();
    }
    await injectPlugins(
      this,
      androidPlatform: androidPlatform,
      iosPlatform: iosPlatform,
      linuxPlatform: linuxPlatform,
      macOSPlatform: macOSPlatform,
      windowsPlatform: windowsPlatform,
      releaseMode: releaseMode,
    );
  }

  void checkForDeprecation({DeprecationBehavior deprecationBehavior = DeprecationBehavior.none}) {
    if (android.existsSync() && pubspecFile.existsSync()) {
      android.checkForDeprecation(deprecationBehavior: deprecationBehavior);
    }
  }

  /// A JSON encoded string containing the [FlutterManifest.appName],
  /// [FlutterManifest.buildName] (version), and [FlutterManifest.buildNumber]
  /// that are used to generate `version.json`.
  String getVersionInfo() {
    final String? buildName = manifest.buildName;
    final String? buildNumber = manifest.buildNumber;
    final versionFileJson = <String, String>{
      'app_name': manifest.appName,
      'version': ?buildName,
      'build_number': ?buildNumber,
      'package_name': manifest.appName,
    };
    return jsonEncode(versionFileJson);
  }
}

/// Base class for projects per platform.
abstract class FlutterProjectPlatform {
  /// Plugin's platform config key, e.g., "macos", "ios".
  String get pluginConfigKey;

  /// Whether the platform exists in the project.
  bool existsSync();
}

/// Represents the Android sub-project of a Flutter project.
///
/// Instances will reflect the contents of the `android/` sub-folder of
/// Flutter applications and the `.android/` sub-folder of Flutter module projects.
class AndroidProject extends FlutterProjectPlatform {
  AndroidProject._(this.parent);

  // User facing string when java/gradle/agp/kgp versions are compatible.
  @visibleForTesting
  static const validJavaGradleAgpKgpString = 'compatible java/gradle/agp/kgp';

  // User facing link that describes compatibility between gradle and
  // android gradle plugin.
  static const gradleAgpCompatUrl =
      'https://developer.android.com/studio/releases/gradle-plugin#updating-gradle';

  // User facing link that describes compatibility between java and the first
  // version of gradle to support it.
  static const javaGradleCompatUrl =
      'https://docs.gradle.org/current/userguide/compatibility.html#java';

  // User facing link that describes compatibility between KGP and Gradle
  // and AGP.
  static const kgpCompatUrl =
      'https://kotlinlang.org/docs/gradle-configure-project.html#apply-the-plugin';

  // User facing link that describes instructions for downloading
  // the latest version of Android Studio.
  static const installAndroidStudioUrl = 'https://developer.android.com/studio/install';

  /// The parent of this project.
  final FlutterProject parent;

  @override
  String get pluginConfigKey => AndroidPlugin.kConfigKey;

  static final _androidNamespacePattern = RegExp(
    'android {[\\S\\s]+namespace\\s*=?\\s*[\'"](.+)[\'"]',
  );
  static final _applicationIdPattern = RegExp('^\\s*applicationId\\s*=?\\s*[\'"](.*)[\'"]\\s*\$');
  static final _imperativeKotlinPluginPattern = RegExp(
    '^\\s*apply plugin\\:\\s+[\'"]kotlin-android[\'"]\\s*\$',
  );

  /// Examples of strings that this regex matches:
  /// - `id "kotlin-android"`
  /// - `id("kotlin-android")`
  /// - `id ( "kotlin-android" ) `
  /// - `id "org.jetbrains.kotlin.android"`
  /// - `id("org.jetbrains.kotlin.android")`
  /// - `id ( "org.jetbrains.kotlin.android" )`
  static final _declarativeKotlinPluginPatterns = <RegExp>[
    RegExp('^\\s*id\\s*\\(?\\s*[\'"]kotlin-android[\'"]\\s*\\)?\\s*\$'),
    RegExp('^\\s*id\\s*\\(?\\s*[\'"]org.jetbrains.kotlin.android[\'"]\\s*\\)?\\s*\$'),
  ];

  /// Pattern used to find the assignment of the "group" property in Gradle.
  /// Expected example: `group "dev.flutter.plugin"`
  /// Regex is used in both Groovy and Kotlin Gradle files.
  static final _groupPattern = RegExp('^\\s*group\\s*=?\\s*[\'"](.*)[\'"]\\s*\$');

  /// The Gradle root directory of the Android host app. This is the directory
  /// containing the `app/` subdirectory and the `settings.gradle` file that
  /// includes it in the overall Gradle project.
  Directory get hostAppGradleRoot {
    if (!isModule || _editableHostAppDirectory.existsSync()) {
      return _editableHostAppDirectory;
    }
    return ephemeralDirectory;
  }

  /// The Gradle root directory of the Android wrapping of Flutter and plugins.
  /// This is the same as [hostAppGradleRoot] except when the project is
  /// a Flutter module with an editable host app.
  Directory get _flutterLibGradleRoot => isModule ? ephemeralDirectory : _editableHostAppDirectory;

  Directory get ephemeralDirectory => parent.directory.childDirectory('.android');
  Directory get _editableHostAppDirectory => parent.directory.childDirectory('android');

  /// True if the parent Flutter project is a module.
  bool get isModule => parent.isModule;

  /// True if the parent Flutter project is a plugin.
  bool get isPlugin => parent.isPlugin;

  /// True if the Flutter project is using the AndroidX support library.
  bool get usesAndroidX => parent.usesAndroidX;

  /// Returns true if the current version of the Gradle plugin is supported.
  late final bool isSupportedVersion = _computeSupportedVersion();

  /// Gets all build variants of this project.
  Future<List<String>> getBuildVariants() async {
    if (!existsSync() || androidBuilder == null) {
      return const <String>[];
    }
    return androidBuilder!.getBuildVariants(project: parent);
  }

  /// Outputs app link related settings into a json file.
  ///
  /// The return future resolves to the path of the json file.
  ///
  /// The future resolves to null if it fails to retrieve app link settings.
  Future<String> outputsAppLinkSettings({required String variant}) async {
    if (!existsSync() || androidBuilder == null) {
      throwToolExit('Target directory $hostAppGradleRoot is not an Android project');
    }
    return androidBuilder!.outputsAppLinkSettings(variant, project: parent);
  }

  bool _computeSupportedVersion() {
    final FileSystem fileSystem = hostAppGradleRoot.fileSystem;
    final File plugin = hostAppGradleRoot.childFile(
      fileSystem.path.join('buildSrc', 'src', 'main', 'groovy', 'FlutterPlugin.groovy'),
    );
    if (plugin.existsSync()) {
      return false;
    }
    try {
      for (final String line in appGradleFile.readAsLinesSync()) {
        // This syntax corresponds to applying the Flutter Gradle Plugin with a
        // script.
        // See https://docs.gradle.org/current/userguide/plugins.html#sec:script_plugins.
        final bool fileBasedApply = line.contains(RegExp(r'apply from: .*/flutter.gradle'));

        // This syntax corresponds to applying the Flutter Gradle Plugin using
        // the declarative "plugins {}" block after including it in the
        // pluginManagement block of the settings.gradle file.
        // See https://docs.gradle.org/current/userguide/composite_builds.html#included_plugin_builds,
        // as well as the settings.gradle and build.gradle templates.
        final bool declarativeApply = line.contains(
          RegExp(r'dev\.flutter\.(?:(?:flutter-gradle-plugin)|(?:`flutter-gradle-plugin`))'),
        );

        // This case allows for flutter run/build to work for modules. It does
        // not guarantee the Flutter Gradle Plugin is applied.
        final bool managed = line.contains(RegExp('def flutterPluginVersion = [\'"]managed[\'"]'));
        if (fileBasedApply || declarativeApply || managed) {
          return true;
        }
      }
    } on FileSystemException {
      return false;
    }
    return false;
  }

  /// True, if the app project is using Kotlin.
  bool get isKotlin {
    final imperativeMatch = firstMatchInFile(appGradleFile, _imperativeKotlinPluginPattern) != null;
    final bool declarativeMatch = _declarativeKotlinPluginPatterns.any((RegExp pattern) {
      return (firstMatchInFile(appGradleFile, pattern) != null);
    });
    return imperativeMatch || declarativeMatch;
  }

  /// Gets top-level Gradle build file.
  /// See https://developer.android.com/build#top-level.
  ///
  /// The file must exist and it must be written in either Groovy (build.gradle)
  /// or Kotlin (build.gradle.kts).
  File get hostAppGradleFile {
    return getGroovyOrKotlin(hostAppGradleRoot, 'build.gradle');
  }

  /// Gets the project root level Gradle settings file.
  ///
  /// The file must exist and it must be written in either Groovy (settings.gradle)
  /// or Kotlin (settings.gradle.kts).
  File get settingsGradleFile {
    return getGroovyOrKotlin(hostAppGradleRoot, 'settings.gradle');
  }

  File getGroovyOrKotlin(Directory directory, String baseFilename) {
    final File groovyFile = directory.childFile(baseFilename);
    final File kotlinFile = directory.childFile('$baseFilename.kts');

    if (groovyFile.existsSync()) {
      // We mimic Gradle's behavior of preferring Groovy over Kotlin when both files exist.
      return groovyFile;
    }
    if (kotlinFile.existsSync()) {
      return kotlinFile;
    }

    // TODO(bartekpacia): An exception should be thrown when neither
    // the Groovy or Kotlin file exists, instead of falling back to the
    // Groovy file. See #141180.
    return groovyFile;
  }

  /// Gets the module-level build.gradle file.
  /// See https://developer.android.com/build#module-level.
  ///
  /// The file must exist and it must be written in either Groovy (build.gradle)
  /// or Kotlin (build.gradle.kts).
  File get appGradleFile {
    final Directory appDir = hostAppGradleRoot.childDirectory('app');
    return getGroovyOrKotlin(appDir, 'build.gradle');
  }

  File get appManifestFile {
    if (isUsingGradle) {
      return hostAppGradleRoot
          .childDirectory('app')
          .childDirectory('src')
          .childDirectory('main')
          .childFile('AndroidManifest.xml');
    }

    return hostAppGradleRoot.childFile('AndroidManifest.xml');
  }

  /// Gets the Gradle wrapper properties file.
  ///
  /// This file is located under `gradle/wrapper/gradle-wrapper.properties`
  /// in the host app's Gradle root directory. It defines the distribution
  /// settings for the Gradle wrapper.
  File get gradleWrapperPropertiesFile {
    return hostAppGradleRoot
        .childDirectory('gradle')
        .childDirectory('wrapper')
        .childFile('gradle-wrapper.properties');
  }

  File get generatedPluginRegistrantFile {
    return hostAppGradleRoot
        .childDirectory('app')
        .childDirectory('src')
        .childDirectory('main')
        .childDirectory('java')
        .childDirectory('io')
        .childDirectory('flutter')
        .childDirectory('plugins')
        .childFile('GeneratedPluginRegistrant.java');
  }

  File get gradleAppOutV1File => gradleAppOutV1Directory.childFile('app-debug.apk');

  Directory get gradleAppOutV1Directory {
    return globals.fs.directory(
      globals.fs.path.join(hostAppGradleRoot.path, 'app', 'build', 'outputs', 'apk'),
    );
  }

  /// Whether the current flutter project has an Android sub-project.
  @override
  bool existsSync() {
    return parent.isModule || _editableHostAppDirectory.existsSync();
  }

  /// Check if the versions of Java, Gradle and AGP are compatible.
  ///
  /// This is expected to be called from
  /// flutter_tools/lib/src/project_validator.dart.
  Future<ProjectValidatorResult> validateJavaAndGradleAgpVersions() async {
    // Constructing ProjectValidatorResult happens here and not in
    // flutter_tools/lib/src/project_validator.dart because of the additional
    // Complexity of variable status values and error string formatting.
    const visibleName = 'Java/Gradle/KGP/Android Gradle Plugin';
    final CompatibilityResult validJavaGradleAgpVersions = await hasValidJavaGradleAgpVersions();

    return ProjectValidatorResult(
      name: visibleName,
      value: validJavaGradleAgpVersions.description,
      status: validJavaGradleAgpVersions.success
          ? StatusProjectValidator.success
          : StatusProjectValidator.error,
    );
  }

  /// Ensures Java SDK is compatible with the project's Gradle version and
  /// the project's Gradle version is compatible with the AGP version and
  /// kotlin version used in build.gradle.
  Future<CompatibilityResult> hasValidJavaGradleAgpVersions() async {
    final String? gradleVersion = await gradle.getGradleVersion(
      hostAppGradleRoot,
      globals.logger,
      globals.processManager,
    );
    final String? agpVersion = gradle.getAgpVersion(hostAppGradleRoot, globals.logger);
    final String? javaVersion = versionToParsableString(globals.java?.version);
    final String? kgpVersion = await gradle.getKgpVersion(
      hostAppGradleRoot,
      globals.logger,
      globals.processManager,
    );

    // Assume valid configuration.
    String description = validJavaGradleAgpKgpString;

    final bool compatibleGradleAgp = gradle.validateGradleAndAgp(
      globals.logger,
      gradleV: gradleVersion,
      agpV: agpVersion,
    );

    final bool compatibleJavaGradle = gradle.validateJavaAndGradle(
      globals.logger,
      javaVersion: javaVersion,
      gradleVersion: gradleVersion,
    );

    final bool compatibleKgpGradle = gradle.validateGradleAndKGP(
      globals.logger,
      gradleV: gradleVersion,
      kgpV: kgpVersion,
    );

    final bool compatibleAgpKgp = gradle.validateAgpAndKgp(
      globals.logger,
      agpV: agpVersion,
      kgpV: kgpVersion,
    );

    // Begin description formatting.
    if (!compatibleGradleAgp) {
      final gradleDescription = agpVersion != null
          ? 'Update Gradle to at least "${gradle.getGradleVersionFor(agpVersion)}".'
          : '';
      description =
          '''
Incompatible Gradle/AGP versions. \n
Gradle Version: $gradleVersion, AGP Version: $agpVersion
$gradleDescription\n
See the link below for more information:
$gradleAgpCompatUrl
''';
    }
    if (!compatibleJavaGradle) {
      // Should contain the agp error (if present) but not the valid String.
      description =
          '''
${compatibleGradleAgp ? '' : description}
Incompatible Java/Gradle versions.
Java Version: $javaVersion, Gradle Version: $gradleVersion\n
See the link below for more information:
$javaGradleCompatUrl
''';
    }
    if (!compatibleKgpGradle) {
      description =
          '''
${compatibleGradleAgp ? '' : description}
Incompatible KGP/Gradle versions.
Gradle Version: $gradleVersion, Kotlin Version: $kgpVersion\n
See the link below for more information:
  $kgpCompatUrl
''';
    }
    if (!compatibleAgpKgp) {
      description =
          '''
${compatibleGradleAgp ? '' : description}
Incompatible AGP/KGP versions.
AGP Version: $agpVersion, KGP Version: $kgpVersion\n
See the link below for more information:
  $kgpCompatUrl
''';
    }
    return CompatibilityResult(
      compatibleJavaGradle && compatibleGradleAgp && compatibleKgpGradle && compatibleAgpKgp,
      description,
    );
  }

  bool get isUsingGradle {
    return hostAppGradleFile.existsSync();
  }

  String? get applicationId {
    return firstMatchInFile(appGradleFile, _applicationIdPattern)?.group(1);
  }

  /// Get the namespace for newer Android projects,
  /// which replaces the `package` attribute in the Manifest.xml.
  String? get namespace {
    try {
      // firstMatchInFile() reads per line but `_androidNamespacePattern` matches a multiline pattern.
      return _androidNamespacePattern.firstMatch(appGradleFile.readAsStringSync())?.group(1);
    } on FileSystemException {
      return null;
    }
  }

  String? get group {
    return firstMatchInFile(hostAppGradleFile, _groupPattern)?.group(1);
  }

  /// The build directory where the Android artifacts are placed.
  Directory get buildDirectory {
    return parent.buildDirectory;
  }

  Future<void> ensureReadyForPlatformSpecificTooling({
    DeprecationBehavior deprecationBehavior = DeprecationBehavior.none,
  }) async {
    if (isModule && _shouldRegenerateFromTemplate()) {
      await _regenerateLibrary();
      // Add ephemeral host app, if an editable host app does not already exist.
      if (!_editableHostAppDirectory.existsSync()) {
        await _overwriteFromTemplate(
          globals.fs.path.join('module', 'android', 'host_app_common'),
          ephemeralDirectory,
        );
        await _overwriteFromTemplate(
          globals.fs.path.join('module', 'android', 'host_app_ephemeral'),
          ephemeralDirectory,
        );
      }
    }
    if (!hostAppGradleRoot.existsSync()) {
      return;
    }
    gradle.updateLocalProperties(project: parent, requireAndroidSdk: false);
  }

  bool _shouldRegenerateFromTemplate() {
    return globals.fsUtils.isOlderThanReference(
          entity: ephemeralDirectory,
          referenceFile: parent.pubspecFile,
        ) ||
        globals.cache.isOlderThanToolsStamp(ephemeralDirectory);
  }

  File get localPropertiesFile => _flutterLibGradleRoot.childFile('local.properties');

  Directory get pluginRegistrantHost =>
      _flutterLibGradleRoot.childDirectory(isModule ? 'Flutter' : 'app');

  Future<void> _regenerateLibrary() async {
    ErrorHandlingFileSystem.deleteIfExists(ephemeralDirectory, recursive: true);
    await _overwriteFromTemplate(
      globals.fs.path.join('module', 'android', 'library_new_embedding'),
      ephemeralDirectory,
    );
    await _overwriteFromTemplate(
      globals.fs.path.join('module', 'android', 'gradle'),
      ephemeralDirectory,
    );
    globals.gradleUtils?.injectGradleWrapperIfNeeded(ephemeralDirectory);
  }

  Future<void> _overwriteFromTemplate(String path, Directory target) async {
    final Template template = await Template.fromName(
      path,
      fileSystem: globals.fs,
      templateManifest: null,
      logger: globals.logger,
      templateRenderer: globals.templateRenderer,
    );
    final String androidIdentifier =
        parent.manifest.androidPackage ?? 'com.example.${parent.manifest.appName}';
    template.render(target, <String, Object>{
      'android': true,
      'projectName': parent.manifest.appName,
      'androidIdentifier': androidIdentifier,
      'androidX': usesAndroidX,
      'agpVersion': gradle.templateAndroidGradlePluginVersion,
      'agpVersionForModule': gradle.templateAndroidGradlePluginVersionForModule,
      'kotlinVersion': gradle.templateKotlinGradlePluginVersion,
      'gradleVersion': gradle.templateDefaultGradleVersion,
      'compileSdkVersion': gradle.compileSdkVersion,
      'minSdkVersion': gradle.minSdkVersion,
      'ndkVersion': gradle.ndkVersion,
      'targetSdkVersion': gradle.targetSdkVersion,
    }, printStatusWhenWriting: false);
  }

  void checkForDeprecation({DeprecationBehavior deprecationBehavior = DeprecationBehavior.none}) {
    if (deprecationBehavior == DeprecationBehavior.none) {
      return;
    }
    final AndroidEmbeddingVersionResult result = computeEmbeddingVersion();
    if (result.version != AndroidEmbeddingVersion.v1) {
      return;
    }
    // The v1 android embedding has been deleted.
    throwToolExit('Build failed due to use of deleted Android v1 embedding.', exitCode: 1);
  }

  AndroidEmbeddingVersion getEmbeddingVersion() {
    final AndroidEmbeddingVersion androidEmbeddingVersion = computeEmbeddingVersion().version;
    if (androidEmbeddingVersion == AndroidEmbeddingVersion.v1) {
      throwToolExit('Build failed due to use of deleted Android v1 embedding.', exitCode: 1);
    }

    return androidEmbeddingVersion;
  }

  AndroidEmbeddingVersionResult computeEmbeddingVersion() {
    if (isModule) {
      // A module type's Android project is used in add-to-app scenarios and
      // only supports the V2 embedding.
      return AndroidEmbeddingVersionResult(AndroidEmbeddingVersion.v2, 'Is add-to-app module');
    }
    if (isPlugin) {
      // Plugins do not use an appManifest, so we stop here.
      //
      // TODO(garyq): This method does not currently check for code references to
      // the v1 embedding, we should check for this once removal is further along.
      return AndroidEmbeddingVersionResult(AndroidEmbeddingVersion.v2, 'Is plugin');
    }
    if (!appManifestFile.existsSync()) {
      return AndroidEmbeddingVersionResult(
        AndroidEmbeddingVersion.v1,
        'No `${appManifestFile.absolute.path}` file',
      );
    }
    XmlDocument document;
    try {
      document = XmlDocument.parse(appManifestFile.readAsStringSync());
    } on XmlException {
      throwToolExit(
        'Error parsing $appManifestFile '
        'Please ensure that the android manifest is a valid XML document and try again.',
      );
    } on FileSystemException {
      throwToolExit(
        'Error reading $appManifestFile even though it exists. '
        'Please ensure that you have read permission to this file and try again.',
      );
    }
    for (final XmlElement application in document.findAllElements('application')) {
      final String? applicationName = application.getAttribute('android:name');
      if (applicationName == 'io.flutter.app.FlutterApplication') {
        return AndroidEmbeddingVersionResult(
          AndroidEmbeddingVersion.v1,
          '${appManifestFile.absolute.path} uses `android:name="io.flutter.app.FlutterApplication"`',
        );
      }
    }
    for (final XmlElement metaData in document.findAllElements('meta-data')) {
      final String? name = metaData.getAttribute('android:name');
      // External code checks for this string to identify flutter android apps.
      // See cl/667760684 as an example.
      if (name == 'flutterEmbedding') {
        final String? embeddingVersionString = metaData.getAttribute('android:value');
        if (embeddingVersionString == '1') {
          return AndroidEmbeddingVersionResult(
            AndroidEmbeddingVersion.v1,
            '${appManifestFile.absolute.path} `<meta-data android:name="flutterEmbedding"` has value 1',
          );
        }
        if (embeddingVersionString == '2') {
          return AndroidEmbeddingVersionResult(
            AndroidEmbeddingVersion.v2,
            '${appManifestFile.absolute.path} `<meta-data android:name="flutterEmbedding"` has value 2',
          );
        }
      }
    }
    return AndroidEmbeddingVersionResult(
      AndroidEmbeddingVersion.v1,
      'No `<meta-data android:name="flutterEmbedding" android:value="2"/>` in ${appManifestFile.absolute.path}',
    );
  }

  static const _impellerEnabledByDefault = true;

  /// Returns the `io.flutter.embedding.android.EnableImpeller` manifest value.
  ///
  /// If there is no manifest file, or the key is not present, returns `false`.
  bool computeImpellerEnabled() {
    if (!appManifestFile.existsSync()) {
      return _impellerEnabledByDefault;
    }
    final XmlDocument document;
    try {
      document = XmlDocument.parse(appManifestFile.readAsStringSync());
    } on XmlException {
      throwToolExit(
        'Error parsing $appManifestFile '
        'Please ensure that the android manifest is a valid XML document and try again.',
      );
    } on FileSystemException {
      throwToolExit(
        'Error reading $appManifestFile even though it exists. '
        'Please ensure that you have read permission to this file and try again.',
      );
    }
    for (final XmlElement metaData in document.findAllElements('meta-data')) {
      final String? name = metaData.getAttribute('android:name');
      if (name == 'io.flutter.embedding.android.EnableImpeller') {
        final String? value = metaData.getAttribute('android:value');
        if (value == 'true') {
          return true;
        }
        if (value == 'false') {
          return false;
        }
      }
    }
    return _impellerEnabledByDefault;
  }
}

/// Iteration of the embedding Java API in the engine used by the Android project.
enum AndroidEmbeddingVersion {
  /// V1 APIs based on io.flutter.app.FlutterActivity.
  v1,

  /// V2 APIs based on io.flutter.embedding.android.FlutterActivity.
  v2,
}

/// Data class that holds the results of checking for embedding version.
///
/// This class includes the reason why a particular embedding was selected.
class AndroidEmbeddingVersionResult {
  AndroidEmbeddingVersionResult(this.version, this.reason);

  /// The embedding version.
  AndroidEmbeddingVersion version;

  /// The reason why the embedding version was selected.
  String reason;
}

// What the tool should do when encountering deprecated API in applications.
enum DeprecationBehavior {
  // The command being run does not care about deprecation status.
  none,
  // The command should continue and ignore the deprecation warning.
  ignore,
  // The command should exit the tool.
  exit,
}

/// Represents the web sub-project of a Flutter project.
class WebProject extends FlutterProjectPlatform {
  WebProject._(this.parent);

  final FlutterProject parent;

  @override
  String get pluginConfigKey => WebPlugin.kConfigKey;

  /// Whether this flutter project has a web sub-project.
  @override
  bool existsSync() {
    return parent.directory.childDirectory('web').existsSync() && indexFile.existsSync();
  }

  /// The 'lib' directory for the application.
  Directory get libDirectory => parent.directory.childDirectory('lib');

  /// The directory containing additional files for the application.
  Directory get directory => parent.directory.childDirectory('web');

  /// The html file used to host the flutter web application.
  File get indexFile => parent.directory.childDirectory('web').childFile('index.html');

  /// The .dart_tool/dartpad directory
  Directory get dartpadToolDirectory =>
      parent.directory.childDirectory('.dart_tool').childDirectory('dartpad');

  Future<void> ensureReadyForPlatformSpecificTooling() async {
    /// Create .dart_tool/dartpad/web_plugin_registrant.dart.
    /// See: https://github.com/dart-lang/dart-services/pull/874
    await injectBuildTimePluginFilesForWebPlatform(parent, destination: dartpadToolDirectory);
  }
}

/// The Fuchsia sub project.
class FuchsiaProject {
  FuchsiaProject._(this.project);

  final FlutterProject project;

  Directory? _editableHostAppDirectory;
  Directory get editableHostAppDirectory =>
      _editableHostAppDirectory ??= project.directory.childDirectory('fuchsia');

  bool existsSync() => editableHostAppDirectory.existsSync();

  Directory? _meta;
  Directory get meta => _meta ??= editableHostAppDirectory.childDirectory('meta');
}

// Combines success and a description into one object that can be returned
// together.
@visibleForTesting
class CompatibilityResult {
  CompatibilityResult(this.success, this.description);
  final bool success;
  final String description;
}

/// Converts a [Version] to a string that can be parsed by [Version.parse].
String? versionToParsableString(Version? version) {
  if (version == null) {
    return null;
  }

  return '${version.major}.${version.minor}.${version.patch}';
}
