// 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.

// @dart = 2.8

import 'package:file/file.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart';

import '../base/common.dart';
import '../base/error_handling_io.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/os.dart';
import '../base/platform.dart';
import '../base/process.dart';
import '../base/version.dart';
import '../build_info.dart';
import '../cache.dart';
import '../ios/xcodeproj.dart';
import '../project.dart';
import '../reporting/reporting.dart';

const String noCocoaPodsConsequence = '''
  CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side.
  Without CocoaPods, plugins will not work on iOS or macOS.
  For more info, see https://flutter.dev/platform-plugins''';

const String unknownCocoaPodsConsequence = '''
  Flutter is unable to determine the installed CocoaPods's version.
  Ensure that the output of 'pod --version' contains only digits and . to be recognized by Flutter.''';

const String brokenCocoaPodsConsequence = '''
  You appear to have CocoaPods installed but it is not working.
  This can happen if the version of Ruby that CocoaPods was installed with is different from the one being used to invoke it.
  This can usually be fixed by re-installing CocoaPods.''';

const String outOfDateFrameworksPodfileConsequence = '''
  This can cause a mismatched version of Flutter to be embedded in your app, which may result in App Store submission rejection or crashes.
  If you have local Podfile edits you would like to keep, see https://github.com/flutter/flutter/issues/24641 for instructions.''';

const String outOfDatePluginsPodfileConsequence = '''
  This can cause issues if your application depends on plugins that do not support iOS or macOS.
  See https://flutter.dev/docs/development/packages-and-plugins/developing-packages#plugin-platforms for details.
  If you have local Podfile edits you would like to keep, see https://github.com/flutter/flutter/issues/45197 for instructions.''';

const String cocoaPodsInstallInstructions = 'see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.';

const String podfileIosMigrationInstructions = '''
  rm ios/Podfile''';

const String podfileMacOSMigrationInstructions = '''
  rm macos/Podfile''';

/// Result of evaluating the CocoaPods installation.
enum CocoaPodsStatus {
  /// iOS plugins will not work, installation required.
  notInstalled,
  /// iOS plugins might not work, upgrade recommended.
  unknownVersion,
  /// iOS plugins will not work, upgrade required.
  belowMinimumVersion,
  /// iOS plugins may not work in certain situations (Swift, static libraries),
  /// upgrade recommended.
  belowRecommendedVersion,
  /// Everything should be fine.
  recommended,
  /// iOS plugins will not work, re-install required.
  brokenInstall,
}

String get cocoaPodsMinimumVersion => '1.9.0';
String get cocoaPodsRecommendedVersion => '1.10.0';

/// Cocoapods is a dependency management solution for iOS and macOS applications.
///
/// Cocoapods is generally installed via ruby gems and interacted with via
/// the `pod` CLI command.
///
/// See also:
///   * https://cocoapods.org/ - the cocoapods website.
///   * https://flutter.dev/docs/get-started/install/macos#deploy-to-ios-devices - instructions for
///     installing iOS/macOS dependencies.
class CocoaPods {
  CocoaPods({
    @required FileSystem fileSystem,
    @required ProcessManager processManager,
    @required XcodeProjectInterpreter xcodeProjectInterpreter,
    @required Logger logger,
    @required Platform platform,
    @required Usage usage,
  }) : _fileSystem = fileSystem,
      _processManager = processManager,
      _xcodeProjectInterpreter = xcodeProjectInterpreter,
      _logger = logger,
      _usage = usage,
      _processUtils = ProcessUtils(processManager: processManager, logger: logger),
      _operatingSystemUtils = OperatingSystemUtils(
        fileSystem: fileSystem,
        logger: logger,
        platform: platform,
        processManager: processManager,
      );

  final FileSystem _fileSystem;
  final ProcessManager _processManager;
  final ProcessUtils _processUtils;
  final OperatingSystemUtils _operatingSystemUtils;
  final XcodeProjectInterpreter _xcodeProjectInterpreter;
  final Logger _logger;
  final Usage _usage;

  Future<String> _versionText;

