// 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 'base/error_handling_io.dart';
import 'base/file_system.dart';
import 'base/utils.dart';
import 'build_info.dart';
import 'bundle.dart' as bundle;
import 'convert.dart';
import 'flutter_plugins.dart';
import 'globals.dart' as globals;
import 'ios/code_signing.dart';
import 'ios/plist_parser.dart';
import 'ios/xcode_build_settings.dart' as xcode;
import 'ios/xcodeproj.dart';
import 'platform_plugins.dart';
import 'project.dart';
import 'template.dart';

/// Represents an Xcode-based sub-project.
///
/// This defines interfaces common to iOS and macOS projects.
abstract class XcodeBasedProject extends FlutterProjectPlatform  {
  static const String _defaultHostAppName = 'Runner';

  /// The Xcode workspace (.xcworkspace directory) of the host app.
  Directory? get xcodeWorkspace {
    if (!hostAppRoot.existsSync()) {
      return null;
    }
    return _xcodeDirectoryWithExtension('.xcworkspace');
  }

  /// The project name (.xcodeproj basename) of the host app.
  late final String hostAppProjectName = () {
    if (!hostAppRoot.existsSync()) {
      return _defaultHostAppName;
    }
    final Directory? xcodeProjectDirectory = _xcodeDirectoryWithExtension('.xcodeproj');
    return xcodeProjectDirectory != null
        ? xcodeProjectDirectory.fileSystem.path.basenameWithoutExtension(xcodeProjectDirectory.path)
        : _defaultHostAppName;
  }();

  Directory? _xcodeDirectoryWithExtension(String extension) {
    final List<FileSystemEntity> contents = hostAppRoot.listSync();
    for (final FileSystemEntity entity in contents) {
      if (globals.fs.path.extension(entity.path) == extension && !globals.fs.path.basename(entity.path).startsWith('.')) {
        return hostAppRoot.childDirectory(entity.basename);
      }
    }
    return null;
  }

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

  Directory get hostAppRoot;

  /// The default 'Info.plist' file of the host app. The developer can change this location in Xcode.
  File get defaultHostInfoPlist => hostAppRoot.childDirectory(_defaultHostAppName).childFile('Info.plist');

  /// The Xcode project (.xcodeproj directory) of the host app.
  Directory get xcodeProject => hostAppRoot.childDirectory('$hostAppProjectName.xcodeproj');

  /// The 'project.pbxproj' file of [xcodeProject].
  File get xcodeProjectInfoFile => xcodeProject.childFile('project.pbxproj');

  /// The 'Runner.xcscheme' file of [xcodeProject].
  File xcodeProjectSchemeFile({String? scheme}) {
    final String schemeName = scheme ?? 'Runner';
    return xcodeProject.childDirectory('xcshareddata').childDirectory('xcschemes').childFile('$schemeName.xcscheme');
  }

  File get xcodeProjectWorkspaceData =>
      xcodeProject
          .childDirectory('project.xcworkspace')
          .childFile('contents.xcworkspacedata');

  /// Xcode workspace shared data directory for the host app.
  Directory? get xcodeWorkspaceSharedData => xcodeWorkspace?.childDirectory('xcshareddata');

  /// Xcode workspace shared workspace settings file for the host app.
  File? get xcodeWorkspaceSharedSettings => xcodeWorkspaceSharedData?.childFile('WorkspaceSettings.xcsettings');

  /// Contains definitions for FLUTTER_ROOT, LOCAL_ENGINE, and more flags for
  /// the Xcode build.
  File get generatedXcodePropertiesFile;

  /// The Flutter-managed Xcode config file for [mode].
  File xcodeConfigFor(String mode);

  /// The script that exports environment variables needed for Flutter tools.
  /// Can be run first in a Xcode Script build phase to make FLUTTER_ROOT,
  /// LOCAL_ENGINE, and other Flutter variables available to any flutter
  /// tooling (`flutter build`, etc) to convert into flags.
  File get generatedEnvironmentVariableExportScript;

  /// The CocoaPods 'Podfile'.
  File get podfile => hostAppRoot.childFile('Podfile');

