// Copyright 2013 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:convert';
import 'dart:io';

import 'package:file/file.dart';
import 'package:path/path.dart' as p;
import 'package:platform/platform.dart';

import 'common/core.dart';
import 'common/package_looping_command.dart';
import 'common/process_runner.dart';

const int _exitUnsupportedPlatform = 2;

/// Lint the CocoaPod podspecs and run unit tests.
///
/// See https://guides.cocoapods.org/terminal/commands.html#pod_lib_lint.
class LintPodspecsCommand extends PackageLoopingCommand {
  /// Creates an instance of the linter command.
  LintPodspecsCommand(
    Directory packagesDir, {
    ProcessRunner processRunner = const ProcessRunner(),
    Platform platform = const LocalPlatform(),
  })  : _platform = platform,
        super(packagesDir, processRunner: processRunner) {
    argParser.addMultiOption('ignore-warnings',
        help:
            'Do not pass --allow-warnings flag to "pod lib lint" for podspecs '
            'with this basename (example: plugins with known warnings)',
        valueHelp: 'podspec_file_name');
  }

  @override
  final String name = 'podspecs';

  @override
  List<String> get aliases => <String>['podspec'];

  @override
  final String description =
      'Runs "pod lib lint" on all iOS and macOS plugin podspecs.\n\n'
      'This command requires "pod" and "flutter" to be in your path. Runs on macOS only.';

  final Platform _platform;

  @override
  Future<void> initializeRun() async {
    if (!_platform.isMacOS) {
      printError('This command is only supported on macOS');
      throw ToolExit(_exitUnsupportedPlatform);
    }

    await processRunner.run(
      'which',
      <String>['pod'],
      workingDir: packagesDir,
      exitOnError: true,
      logOnError: true,
    );
  }

  @override
  Future<List<String>> runForPackage(Directory package) async {
    final List<String> errors = <String>[];
    for (final File podspec in await _podspecsToLint(package)) {
      if (!await _lintPodspec(podspec)) {
        errors.add(p.basename(podspec.path));
      }
    }
    return errors;
  }

  Future<List<File>> _podspecsToLint(Directory package) async {
    final List<File> podspecs =
        await getFilesForPackage(package).where((File entity) {
      final String filePath = entity.path;
      return p.extension(filePath) == '.podspec';
    }).toList();

    podspecs.sort(
        (File a, File b) => p.basename(a.path).compareTo(p.basename(b.path)));
    return podspecs;
  }

  Future<bool> _lintPodspec(File podspec) async {
    // Do not run the static analyzer on plugins with known analyzer issues.
    final String podspecPath = podspec.path;

    final String podspecBasename = p.basename(podspecPath);
    print('Linting $podspecBasename');

    // Lint plugin as framework (use_frameworks!).
    final ProcessResult frameworkResult =
        await _runPodLint(podspecPath, libraryLint: true);
    print(frameworkResult.stdout);
    print(frameworkResult.stderr);

    // Lint plugin as library.
    final ProcessResult libraryResult =
        await _runPodLint(podspecPath, libraryLint: false);
    print(libraryResult.stdout);
    print(libraryResult.stderr);

    return frameworkResult.exitCode == 0 && libraryResult.exitCode == 0;
  }

  Future<ProcessResult> _runPodLint(String podspecPath,
      {required bool libraryLint}) async {
    final bool allowWarnings = (getStringListArg('ignore-warnings'))
        .contains(p.basenameWithoutExtension(podspecPath));
    final List<String> arguments = <String>[
      'lib',
      'lint',
      podspecPath,
      '--configuration=Debug', // Release targets unsupported arm64 simulators. Use Debug to only build against targeted x86_64 simulator devices.
      '--skip-tests',
      '--use-modular-headers', // Flutter sets use_modular_headers! in its templates.
      if (allowWarnings) '--allow-warnings',
      if (libraryLint) '--use-libraries'
    ];

    print('Running "pod ${arguments.join(' ')}"');
    return processRunner.run('pod', arguments,
        workingDir: packagesDir, stdoutEncoding: utf8, stderrEncoding: utf8);
  }
}
