// 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:async';
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.dart';

typedef void Print(Object object);

/// Lint the CocoaPod podspecs and run unit tests.
///
/// See https://guides.cocoapods.org/terminal/commands.html#pod_lib_lint.
class LintPodspecsCommand extends PluginCommand {
  LintPodspecsCommand(
    Directory packagesDir,
    FileSystem fileSystem, {
    ProcessRunner processRunner = const ProcessRunner(),
    this.platform = const LocalPlatform(),
    Print print = print,
  })  : _print = print,
        super(packagesDir, fileSystem, processRunner: processRunner) {
    argParser.addMultiOption('skip',
        help:
            'Skip all linting for podspecs with this basename (example: federated plugins with placeholder podspecs)',
        valueHelp: 'podspec_file_name');
    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;

  final Print _print;

  @override
  Future<Null> run() async {
    if (!platform.isMacOS) {
      _print('Detected platform is not macOS, skipping podspec lint');
      return;
    }

    checkSharding();

    await processRunner.runAndExitOnError('which', <String>['pod'],
        workingDir: packagesDir);

    _print('Starting podspec lint test');

    final List<String> failingPlugins = <String>[];
    for (File podspec in await _podspecsToLint()) {
      if (!await _lintPodspec(podspec)) {
        failingPlugins.add(p.basenameWithoutExtension(podspec.path));
      }
    }

    _print('\n\n');
    if (failingPlugins.isNotEmpty) {
      _print('The following plugins have podspec errors (see above):');
      failingPlugins.forEach((String plugin) {
        _print(' * $plugin');
      });
      throw ToolExit(1);
    }
  }

  Future<List<File>> _podspecsToLint() async {
    final List<File> podspecs = await getFiles().where((File entity) {
      final String filePath = entity.path;
      return p.extension(filePath) == '.podspec' &&
          !argResults['skip'].contains(p.basenameWithoutExtension(filePath));
    }).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,
      {bool libraryLint}) async {
    final bool allowWarnings = argResults['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',
      if (allowWarnings) '--allow-warnings',
      if (libraryLint) '--use-libraries'
    ];

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