  /// The CocoaPods 'Podfile.lock'.
  File get podfileLock => hostAppRoot.childFile('Podfile.lock');

  /// The CocoaPods 'Manifest.lock'.
  File get podManifestLock => hostAppRoot.childDirectory('Pods').childFile('Manifest.lock');

  /// The CocoaPods generated 'Pods-Runner-frameworks.sh'.
  File get podRunnerFrameworksScript => podRunnerTargetSupportFiles
      .childFile('Pods-Runner-frameworks.sh');

  /// The CocoaPods generated directory 'Pods-Runner'.
  Directory get podRunnerTargetSupportFiles => hostAppRoot
      .childDirectory('Pods')
      .childDirectory('Target Support Files')
      .childDirectory('Pods-Runner');
}

/// Represents the iOS sub-project of a Flutter project.
///
/// Instances will reflect the contents of the `ios/` sub-folder of
/// Flutter applications and the `.ios/` sub-folder of Flutter module projects.
class IosProject extends XcodeBasedProject {
  IosProject.fromFlutter(this.parent);

  @override
  final FlutterProject parent;

  @override
  String get pluginConfigKey => IOSPlugin.kConfigKey;

  // build setting keys
  static const String kProductBundleIdKey = 'PRODUCT_BUNDLE_IDENTIFIER';
  static const String kTeamIdKey = 'DEVELOPMENT_TEAM';
  static const String kEntitlementFilePathKey = 'CODE_SIGN_ENTITLEMENTS';
  static const String kHostAppBundleNameKey = 'FULL_PRODUCT_NAME';

  static final RegExp _productBundleIdPattern = RegExp('^\\s*$kProductBundleIdKey\\s*=\\s*(["\']?)(.*?)\\1;\\s*\$');
  static const String _kProductBundleIdVariable = '\$($kProductBundleIdKey)';

  static final RegExp _associatedDomainPattern = RegExp(r'^applinks:(.*)');

  Directory get ephemeralModuleDirectory => parent.directory.childDirectory('.ios');
  Directory get _editableDirectory => parent.directory.childDirectory('ios');

  /// This parent folder of `Runner.xcodeproj`.
  @override
  Directory get hostAppRoot {
    if (!isModule || _editableDirectory.existsSync()) {
      return _editableDirectory;
    }
    return ephemeralModuleDirectory;
  }

  /// The root directory of the iOS wrapping of Flutter and plugins. This is the
  /// parent of the `Flutter/` folder into which Flutter artifacts are written
  /// during build.
  ///
  /// This is the same as [hostAppRoot] except when the project is
  /// a Flutter module with an editable host app.
  Directory get _flutterLibRoot => isModule ? ephemeralModuleDirectory : _editableDirectory;

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

  /// Whether the Flutter application has an iOS project.
  bool get exists => hostAppRoot.existsSync();

  /// Put generated files here.
  Directory get ephemeralDirectory => _flutterLibRoot.childDirectory('Flutter').childDirectory('ephemeral');

  @override
  File xcodeConfigFor(String mode) => _flutterLibRoot.childDirectory('Flutter').childFile('$mode.xcconfig');

  @override
  File get generatedEnvironmentVariableExportScript => _flutterLibRoot.childDirectory('Flutter').childFile('flutter_export_environment.sh');

  File get appFrameworkInfoPlist => _flutterLibRoot.childDirectory('Flutter').childFile('AppFrameworkInfo.plist');

  /// The 'AppDelegate.swift' file of the host app. This file might not exist if the app project uses Objective-C.
  File get appDelegateSwift => _editableDirectory.childDirectory('Runner').childFile('AppDelegate.swift');

  File get infoPlist => _editableDirectory.childDirectory('Runner').childFile('Info.plist');

  Directory get symlinks => _flutterLibRoot.childDirectory('.symlinks');

  /// True if the app project uses Swift.
  bool get isSwift => appDelegateSwift.existsSync();