  Future<bool> get isInstalled =>
    _processUtils.exitsHappy(<String>['which', 'pod']);

  Future<String> get cocoaPodsVersionText {
    _versionText ??= _processUtils.run(
      <String>['pod', '--version'],
      environment: <String, String>{
        'LANG': 'en_US.UTF-8',
      },
    ).then<String>((RunResult result) {
      return result.exitCode == 0 ? result.stdout.trim() : null;
    }, onError: (dynamic _) => null);
    return _versionText;
  }

  Future<CocoaPodsStatus> get evaluateCocoaPodsInstallation async {
    if (!(await isInstalled)) {
      return CocoaPodsStatus.notInstalled;
    }
    final String versionText = await cocoaPodsVersionText;
    if (versionText == null) {
      return CocoaPodsStatus.brokenInstall;
    }
    try {
      final Version installedVersion = Version.parse(versionText);
      if (installedVersion == null) {
        return CocoaPodsStatus.unknownVersion;
      }
      if (installedVersion < Version.parse(cocoaPodsMinimumVersion)) {
        return CocoaPodsStatus.belowMinimumVersion;
      }
      if (installedVersion < Version.parse(cocoaPodsRecommendedVersion)) {
        return CocoaPodsStatus.belowRecommendedVersion;
      }
      return CocoaPodsStatus.recommended;
    } on FormatException {
      return CocoaPodsStatus.notInstalled;
    }
  }

  Future<bool> processPods({
    @required XcodeBasedProject xcodeProject,
    @required BuildMode buildMode,
    bool dependenciesChanged = true,
  }) async {
    if (!xcodeProject.podfile.existsSync()) {
      throwToolExit('Podfile missing');
    }
    bool podsProcessed = false;
    if (_shouldRunPodInstall(xcodeProject, dependenciesChanged)) {
      if (!await _checkPodCondition()) {
        throwToolExit('CocoaPods not installed or not in valid state.');
      }
      await _runPodInstall(xcodeProject, buildMode);
      podsProcessed = true;
    }
    _warnIfPodfileOutOfDate(xcodeProject);
    return podsProcessed;
  }

  /// Make sure the CocoaPods tools are in the right states.
  Future<bool> _checkPodCondition() async {
    final CocoaPodsStatus installation = await evaluateCocoaPodsInstallation;
    switch (installation) {
      case CocoaPodsStatus.notInstalled:
        _logger.printError(
          'Warning: CocoaPods not installed. Skipping pod install.\n'
          '$noCocoaPodsConsequence\n'
          'To install $cocoaPodsInstallInstructions\n',
          emphasis: true,
        );
        return false;
      case CocoaPodsStatus.brokenInstall:
        _logger.printError(
          'Warning: CocoaPods is installed but broken. Skipping pod install.\n'
          '$brokenCocoaPodsConsequence\n'
          'To re-install $cocoaPodsInstallInstructions\n',
          emphasis: true,
        );
        return false;
      case CocoaPodsStatus.unknownVersion:
        _logger.printError(
          'Warning: Unknown CocoaPods version installed.\n'
          '$unknownCocoaPodsConsequence\n'
          'To upgrade $cocoaPodsInstallInstructions\n',
          emphasis: true,
        );
        break;
      case CocoaPodsStatus.belowMinimumVersion:
        _logger.printError(
          'Warning: CocoaPods minimum required version $cocoaPodsMinimumVersion or greater not installed. Skipping pod install.\n'
          '$noCocoaPodsConsequence\n'
          'To upgrade $cocoaPodsInstallInstructions\n',
          emphasis: true,
        );
        return false;
      case CocoaPodsStatus.belowRecommendedVersion:
        _logger.printError(
          'Warning: CocoaPods recommended version $cocoaPodsRecommendedVersion or greater not installed.\n'
          'Pods handling may fail on some projects involving plugins.\n'
          'To upgrade $cocoaPodsInstallInstructions\n',
          emphasis: true,
        );
        break;
      case CocoaPodsStatus.recommended:
        break;
    }

    return true;
  }

