// 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 'package:meta/meta.dart';
import 'package:process/process.dart';

import '../artifacts.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/logger.dart';
import '../base/platform.dart';
import '../base/terminal.dart';
import '../project.dart';
import '../project_validator.dart';
import '../runner/flutter_command.dart';
import 'analyze_base.dart';
import 'analyze_continuously.dart';
import 'analyze_once.dart';
import 'android_analyze.dart';
import 'ios_analyze.dart';
import 'validate_project.dart';

class AnalyzeCommand extends FlutterCommand {
  AnalyzeCommand({
    bool verboseHelp = false,
    this.workingDirectory,
    required FileSystem fileSystem,
    required Platform platform,
    required Terminal terminal,
    required Logger logger,
    required ProcessManager processManager,
    required Artifacts artifacts,
    required List<ProjectValidator> allProjectValidators,
    required bool suppressAnalytics,
  }) : _artifacts = artifacts,
       _fileSystem = fileSystem,
       _processManager = processManager,
       _logger = logger,
       _terminal = terminal,
       _allProjectValidators = allProjectValidators,
       _platform = platform,
       _suppressAnalytics = suppressAnalytics {
    argParser.addFlag('flutter-repo',
        negatable: false,
        help: 'Include all the examples and tests from the Flutter repository.',
        hide: !verboseHelp);
    argParser.addFlag('current-package',
        help: 'Analyze the current project, if applicable.', defaultsTo: true);
    argParser.addFlag('dartdocs',
        negatable: false,
        help: '(deprecated) List every public member that is lacking documentation. '
              'This command will be removed in a future version of Flutter.',
        hide: !verboseHelp);
    argParser.addFlag('watch',
        help: 'Run analysis continuously, watching the filesystem for changes.',
        negatable: false);
    argParser.addOption('write',
        valueHelp: 'file',
        help: 'Also output the results to a file. This is useful with "--watch" '
              'if you want a file to always contain the latest results.');
    argParser.addOption('dart-sdk',
        valueHelp: 'path-to-sdk',
        help: 'The path to the Dart SDK.',
        hide: !verboseHelp);
    argParser.addOption('protocol-traffic-log',
        valueHelp: 'path-to-protocol-traffic-log',
        help: 'The path to write the request and response protocol. This is '
              'only intended to be used for debugging the tooling.',
        hide: !verboseHelp);
    argParser.addFlag('suggestions',
        help: 'Show suggestions about the current flutter project.'
    );
    argParser.addFlag('machine',
        negatable: false,
        help: 'Dumps a JSON with a subset of relevant data about the tool, project, '
              'and environment.',
        hide: !verboseHelp,
    );

    // Hidden option to enable a benchmarking mode.
    argParser.addFlag('benchmark',
        negatable: false,
        hide: !verboseHelp,
        help: 'Also output the analysis time.');

    usesPubOption();

    // Not used by analyze --watch
    argParser.addFlag('congratulate',
        help: 'Show output even when there are no errors, warnings, hints, or lints. '
              'Ignored if "--watch" is specified.',
        defaultsTo: true);
    argParser.addFlag('preamble',
        defaultsTo: true,
        help: 'When analyzing the flutter repository, display the number of '
              'files that will be analyzed.\n'
              'Ignored if "--watch" is specified.');
    argParser.addFlag('fatal-infos',
        help: 'Treat info level issues as fatal.',
        defaultsTo: true);
    argParser.addFlag('fatal-warnings',
        help: 'Treat warning level issues as fatal.',
        defaultsTo: true);

    argParser.addFlag('android',
      negatable: false,
      help: 'Analyze Android sub-project. Used by internal tools only.',
      hide: !verboseHelp,
    );

    argParser.addFlag('ios',
      negatable: false,
      help: 'Analyze iOS Xcode sub-project. Used by internal tools only.',
      hide: !verboseHelp,
    );

    if (verboseHelp) {
      argParser.addSeparator('Usage: flutter analyze --android [arguments]');
    }

    argParser.addFlag('list-build-variants',
      negatable: false,
      help: 'Print out a list of available build variants for the '
          'Android sub-project.',
      hide: !verboseHelp,
    );

    argParser.addFlag('output-app-link-settings',
      negatable: false,
      help: 'Output a JSON with Android app link settings into a file. '
          'The "--build-variant" must also be set.',
      hide: !verboseHelp,
    );

    argParser.addOption('build-variant',
      help: 'Sets the Android build variant to be analyzed.',
      valueHelp: 'build variant',
      hide: !verboseHelp,
    );

    if (verboseHelp) {
      argParser.addSeparator('Usage: flutter analyze --ios [arguments]');
    }

    argParser.addFlag('list-build-options',
      help: 'Print out a list of available build options for the '
          'iOS Xcode sub-project.',
      hide: !verboseHelp,
    );

    argParser.addFlag('output-universal-link-settings',
      negatable: false,
      help: 'Output a JSON with iOS Xcode universal link settings into a file. '
          'The "--configuration" and "--target" must be set.',
      hide: !verboseHelp,
    );

    argParser.addOption('configuration',
      help: 'Sets the iOS build configuration to be analyzed.',
      valueHelp: 'configuration',
      hide: !verboseHelp,
    );

    argParser.addOption('target',
      help: 'Sets the iOS build target to be analyzed.',
      valueHelp: 'target',
      hide: !verboseHelp,
    );
  }

  /// The working directory for testing analysis using dartanalyzer.
  final Directory? workingDirectory;

  final Artifacts _artifacts;
  final FileSystem _fileSystem;
  final Logger _logger;
  final Terminal _terminal;
  final ProcessManager _processManager;
  final Platform _platform;
  final List<ProjectValidator> _allProjectValidators;
  final bool _suppressAnalytics;