  /// Do all plugins support arm64 simulators to run natively on an ARM Mac?
  Future<bool> pluginsSupportArmSimulator() async {
    final Directory podXcodeProject = hostAppRoot
        .childDirectory('Pods')
        .childDirectory('Pods.xcodeproj');
    if (!podXcodeProject.existsSync()) {
      // No plugins.
      return true;
    }

    final XcodeProjectInterpreter? xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
    if (xcodeProjectInterpreter == null) {
      // Xcode isn't installed, don't try to check.
      return false;
    }
    final String? buildSettings = await xcodeProjectInterpreter.pluginsBuildSettingsOutput(podXcodeProject);

    // See if any plugins or their dependencies exclude arm64 simulators
    // as a valid architecture, usually because a binary is missing that slice.
    // Example: EXCLUDED_ARCHS = arm64 i386
    // NOT: EXCLUDED_ARCHS = i386
    return buildSettings != null && !buildSettings.contains(RegExp('EXCLUDED_ARCHS.*arm64'));
  }

  @override
  bool existsSync()  {
    return parent.isModule || _editableDirectory.existsSync();
  }

  /// Outputs universal link related project settings of the iOS sub-project into
  /// a json file.
  ///
  /// The return future will resolve to string path to the output file.
  Future<String> outputsUniversalLinkSettings({
    required String configuration,
    required String target,
  }) async {
    final XcodeProjectBuildContext context = XcodeProjectBuildContext(
      configuration: configuration,
      target: target,
    );
    final File file = await parent.buildDirectory
        .childDirectory('deeplink_data')
        .childFile('universal-link-settings-$configuration-$target.json')
        .create(recursive: true);

    await file.writeAsString(jsonEncode(<String, Object?>{
      'bundleIdentifier': await _productBundleIdentifierWithBuildContext(context),
      'teamIdentifier': await _getTeamIdentifier(context),
      'associatedDomains': await _getAssociatedDomains(context),
    }));
    return file.absolute.path;
  }

  /// The product bundle identifier of the host app, or null if not set or if
  /// iOS tooling needed to read it is not installed.
  Future<String?> productBundleIdentifier(BuildInfo? buildInfo) async {
    if (!existsSync()) {
      return null;
    }

    XcodeProjectBuildContext? buildContext;
    final XcodeProjectInfo? info = await projectInfo();
    if (info != null) {
      final String? scheme = info.schemeFor(buildInfo);
      if (scheme == null) {
        info.reportFlavorNotFoundAndExit();
      }
      final String? configuration = info.buildConfigurationFor(
        buildInfo,
        scheme,
      );
      buildContext = XcodeProjectBuildContext(
        configuration: configuration,
        scheme: scheme,
      );
    }
    return _productBundleIdentifierWithBuildContext(buildContext);
  }

  Future<String?> _productBundleIdentifierWithBuildContext(XcodeProjectBuildContext? buildContext) async {
    if (!existsSync()) {
      return null;
    }
    if (_productBundleIdentifiers.containsKey(buildContext)) {
      return _productBundleIdentifiers[buildContext];
    }
    return _productBundleIdentifiers[buildContext] = await _parseProductBundleIdentifier(buildContext);
  }

  final Map<XcodeProjectBuildContext?, String?> _productBundleIdentifiers = <XcodeProjectBuildContext?, String?>{};


  Future<String?> _parseProductBundleIdentifier(XcodeProjectBuildContext? buildContext) async {
    String? fromPlist;
    final File defaultInfoPlist = defaultHostInfoPlist;
    // Users can change the location of the Info.plist.
    // Try parsing the default, first.
    if (defaultInfoPlist.existsSync()) {
      try {
        fromPlist = globals.plistParser.getValueFromFile<String>(
          defaultHostInfoPlist.path,
          PlistParser.kCFBundleIdentifierKey,
        );
      } on FileNotFoundException {
        // iOS tooling not found; likely not running OSX; let [fromPlist] be null
      }
      if (fromPlist != null && !fromPlist.contains(r'$')) {
        // Info.plist has no build variables in product bundle ID.
        return fromPlist;
      }
    }
    if (buildContext == null) {
      // Getting build settings to evaluate info.Plist requires a context.
      return null;
    }

    final Map<String, String>? allBuildSettings = await _buildSettingsForXcodeProjectBuildContext(buildContext);
    if (allBuildSettings != null) {
      if (fromPlist != null) {
        // Perform variable substitution using build settings.
        return substituteXcodeVariables(fromPlist, allBuildSettings);
      }
      return allBuildSettings[kProductBundleIdKey];
    }

    // On non-macOS platforms, parse the first PRODUCT_BUNDLE_IDENTIFIER from
    // the project file. This can return the wrong bundle identifier if additional
    // bundles have been added to the project and are found first, like frameworks
    // or companion watchOS projects. However, on non-macOS platforms this is
    // only used for display purposes and to regenerate organization names, so
    // best-effort is probably fine.
    final String? fromPbxproj = firstMatchInFile(xcodeProjectInfoFile, _productBundleIdPattern)?.group(2);
    if (fromPbxproj != null && (fromPlist == null || fromPlist == _kProductBundleIdVariable)) {
      return fromPbxproj;
    }
    return null;
  }