  /// Ensures the given Xcode-based sub-project of a parent Flutter project
  /// contains a suitable `Podfile` and that its `Flutter/Xxx.xcconfig` files
  /// include pods configuration.
  Future<void> setupPodfile(XcodeBasedProject xcodeProject) async {
    if (!_xcodeProjectInterpreter.isInstalled) {
      // Don't do anything for iOS when host platform doesn't support it.
      return;
    }
    final Directory runnerProject = xcodeProject.xcodeProject;
    if (!runnerProject.existsSync()) {
      return;
    }
    final File podfile = xcodeProject.podfile;
    if (podfile.existsSync()) {
      addPodsDependencyToFlutterXcconfig(xcodeProject);
      return;
    }
    String podfileTemplateName;
    if (xcodeProject is MacOSProject) {
      podfileTemplateName = 'Podfile-macos';
    } else {
      final bool isSwift = (await _xcodeProjectInterpreter.getBuildSettings(
        runnerProject.path,
      )).containsKey('SWIFT_VERSION');
      podfileTemplateName = isSwift ? 'Podfile-ios-swift' : 'Podfile-ios-objc';
    }
    final File podfileTemplate = _fileSystem.file(_fileSystem.path.join(
      Cache.flutterRoot,
      'packages',
      'flutter_tools',
      'templates',
      'cocoapods',
      podfileTemplateName,
    ));
    podfileTemplate.copySync(podfile.path);
    addPodsDependencyToFlutterXcconfig(xcodeProject);
  }

  /// Ensures all `Flutter/Xxx.xcconfig` files for the given Xcode-based
  /// sub-project of a parent Flutter project include pods configuration.
  void addPodsDependencyToFlutterXcconfig(XcodeBasedProject xcodeProject) {
    _addPodsDependencyToFlutterXcconfig(xcodeProject, 'Debug');
    _addPodsDependencyToFlutterXcconfig(xcodeProject, 'Release');
  }