  @override
  String get name => 'analyze';

  @override
  String get description => "Analyze the project's Dart code.";

  @override
  String get category => FlutterCommandCategory.project;

  @visibleForTesting
  List<ProjectValidator> allProjectValidators() => _allProjectValidators;

  @override
  bool get shouldRunPub {
    // If they're not analyzing the current project.
    if (!boolArg('current-package')) {
      return false;
    }

    // Or we're not in a project directory.
    if (!_fileSystem.file('pubspec.yaml').existsSync()) {
      return false;
    }

    // Don't run pub if asking for machine output.
    if (boolArg('machine')) {
      return false;
    }

    // Don't run pub if asking for android analysis.
    if (boolArg('android')) {
      return false;
    }

    return super.shouldRunPub;
  }

  @override
  Future<FlutterCommandResult> runCommand() async {
    if (boolArg('android')) {
      final AndroidAnalyzeOption option;
      final String? buildVariant;
      if (argResults!['list-build-variants'] as bool && argResults!['output-app-link-settings'] as bool) {
        throwToolExit('Only one of "--list-build-variants" or "--output-app-link-settings" can be provided');
      }
      if (argResults!['list-build-variants'] as bool) {
        option = AndroidAnalyzeOption.listBuildVariant;
        buildVariant = null;
      } else if (argResults!['output-app-link-settings'] as bool) {
        option = AndroidAnalyzeOption.outputAppLinkSettings;
        buildVariant = argResults!['build-variant'] as String?;
        if (buildVariant == null) {
          throwToolExit('"--build-variant" must be provided');
        }
      } else {
        throwToolExit('No argument is provided to analyze. Use -h to see available commands.');
      }
      final Set<String> items = findDirectories(argResults!, _fileSystem);
      final String directoryPath;
      if (items.isEmpty) { // user did not specify any path
        directoryPath = _fileSystem.currentDirectory.path;
      } else if (items.length > 1) { // if the user sends more than one path
        throwToolExit('The Android analyze can process only one directory path');
      } else {
        directoryPath = items.first;
      }
      await AndroidAnalyze(
        fileSystem: _fileSystem,
        option: option,
        userPath: directoryPath,
        buildVariant: buildVariant,
        logger: _logger,
      ).analyze();
    } else if (boolArg('ios')) {
      final IOSAnalyzeOption option;
      final String? configuration;
      final String? target;
      if (argResults!['list-build-options'] as bool && argResults!['output-universal-link-settings'] as bool) {
        throwToolExit('Only one of "--list-build-options" or "--output-universal-link-settings" can be provided');
      }
      if (argResults!['list-build-options'] as bool) {
        option = IOSAnalyzeOption.listBuildOptions;
        configuration = null;
        target = null;
      } else if (argResults!['output-universal-link-settings'] as bool) {
        option = IOSAnalyzeOption.outputUniversalLinkSettings;
        configuration = argResults!['configuration'] as String?;
        if (configuration == null) {
          throwToolExit('"--configuration" must be provided');
        }
        target = argResults!['target'] as String?;
        if (target == null) {
          throwToolExit('"--target" must be provided');
        }
      } else {
        throwToolExit('No argument is provided to analyze. Use -h to see available commands.');
      }
      final Set<String> items = findDirectories(argResults!, _fileSystem);
      final String directoryPath;
      if (items.isEmpty) { // user did not specify any path
        directoryPath = _fileSystem.currentDirectory.path;
      } else if (items.length > 1) { // if the user sends more than one path
        throwToolExit('The iOS analyze can process only one directory path');
      } else {
        directoryPath = items.first;
      }
      await IOSAnalyze(
        project: FlutterProject.fromDirectory(_fileSystem.directory(directoryPath)),
        option: option,
        configuration: configuration,
        target: target,
        logger: _logger,
      ).analyze();
    } else if (boolArg('suggestions')) {
      final String directoryPath;
      if (boolArg('watch')) {
        throwToolExit('flag --watch is not compatible with --suggestions');
      }
      if (workingDirectory == null) {
        final Set<String> items = findDirectories(argResults!, _fileSystem);
        if (items.isEmpty) { // user did not specify any path
          directoryPath = _fileSystem.currentDirectory.path;
          _logger.printTrace('Showing suggestions for current directory: $directoryPath');
        } else if (items.length > 1) { // if the user sends more than one path
          throwToolExit('The suggestions flag can process only one directory path');
        } else {
          directoryPath = items.first;
        }
      } else {
        directoryPath = workingDirectory!.path;
      }
      return ValidateProject(
        fileSystem: _fileSystem,
        logger: _logger,
        allProjectValidators: _allProjectValidators,
        userPath: directoryPath,
        processManager: _processManager,
        machine: boolArg('machine'),
      ).run();
    } else if (boolArg('watch')) {
      await AnalyzeContinuously(
        argResults!,
        runner!.getRepoPackages(),
        fileSystem: _fileSystem,
        logger: _logger,
        platform: _platform,
        processManager: _processManager,
        terminal: _terminal,
        artifacts: _artifacts,
        suppressAnalytics: _suppressAnalytics,
      ).analyze();
    } else {
      await AnalyzeOnce(
        argResults!,
        runner!.getRepoPackages(),
        workingDirectory: workingDirectory,
        fileSystem: _fileSystem,
        logger: _logger,
        platform: _platform,
        processManager: _processManager,
        terminal: _terminal,
        artifacts: _artifacts,
        suppressAnalytics: _suppressAnalytics,
      ).analyze();
    }
    return FlutterCommandResult.success();
  }
}