  Future<String?> _getTeamIdentifier(XcodeProjectBuildContext buildContext) async {
    final Map<String, String>? buildSettings = await _buildSettingsForXcodeProjectBuildContext(buildContext);
    return buildSettings?[kTeamIdKey];
  }

  Future<List<String>> _getAssociatedDomains(XcodeProjectBuildContext buildContext) async {
    final Map<String, String>? buildSettings = await _buildSettingsForXcodeProjectBuildContext(buildContext);
    if (buildSettings != null) {
      final String? entitlementPath = buildSettings[kEntitlementFilePathKey];
      if (entitlementPath != null) {
        final File entitlement = hostAppRoot.childFile(entitlementPath);
        if (entitlement.existsSync()) {
          final List<String>? domains = globals.plistParser.getValueFromFile<List<Object>>(
            entitlement.path,
            PlistParser.kAssociatedDomainsKey,
          )?.cast<String>();

          if (domains != null) {
            final List<String> result = <String>[];
            for (final String domain in domains) {
              final RegExpMatch? match = _associatedDomainPattern.firstMatch(domain);
              if (match != null) {
                result.add(match.group(1)!);
              }
            }
            return result;
          }
        }
      }
    }
    return const <String>[];
  }

  /// The bundle name of the host app, `My App.app`.
  Future<String?> hostAppBundleName(BuildInfo? buildInfo) async {
    if (!existsSync()) {
      return null;
    }
    return _hostAppBundleName ??= await _parseHostAppBundleName(buildInfo);
  }
  String? _hostAppBundleName;

  Future<String> _parseHostAppBundleName(BuildInfo? buildInfo) async {
    // The product name and bundle name are derived from the display name, which the user
    // is instructed to change in Xcode as part of deploying to the App Store.
    // https://flutter.dev/docs/deployment/ios#review-xcode-project-settings
    // The only source of truth for the name is Xcode's interpretation of the build settings.
    String? productName;
    if (globals.xcodeProjectInterpreter?.isInstalled ?? false) {
      final Map<String, String>? xcodeBuildSettings = await buildSettingsForBuildInfo(buildInfo);
      if (xcodeBuildSettings != null) {
        productName = xcodeBuildSettings[kHostAppBundleNameKey];
      }
    }
    if (productName == null) {
      globals.printTrace('$kHostAppBundleNameKey not present, defaulting to $hostAppProjectName');
    }
    return productName ?? '${XcodeBasedProject._defaultHostAppName}.app';
  }

  /// The build settings for the host app of this project, as a detached map.
  ///
  /// Returns null, if iOS tooling is unavailable.
  Future<Map<String, String>?> buildSettingsForBuildInfo(
    BuildInfo? buildInfo, {
    String? scheme,
    String? configuration,
    String? target,
    EnvironmentType environmentType = EnvironmentType.physical,
    String? deviceId,
    bool isWatch = false,
  }) async {
    if (!existsSync()) {
      return null;
    }
    final XcodeProjectInfo? info = await projectInfo();
    if (info == null) {
      return null;
    }

    scheme ??= info.schemeFor(buildInfo);
    if (scheme == null) {
      info.reportFlavorNotFoundAndExit();
    }

    configuration ??= (await projectInfo())?.buildConfigurationFor(
      buildInfo,
      scheme,
    );
    return _buildSettingsForXcodeProjectBuildContext(
      XcodeProjectBuildContext(
        environmentType: environmentType,
        scheme: scheme,
        configuration: configuration,
        target: target,
        deviceId: deviceId,
        isWatch: isWatch,
      ),
    );
  }