  void _addPodsDependencyToFlutterXcconfig(XcodeBasedProject xcodeProject, String mode) {
    final File file = xcodeProject.xcodeConfigFor(mode);
    if (file.existsSync()) {
      final String content = file.readAsStringSync();
      final String includeFile = 'Pods/Target Support Files/Pods-Runner/Pods-Runner.${mode
          .toLowerCase()}.xcconfig';
      final String include = '#include? "$includeFile"';
      if (!content.contains(includeFile)) {
        file.writeAsStringSync('$include\n$content', flush: true);
      }
    }
  }

  /// Ensures that pod install is deemed needed on next check.
  void invalidatePodInstallOutput(XcodeBasedProject xcodeProject) {
    final File manifestLock = xcodeProject.podManifestLock;
    ErrorHandlingFileSystem.deleteIfExists(manifestLock);
  }

  // Check if you need to run pod install.
  // The pod install will run if any of below is true.
  // 1. Flutter dependencies have changed
  // 2. Podfile.lock doesn't exist or is older than Podfile
  // 3. Pods/Manifest.lock doesn't exist (It is deleted when plugins change)
  // 4. Podfile.lock doesn't match Pods/Manifest.lock.
  bool _shouldRunPodInstall(XcodeBasedProject xcodeProject, bool dependenciesChanged) {
    if (dependenciesChanged) {
      return true;
    }

    final File podfileFile = xcodeProject.podfile;
    final File podfileLockFile = xcodeProject.podfileLock;
    final File manifestLockFile = xcodeProject.podManifestLock;

    return !podfileLockFile.existsSync()
        || !manifestLockFile.existsSync()
        || podfileLockFile.statSync().modified.isBefore(podfileFile.statSync().modified)
        || podfileLockFile.readAsStringSync() != manifestLockFile.readAsStringSync();
  }

  Future<void> _runPodInstall(XcodeBasedProject xcodeProject, BuildMode buildMode) async {
    final Status status = _logger.startProgress('Running pod install...');
    final ProcessResult result = await _processManager.run(
      <String>['pod', 'install', '--verbose'],
      workingDirectory: _fileSystem.path.dirname(xcodeProject.podfile.path),
      environment: <String, String>{
        // See https://github.com/flutter/flutter/issues/10873.
        // CocoaPods analytics adds a lot of latency.
        'COCOAPODS_DISABLE_STATS': 'true',
        'LANG': 'en_US.UTF-8',
      },
    );
    status.stop();
    if (_logger.isVerbose || result.exitCode != 0) {
      final String stdout = result.stdout as String;
      if (stdout.isNotEmpty) {
        _logger.printStatus("CocoaPods' output:\n↳");
        _logger.printStatus(stdout, indent: 4);
      }
      final String stderr = result.stderr as String;
      if (stderr.isNotEmpty) {
        _logger.printStatus('Error output from CocoaPods:\n↳');
        _logger.printStatus(stderr, indent: 4);
      }
    }
    if (result.exitCode != 0) {
      invalidatePodInstallOutput(xcodeProject);
      _diagnosePodInstallFailure(result);
      throwToolExit('Error running pod install');
    }
  }

  void _diagnosePodInstallFailure(ProcessResult result) {
    if (result.stdout is! String) {
      return;
    }
    final String stdout = result.stdout as String;
    if (stdout.contains('out-of-date source repos')) {
      _logger.printError(
        "Error: CocoaPods's specs repository is too out-of-date to satisfy dependencies.\n"
        'To update the CocoaPods specs, run:\n'
        '  pod repo update\n',
        emphasis: true,
      );
    } else if (stdout.contains('Init_ffi_c') &&
        stdout.contains('symbol not found') &&
        _operatingSystemUtils.hostPlatform == HostPlatform.darwin_arm) {
      // https://github.com/flutter/flutter/issues/70796
      UsageEvent(
        'pod-install-failure',
        'arm-ffi',
        flutterUsage: _usage,
      ).send();
      _logger.printError(
        'Error: To set up CocoaPods for ARM macOS, run:\n'
        '  arch -x86_64 sudo gem install ffi\n',
        emphasis: true,
      );
    }
  }

  void _warnIfPodfileOutOfDate(XcodeBasedProject xcodeProject) {
    final bool isIos = xcodeProject is IosProject;
    if (isIos) {
      // Previously, the Podfile created a symlink to the cached artifacts engine framework
      // and installed the Flutter pod from that path. This could get out of sync with the copy
      // of the Flutter engine that was copied to ios/Flutter by the xcode_backend script.
      // It was possible for the symlink to point to a Debug version of the engine when the
      // Xcode build configuration was Release, which caused App Store submission rejections.
      //
      // Warn the user if they are still symlinking to the framework.
      final Link flutterSymlink = _fileSystem.link(_fileSystem.path.join(
        (xcodeProject as IosProject).symlinks.path,
        'flutter',
      ));
      if (flutterSymlink.existsSync()) {
        throwToolExit(
          'Warning: Podfile is out of date\n'
              '$outOfDateFrameworksPodfileConsequence\n'
              'To regenerate the Podfile, run:\n'
              '$podfileIosMigrationInstructions\n',
        );
      }
    }
    // Most of the pod and plugin parsing logic was moved from the Podfile
    // into the tool's podhelper.rb script. If the Podfile still references
    // the old parsed .flutter-plugins file, prompt the regeneration. Old line was:
    // plugin_pods = parse_KV_file('../.flutter-plugins')
    if (xcodeProject.podfile.existsSync() &&
      xcodeProject.podfile.readAsStringSync().contains('.flutter-plugins\'')) {
      const String error = 'Warning: Podfile is out of date\n'
          '$outOfDatePluginsPodfileConsequence\n'
          'To regenerate the Podfile, run:\n';
      if (isIos) {
        throwToolExit('$error\n$podfileIosMigrationInstructions\n');
      } else {
        // The old macOS Podfile will work until `.flutter-plugins` is removed.
        // Warn instead of exit.
        _logger.printError('$error\n$podfileMacOSMigrationInstructions\n', emphasis: true);
      }
    }
  }
}