  Future<Map<String, String>?> _buildSettingsForXcodeProjectBuildContext(XcodeProjectBuildContext buildContext) async {
    if (!existsSync()) {
      return null;
    }
    final Map<String, String>? currentBuildSettings = _buildSettingsByBuildContext[buildContext];
    if (currentBuildSettings == null) {
      final Map<String, String>? calculatedBuildSettings = await _xcodeProjectBuildSettings(buildContext);
      if (calculatedBuildSettings != null) {
        _buildSettingsByBuildContext[buildContext] = calculatedBuildSettings;
      }
    }
    return _buildSettingsByBuildContext[buildContext];
  }

  final Map<XcodeProjectBuildContext, Map<String, String>> _buildSettingsByBuildContext = <XcodeProjectBuildContext, Map<String, String>>{};

  Future<XcodeProjectInfo?> projectInfo() async {
    final XcodeProjectInterpreter? xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
    if (!xcodeProject.existsSync() || xcodeProjectInterpreter == null || !xcodeProjectInterpreter.isInstalled) {
      return null;
    }
    return _projectInfo ??= await xcodeProjectInterpreter.getInfo(hostAppRoot.path);
  }
  XcodeProjectInfo? _projectInfo;

  Future<Map<String, String>?> _xcodeProjectBuildSettings(XcodeProjectBuildContext buildContext) async {
    final XcodeProjectInterpreter? xcodeProjectInterpreter = globals.xcodeProjectInterpreter;
    if (xcodeProjectInterpreter == null || !xcodeProjectInterpreter.isInstalled) {
      return null;
    }

    final Map<String, String> buildSettings = await xcodeProjectInterpreter.getBuildSettings(
      xcodeProject.path,
      buildContext: buildContext,
    );
    if (buildSettings.isNotEmpty) {
      // No timeouts, flakes, or errors.
      return buildSettings;
    }
    return null;
  }

  Future<void> ensureReadyForPlatformSpecificTooling() async {
    await _regenerateFromTemplateIfNeeded();
    if (!_flutterLibRoot.existsSync()) {
      return;
    }
    await _updateGeneratedXcodeConfigIfNeeded();
  }

  /// Check if one the [targets] of the project is a watchOS companion app target.
  Future<bool> containsWatchCompanion({
    required XcodeProjectInfo projectInfo,
    required BuildInfo buildInfo,
    String? deviceId,
  }) async {
    final String? bundleIdentifier = await productBundleIdentifier(buildInfo);
    // A bundle identifier is required for a companion app.
    if (bundleIdentifier == null) {
      return false;
    }
    for (final String target in projectInfo.targets) {
      // Create Info.plist file of the target.
      final File infoFile = hostAppRoot.childDirectory(target).childFile('Info.plist');
      // In older versions of Xcode, if the target was a watchOS companion app,
      // the Info.plist file of the target contained the key WKCompanionAppBundleIdentifier.
      if (infoFile.existsSync()) {
        final String? fromPlist = globals.plistParser.getValueFromFile<String>(infoFile.path, 'WKCompanionAppBundleIdentifier');
        if (bundleIdentifier == fromPlist) {
          return true;
        }

        // The key WKCompanionAppBundleIdentifier might contain an xcode variable
        // that needs to be substituted before comparing it with bundle id
        if (fromPlist != null && fromPlist.contains(r'$')) {
          final Map<String, String>? allBuildSettings = await buildSettingsForBuildInfo(buildInfo, deviceId: deviceId);
          if (allBuildSettings != null) {
            final String substitutedVariable = substituteXcodeVariables(fromPlist, allBuildSettings);
            if (substitutedVariable == bundleIdentifier) {
              return true;
            }
          }
        }
      }
    }

    // If key not found in Info.plist above, do more expensive check of build settings.
    // In newer versions of Xcode, the build settings of the watchOS companion
    // app's scheme should contain the key INFOPLIST_KEY_WKCompanionAppBundleIdentifier.
    final bool watchIdentifierFound = xcodeProjectInfoFile.readAsStringSync().contains('WKCompanionAppBundleIdentifier');
    if (!watchIdentifierFound) {
      return false;
    }

    final String? defaultScheme = projectInfo.schemeFor(buildInfo);
    if (defaultScheme == null) {
      projectInfo.reportFlavorNotFoundAndExit();
    }
    for (final String scheme in projectInfo.schemes) {
      // the default scheme should not be a watch scheme, so skip it
      if (scheme == defaultScheme) {
        continue;
      }
      final Map<String, String>? allBuildSettings = await buildSettingsForBuildInfo(
        buildInfo,
        deviceId: deviceId,
        scheme: scheme,
        isWatch: true,
      );
      if (allBuildSettings != null) {
        final String? fromBuild = allBuildSettings['INFOPLIST_KEY_WKCompanionAppBundleIdentifier'];
        if (bundleIdentifier == fromBuild) {
          return true;
        }
        if (fromBuild != null && fromBuild.contains(r'$')) {
          final String substitutedVariable = substituteXcodeVariables(fromBuild, allBuildSettings);
          if (substitutedVariable == bundleIdentifier) {
            return true;
          }
        }
      }
    }
    return false;
  }

  Future<void> _updateGeneratedXcodeConfigIfNeeded() async {
    if (globals.cache.isOlderThanToolsStamp(generatedXcodePropertiesFile)) {
      await xcode.updateGeneratedXcodeProperties(
        project: parent,
        buildInfo: BuildInfo.debug,
        targetOverride: bundle.defaultMainPath,
      );
    }
  }

  Future<void> _regenerateFromTemplateIfNeeded() async {
    if (!isModule) {
      return;
    }
    final bool pubspecChanged = globals.fsUtils.isOlderThanReference(
      entity: ephemeralModuleDirectory,
      referenceFile: parent.pubspecFile,
    );
    final bool toolingChanged = globals.cache.isOlderThanToolsStamp(ephemeralModuleDirectory);
    if (!pubspecChanged && !toolingChanged) {
      return;
    }

    ErrorHandlingFileSystem.deleteIfExists(ephemeralModuleDirectory, recursive: true);
    await _overwriteFromTemplate(
      globals.fs.path.join('module', 'ios', 'library'),
      ephemeralModuleDirectory,
    );
    // Add ephemeral host app, if a editable host app does not already exist.
    if (!_editableDirectory.existsSync()) {
      await _overwriteFromTemplate(
        globals.fs.path.join('module', 'ios', 'host_app_ephemeral'),
        ephemeralModuleDirectory,
      );
      if (hasPlugins(parent)) {
        await _overwriteFromTemplate(
          globals.fs.path.join('module', 'ios', 'host_app_ephemeral_cocoapods'),
          ephemeralModuleDirectory,
        );
      }
    }
  }

  @override
  File get generatedXcodePropertiesFile => _flutterLibRoot
    .childDirectory('Flutter')
    .childFile('Generated.xcconfig');

  /// No longer compiled to this location.
  ///
  /// Used only for "flutter clean" to remove old references.
  Directory get deprecatedCompiledDartFramework => _flutterLibRoot
      .childDirectory('Flutter')
      .childDirectory('App.framework');

  /// No longer copied to this location.
  ///
  /// Used only for "flutter clean" to remove old references.
  Directory get deprecatedProjectFlutterFramework => _flutterLibRoot
      .childDirectory('Flutter')
      .childDirectory('Flutter.framework');

  /// Used only for "flutter clean" to remove old references.
  File get flutterPodspec => _flutterLibRoot
      .childDirectory('Flutter')
      .childFile('Flutter.podspec');

  Directory get pluginRegistrantHost {
    return isModule
        ? _flutterLibRoot
            .childDirectory('Flutter')
            .childDirectory('FlutterPluginRegistrant')
        : hostAppRoot.childDirectory(XcodeBasedProject._defaultHostAppName);
  }

  File get pluginRegistrantHeader {
    final Directory registryDirectory = isModule ? pluginRegistrantHost.childDirectory('Classes') : pluginRegistrantHost;
    return registryDirectory.childFile('GeneratedPluginRegistrant.h');
  }

  File get pluginRegistrantImplementation {
    final Directory registryDirectory = isModule ? pluginRegistrantHost.childDirectory('Classes') : pluginRegistrantHost;
    return registryDirectory.childFile('GeneratedPluginRegistrant.m');
  }

  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 iosBundleIdentifier = parent.manifest.iosBundleIdentifier ?? 'com.example.${parent.manifest.appName}';

    final String? iosDevelopmentTeam = await getCodeSigningIdentityDevelopmentTeam(
      processManager: globals.processManager,
      platform: globals.platform,
      logger: globals.logger,
      config: globals.config,
      terminal: globals.terminal,
    );

    final String projectName = parent.manifest.appName;

    // The dart project_name is in snake_case, this variable is the Title Case of the Project Name.
    final String titleCaseProjectName = snakeCaseToTitleCase(projectName);

    template.render(
      target,
      <String, Object>{
        'ios': true,
        'projectName': projectName,
        'titleCaseProjectName': titleCaseProjectName,
        'iosIdentifier': iosBundleIdentifier,
        'hasIosDevelopmentTeam': iosDevelopmentTeam != null && iosDevelopmentTeam.isNotEmpty,
        'iosDevelopmentTeam': iosDevelopmentTeam ?? '',
      },
      printStatusWhenWriting: false,
    );
  }
}

/// The macOS sub project.
class MacOSProject extends XcodeBasedProject {
  MacOSProject.fromFlutter(this.parent);

  @override
  final FlutterProject parent;

  @override
  String get pluginConfigKey => MacOSPlugin.kConfigKey;

  @override
  bool existsSync() => hostAppRoot.existsSync();

  @override
  Directory get hostAppRoot => parent.directory.childDirectory('macos');

  /// The directory in the project that is managed by Flutter. As much as
  /// possible, files that are edited by Flutter tooling after initial project
  /// creation should live here.
  Directory get managedDirectory => hostAppRoot.childDirectory('Flutter');

  /// The subdirectory of [managedDirectory] that contains files that are
  /// generated on the fly. All generated files that are not intended to be
  /// checked in should live here.
  Directory get ephemeralDirectory => managedDirectory.childDirectory('ephemeral');

  /// The xcfilelist used to track the inputs for the Flutter script phase in
  /// the Xcode build.
  File get inputFileList => ephemeralDirectory.childFile('FlutterInputs.xcfilelist');

  /// The xcfilelist used to track the outputs for the Flutter script phase in
  /// the Xcode build.
  File get outputFileList => ephemeralDirectory.childFile('FlutterOutputs.xcfilelist');

  @override
  File get generatedXcodePropertiesFile => ephemeralDirectory.childFile('Flutter-Generated.xcconfig');

  File get pluginRegistrantImplementation => managedDirectory.childFile('GeneratedPluginRegistrant.swift');

  /// The 'AppDelegate.swift' file of the host app. This file might not exist if the app project uses Objective-C.
  File get appDelegateSwift => hostAppRoot.childDirectory('Runner').childFile('AppDelegate.swift');

  @override
  File xcodeConfigFor(String mode) => managedDirectory.childFile('Flutter-$mode.xcconfig');

  @override
  File get generatedEnvironmentVariableExportScript => ephemeralDirectory.childFile('flutter_export_environment.sh');

  /// The file where the Xcode build will write the name of the built app.
  ///
  /// Ideally this will be replaced in the future with inspection of the Runner
  /// scheme's target.
  File get nameFile => ephemeralDirectory.childFile('.app_filename');

  Future<void> ensureReadyForPlatformSpecificTooling() async {
    // TODO(stuartmorgan): Add create-from-template logic here.
    await _updateGeneratedXcodeConfigIfNeeded();
  }

  Future<void> _updateGeneratedXcodeConfigIfNeeded() async {
    if (globals.cache.isOlderThanToolsStamp(generatedXcodePropertiesFile)) {
      await xcode.updateGeneratedXcodeProperties(
        project: parent,
        buildInfo: BuildInfo.debug,
        useMacOSConfig: true,
      );
    }
  }
}
