// Copyright (c) 2020, the Dart project authors. Please see the AUTHORS file
// for details. 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:io' hide File;

import 'package:analyzer/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/diagnostic/diagnostic.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/file_system/file_system.dart'
    show File, ResourceProvider;
import 'package:analyzer/file_system/physical_file_system.dart';
import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
import 'package:analyzer/src/dart/analysis/experiments.dart';
import 'package:analyzer/src/error/codes.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/util/sdk.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart'
    hide AnalysisError;
import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:cli_util/cli_logging.dart';
import 'package:meta/meta.dart';
import 'package:nnbd_migration/src/edit_plan.dart';
import 'package:nnbd_migration/src/exceptions.dart';
import 'package:nnbd_migration/src/front_end/dartfix_listener.dart';
import 'package:nnbd_migration/src/front_end/driver_provider_impl.dart';
import 'package:nnbd_migration/src/front_end/migration_state.dart';
import 'package:nnbd_migration/src/front_end/non_nullable_fix.dart';
import 'package:nnbd_migration/src/messages.dart';
import 'package:nnbd_migration/src/utilities/progress_bar.dart';
import 'package:nnbd_migration/src/utilities/source_edit_diff_formatter.dart';
import 'package:path/path.dart' show Context;

String _pluralize(int count, String single, {String multiple}) {
  return count == 1 ? single : (multiple ?? '${single}s');
}

String _removePeriod(String value) {
  return value.endsWith('.') ? value.substring(0, value.length - 1) : value;
}

/// The result of a round of static analysis; primarily a list of
/// [AnalysisError]s.
class AnalysisResult {
  final List<AnalysisError> errors;
  final Map<String, LineInfo> lineInfo;
  final Context pathContext;
  final String rootDirectory;

  AnalysisResult(
      this.errors, this.lineInfo, this.pathContext, this.rootDirectory) {
    errors.sort((AnalysisError one, AnalysisError two) {
      if (one.source != two.source) {
        return one.source.fullName.compareTo(two.source.fullName);
      }
      return one.offset - two.offset;
    });
  }

  bool get hasErrors => errors.isNotEmpty;

  /// Whether the errors include any which may be the result of not yet having
  /// run "pub get".
  bool get hasImportErrors => errors.any(
      (error) => error.errorCode == CompileTimeErrorCode.URI_DOES_NOT_EXIST);

  /// Converts the list of errors into JSON, for displaying in the web preview.
  List<Map<String, dynamic>> toJson() {
    var result = <Map<String, dynamic>>[];
    // severity • Message ... at foo/bar.dart:6:1 • (error_code)
    for (var error in errors) {
      var lineInfoForThisFile = lineInfo[error.source.fullName];
      var location = lineInfoForThisFile.getLocation(error.offset);
      var path =
          pathContext.relative(error.source.fullName, from: rootDirectory);
      result.add({
        'severity': error.severity.name,
        'message': _removePeriod(error.message),
        'location': '$path:${location.lineNumber}:${location.columnNumber}',
        'code': error.errorCode.name.toLowerCase(),
      });
    }
    return result;
  }
}

/// Data structure recording command-line options for the migration tool that
/// have been passed in by the client.
class CommandLineOptions {
  static const applyChangesFlag = 'apply-changes';
  static const helpFlag = 'help';
  static const ignoreErrorsFlag = 'ignore-errors';
  static const ignoreExceptionsFlag = 'ignore-exceptions';
  static const previewHostnameOption = 'preview-hostname';
  static const previewPortOption = 'preview-port';
  static const sdkPathOption = 'sdk-path';
  static const skipImportCheckFlag = 'skip-import-check';

  /// TODO(paulberry): remove this flag once internal sources have been updated.
  @Deprecated('The migration tool no longer performs "pub outdated" checks')
  static const skipPubOutdatedFlag = 'skip-pub-outdated';
  static const summaryOption = 'summary';
  static const verboseFlag = 'verbose';
  static const webPreviewFlag = 'web-preview';

  final bool applyChanges;

  final String directory;

  final bool ignoreErrors;

  final bool ignoreExceptions;

  final String previewHostname;

  final int previewPort;

  final String sdkPath;

  final bool skipImportCheck;

  final String summary;

  final bool webPreview;

  CommandLineOptions(
      {@required
          this.applyChanges,
      @required
          this.directory,
      @required
          this.ignoreErrors,
      @required
          this.ignoreExceptions,
      @required
          this.previewHostname,
      @required
          this.previewPort,
      @required
          this.sdkPath,
      // TODO(paulberry): make this parameter required once internal sources
      // have been updated.
      bool skipImportCheck,
      // TODO(paulberry): remove this flag once internal sources have been
      // updated.
      @Deprecated('The migration tool no longer performs "pub outdated" checks')
          bool skipPubOutdated = false,
      @required
          this.summary,
      @required
          this.webPreview})
      // `skipImportCheck` has replaced `skipPubOutdated`, so if the caller
      // specifies the latter but not the former, carry it over.
      // TODO(paulberry): remove this logic once internal sources have been
      // updated.
      : skipImportCheck = skipImportCheck ?? skipPubOutdated;
}

// TODO(devoncarew): Refactor so this class extends DartdevCommand.
class MigrateCommand extends Command<int> {
  static const String cmdName = 'migrate';

  static const String cmdDescription =
      'Perform a null safety migration on a project or package.';

  static const String migrationGuideLink =
      'See https://dart.dev/go/null-safety-migration for a migration guide.';

  /// Return whether the SDK has null safety on by default.
  static bool get nullSafetyOnByDefault => IsEnabledByDefault.non_nullable;

  final bool verbose;

  ArgParser _argParser;

  MigrateCommand({this.verbose = false}) {
    MigrationCli._defineOptions(argParser, !verbose);
  }

  @override
  ArgParser get argParser {
    // We override this in order to configure the help text line wrapping.
    return _argParser ??= ArgParser(
      usageLineLength: stdout.hasTerminal ? stdout.terminalColumns : null,
    );
  }

  @override
  String get description => '$cmdDescription\n\n$migrationGuideLink';

  @override
  String get invocation {
    return '${super.invocation} [project or directory]';
  }

  @override
  String get name => cmdName;

  @override
  FutureOr<int> run() async {
    var cli = MigrationCli(binaryName: 'dart $name');
    try {
      await cli.decodeCommandLineArgs(argResults, isVerbose: verbose)?.run();
    } on MigrationExit catch (migrationExit) {
      return migrationExit.exitCode;
    }
    return 0;
  }
}

/// Command-line API for the migration tool, with additional parameters exposed
/// for testing.
///
/// Recommended usage: create an instance of this object and call
/// [decodeCommandLineArgs].  If it returns non-null, call
/// [MigrationCliRunner.run] on the result.  If either method throws a
/// [MigrationExit], exit with the error code contained therein.
class MigrationCli {
  /// A list of all the command-line options supported by the tool.
  ///
  /// This may be used by clients that wish to run migration but provide their
  /// own command-line interface.
  static final List<MigrationCliOption> options = [
    MigrationCliOption(
        CommandLineOptions.verboseFlag,
        (parser, hide) => parser.addFlag(
              CommandLineOptions.verboseFlag,
              abbr: 'v',
              defaultsTo: false,
              help: 'Show additional command output.',
              negatable: false,
            )),
    MigrationCliOption(
        CommandLineOptions.applyChangesFlag,
        (parser, hide) => parser.addFlag(CommandLineOptions.applyChangesFlag,
            defaultsTo: false,
            negatable: false,
            help:
                'Apply the proposed null safety changes to the files on disk.')),
    MigrationCliOption(
        CommandLineOptions.ignoreErrorsFlag,
        (parser, hide) => parser.addFlag(
              CommandLineOptions.ignoreErrorsFlag,
              defaultsTo: false,
              negatable: false,
              help:
                  'Attempt to perform null safety analysis even if the package has '
                  'analysis errors.',
            )),
    MigrationCliOption(
        CommandLineOptions.skipImportCheckFlag,
        (parser, hide) => parser.addFlag(
              CommandLineOptions.skipImportCheckFlag,
              defaultsTo: false,
              negatable: false,
              help: 'Go ahead with migration even if some imported files have '
                  'not yet been migrated.',
            )),
    MigrationCliOption.separator('Web interface options:'),
    MigrationCliOption(
        CommandLineOptions.webPreviewFlag,
        (parser, hide) => parser.addFlag(
              CommandLineOptions.webPreviewFlag,
              defaultsTo: true,
              negatable: true,
              help:
                  'Show an interactive preview of the proposed null safety changes '
                  'in a browser window. Use --no-web-preview to print proposed changes '
                  'to the console.',
            )),
    MigrationCliOption(
        CommandLineOptions.previewHostnameOption,
        (parser, hide) => parser.addOption(
              CommandLineOptions.previewHostnameOption,
              defaultsTo: 'localhost',
              valueHelp: 'host',
              help: 'Run the preview server on the specified hostname. If not '
                  'specified, "localhost" is used. Use "any" to specify IPv6.any or '
                  'IPv4.any.',
            )),
    MigrationCliOption(
        CommandLineOptions.previewPortOption,
        (parser, hide) => parser.addOption(
              CommandLineOptions.previewPortOption,
              valueHelp: 'port',
              help:
                  'Run the preview server on the specified port. If not specified, '
                  'dynamically allocate a port.',
            )),
    MigrationCliOption.separator('Additional options:'),
    MigrationCliOption(
        CommandLineOptions.summaryOption,
        (parser, hide) => parser.addOption(
              CommandLineOptions.summaryOption,
              help: 'Output a machine-readable summary of migration changes.',
              valueHelp: 'path',
            )),
    // hidden options
    MigrationCliOption(
        CommandLineOptions.ignoreExceptionsFlag,
        (parser, hide) => parser.addFlag(
              CommandLineOptions.ignoreExceptionsFlag,
              defaultsTo: false,
              negatable: false,
              help:
                  'Attempt to perform null safety analysis even if exceptions occur.',
              hide: hide,
            )),
    MigrationCliOption(
        CommandLineOptions.sdkPathOption,
        (parser, hide) => parser.addOption(
              CommandLineOptions.sdkPathOption,
              valueHelp: 'sdk-path',
              help: 'The path to the Dart SDK.',
              hide: hide,
            )),
  ];

  /// The name of the executable, for reporting in help messages.
  final String binaryName;

  /// The SDK path that should be used if none is provided by the user.  Used in
  /// testing to install a mock SDK.
  final String defaultSdkPathOverride;

  /// Factory to create an appropriate Logger instance to give feedback to the
  /// user.  Used in testing to allow user feedback messages to be tested.
  final Logger Function(bool isVerbose) loggerFactory;

  /// Resource provider that should be used to access the filesystem.  Used in
  /// testing to redirect to an in-memory filesystem.
  final ResourceProvider resourceProvider;

  /// Logger instance we use to give feedback to the user.
  final Logger logger;

  /// The environment variables, tracked to help users debug if SDK_PATH was
  /// specified and that resulted in any [ExperimentStatusException]s.
  final Map<String, String> _environmentVariables;

  MigrationCli({
    @required this.binaryName,
    @visibleForTesting this.loggerFactory = _defaultLoggerFactory,
    @visibleForTesting this.defaultSdkPathOverride,
    @visibleForTesting ResourceProvider resourceProvider,
    @visibleForTesting Map<String, String> environmentVariables,
  })  : logger = loggerFactory(false),
        resourceProvider =
            resourceProvider ?? PhysicalResourceProvider.INSTANCE,
        _environmentVariables = environmentVariables ?? Platform.environment;

  Context get pathContext => resourceProvider.pathContext;

  /// Parses and validates command-line arguments, and creates a
  /// [MigrationCliRunner] that is prepared to perform migration.
  ///
  /// If the user asked for help, it is printed using the logger configured in
  /// the constructor, and `null` is returned.
  ///
  /// If the user supplied a bad option, a message is printed using the logger
  /// configured in the constructor, and [MigrationExit] is thrown.
  MigrationCliRunner decodeCommandLineArgs(ArgResults argResults,
      {bool isVerbose}) {
    try {
      isVerbose ??= argResults[CommandLineOptions.verboseFlag] as bool;
      if (argResults[CommandLineOptions.helpFlag] as bool) {
        _showUsage(isVerbose);
        return null;
      }
      var rest = argResults.rest;
      String migratePath;
      if (rest.isEmpty) {
        migratePath = pathContext.current;
      } else if (rest.length > 1) {
        throw _BadArgException('No more than one path may be specified.');
      } else {
        migratePath = pathContext
            .normalize(pathContext.join(pathContext.current, rest[0]));
      }
      var migrateResource = resourceProvider.getResource(migratePath);
      if (migrateResource is File) {
        if (migrateResource.exists) {
          throw _BadArgException('$migratePath is a file.');
        } else {
          throw _BadArgException('$migratePath does not exist.');
        }
      }
      var applyChanges =
          argResults[CommandLineOptions.applyChangesFlag] as bool;
      var previewPortRaw =
          argResults[CommandLineOptions.previewPortOption] as String;
      int previewPort;
      try {
        previewPort = previewPortRaw == null ? null : int.parse(previewPortRaw);
      } on FormatException catch (_) {
        throw _BadArgException(
            'Invalid value for --${CommandLineOptions.previewPortOption}');
      }
      bool webPreview;
      if (argResults.wasParsed(CommandLineOptions.webPreviewFlag)) {
        webPreview = argResults[CommandLineOptions.webPreviewFlag] as bool;
      } else {
        // If the `webPreviewFlag` wasn't explicitly passed, then the value of
        // this option is based on the value of the [applyChanges] option.
        webPreview = !applyChanges;
      }
      if (applyChanges && webPreview) {
        throw _BadArgException('--apply-changes requires --no-web-preview');
      }
      var options = CommandLineOptions(
          applyChanges: applyChanges,
          directory: migratePath,
          ignoreErrors: argResults[CommandLineOptions.ignoreErrorsFlag] as bool,
          ignoreExceptions:
              argResults[CommandLineOptions.ignoreExceptionsFlag] as bool,
          previewHostname:
              argResults[CommandLineOptions.previewHostnameOption] as String,
          previewPort: previewPort,
          sdkPath: argResults[CommandLineOptions.sdkPathOption] as String ??
              defaultSdkPathOverride ??
              getSdkPath(),
          skipImportCheck:
              argResults[CommandLineOptions.skipImportCheckFlag] as bool,
          summary: argResults[CommandLineOptions.summaryOption] as String,
          webPreview: webPreview);
      return MigrationCliRunner(this, options,
          logger: isVerbose ? loggerFactory(true) : null);
    } on Object catch (exception) {
      handleArgParsingException(exception);
    }
  }

  @alwaysThrows
  void handleArgParsingException(Object exception) {
    String message;
    if (exception is FormatException) {
      message = exception.message;
    } else if (exception is _BadArgException) {
      message = exception.message;
    } else {
      message =
          'Exception occurred while parsing command-line options: $exception';
    }
    logger.stderr(message);
    _showUsage(false);
    throw MigrationExit(1);
  }

  void _showUsage(bool isVerbose) {
    logger.stderr('Usage: $binaryName [options...] [<package directory>]');

    logger.stderr('');
    logger.stderr(createParser(hide: !isVerbose).usage);
    if (!isVerbose) {
      logger.stderr('');
      logger
          .stderr('Run "$binaryName -h -v" for verbose help output, including '
              'less commonly used options.');
    }
  }

  static ArgParser createParser({bool hide = true}) {
    var parser = ArgParser();
    parser.addFlag(CommandLineOptions.helpFlag,
        abbr: 'h',
        help:
            'Display this help message. Add --verbose to show hidden options.',
        defaultsTo: false,
        negatable: false);
    _defineOptions(parser, hide);
    return parser;
  }

  static Logger _defaultLoggerFactory(bool isVerbose) {
    var ansi = Ansi(Ansi.terminalSupportsAnsi);
    if (isVerbose) {
      return Logger.verbose(ansi: ansi);
    } else {
      return Logger.standard(ansi: ansi);
    }
  }

  static void _defineOptions(ArgParser parser, bool hide) {
    for (var option in options) {
      option.addToParser(parser, hide);
    }
  }
}

/// Data structure representing a single command-line option to the migration
/// tool, or a separator in the list of command-line options.
class MigrationCliOption {
  /// The name of the option, without the leading `--`.
  final String name;

  /// Callback function that can be used to add the option or separator to the
  /// given [parser].  If [hide] is `true`, and the option is rarely used, it
  /// is added as a hidden option.
  final void Function(ArgParser parser, bool hide) addToParser;

  /// If `true`, this is a separator between command line options; if `false`,
  /// it's an option.
  final bool isSeparator;

  MigrationCliOption(this.name, this.addToParser) : isSeparator = false;

  MigrationCliOption.separator(this.name)
      : addToParser = ((parser, hide) => parser.addSeparator(name)),
        isSeparator = true;
}

/// Internals of the command-line API for the migration tool, with additional
/// methods exposed for testing.
///
/// This class may be used directly by clients that with to run migration but
/// provide their own command-line interface.
class MigrationCliRunner {
  final MigrationCli cli;

  /// Logger instance we use to give feedback to the user.
  final Logger logger;

  /// The result of parsing command-line options.
  final CommandLineOptions options;

  final Map<String, LineInfo> lineInfo = {};

  DartFixListener _dartFixListener;

  _FixCodeProcessor _fixCodeProcessor;

  AnalysisContextCollection _contextCollection;

  bool _hasExceptions = false;

  bool _hasAnalysisErrors = false;

  MigrationCliRunner(this.cli, this.options, {Logger logger})
      : logger = logger ?? cli.logger;

  @visibleForTesting
  DriverBasedAnalysisContext get analysisContext {
    // Handle the case of more than one analysis context being found (typically,
    // the current directory and one or more sub-directories).
    if (hasMultipleAnalysisContext) {
      return contextCollection.contextFor(options.directory)
          as DriverBasedAnalysisContext;
    } else {
      return contextCollection.contexts.single as DriverBasedAnalysisContext;
    }
  }

  Ansi get ansi => logger.ansi;

  AnalysisContextCollection get contextCollection {
    _contextCollection ??= AnalysisContextCollectionImpl(
        includedPaths: [options.directory],
        resourceProvider: resourceProvider,
        sdkPath: pathContext.normalize(options.sdkPath));
    return _contextCollection;
  }

  @visibleForTesting
  bool get hasMultipleAnalysisContext {
    return contextCollection.contexts.length > 1;
  }

  @visibleForTesting
  bool get isPreviewServerRunning =>
      _fixCodeProcessor?.isPreviewServerRunnning ?? false;

  Context get pathContext => resourceProvider.pathContext;

  ResourceProvider get resourceProvider => cli.resourceProvider;

  /// Called after changes have been applied on disk.  Maybe overridden by a
  /// derived class.
  void applyHook() {}

  /// Blocks until an interrupt signal (control-C) is received.  Tests may
  /// override this method to simulate control-C.
  @visibleForTesting
  Future<void> blockUntilSignalInterrupt() {
    Stream<ProcessSignal> stream = ProcessSignal.sigint.watch();
    return stream.first;
  }

  /// Computes the internet address that should be passed to `HttpServer.bind`
  /// when starting the preview server.  May be overridden in derived classes.
  Object computeBindAddress() {
    var hostname = options.previewHostname;
    if (hostname == 'localhost') {
      return InternetAddress.loopbackIPv4;
    } else if (hostname == 'any') {
      return InternetAddress.anyIPv6;
    } else {
      return hostname;
    }
  }

  /// Computes the set of file paths that should be analyzed by the migration
  /// engine.  May be overridden by a derived class.
  ///
  /// All files to be migrated must be included in the returned set.  It is
  /// permissible for the set to contain additional files that could help the
  /// migration tool build up a more complete nullability graph (for example
  /// generated files, or usages of the code-to-be-migrated by one one of its
  /// clients).
  ///
  /// By default returns the set of all `.dart` files contained in the context.
  Set<String> computePathsToProcess(DriverBasedAnalysisContext context) =>
      context.contextRoot
          .analyzedFiles()
          .where((s) => s.endsWith('.dart'))
          .toSet();

  NonNullableFix createNonNullableFix(
      DartFixListener listener,
      ResourceProvider resourceProvider,
      LineInfo Function(String path) getLineInfo,
      Object bindAddress,
      {List<String> included = const <String>[],
      int preferredPort,
      String summaryPath,
      @required String sdkPath}) {
    return NonNullableFix(
        listener, resourceProvider, getLineInfo, bindAddress, logger,
        included: included,
        preferredPort: preferredPort,
        summaryPath: summaryPath,
        sdkPath: sdkPath);
  }

  /// Runs the full migration process.
  ///
  /// If something goes wrong, a message is printed using the logger configured
  /// in the constructor, and [MigrationExit] is thrown.
  Future<void> run() async {
    logger.stdout('Migrating ${options.directory}');
    logger.stdout('');

    logger.stdout(MigrateCommand.migrationGuideLink);
    logger.stdout('');

    if (hasMultipleAnalysisContext) {
      logger.stdout('Note: more than one project found; migrating the '
          'top-level project.');
      logger.stdout('');
    }

    DriverBasedAnalysisContext context = analysisContext;

    NonNullableFix nonNullableFix;

    logger.stdout(ansi.emphasized('Analyzing project...'));
    _fixCodeProcessor = _FixCodeProcessor(context, this);
    _dartFixListener = DartFixListener(
        DriverProviderImpl(resourceProvider, context), _exceptionReported);
    nonNullableFix = createNonNullableFix(_dartFixListener, resourceProvider,
        _fixCodeProcessor.getLineInfo, computeBindAddress(),
        included: [options.directory],
        preferredPort: options.previewPort,
        summaryPath: options.summary,
        sdkPath: options.sdkPath);
    nonNullableFix.rerunFunction = _rerunFunction;
    _fixCodeProcessor.registerCodeTask(nonNullableFix);

    try {
      var analysisResult = await _fixCodeProcessor.runFirstPhase();

      if (analysisResult.hasErrors) {
        _logErrors(analysisResult);
        if (!options.ignoreErrors) {
          throw MigrationExit(1);
        }
      } else {
        logger.stdout('No analysis issues found.');
      }
    } on ExperimentStatusException catch (e) {
      logger.stdout(e.toString());
      final sdkPathVar = cli._environmentVariables['SDK_PATH'];
      if (sdkPathVar != null) {
        logger.stdout('$sdkPathEnvironmentVariableSet: $sdkPathVar');
      }
      throw MigrationExit(1);
    }

    logger.stdout('');
    logger.stdout(ansi.emphasized('Generating migration suggestions...'));
    var previewUrls = (await _fixCodeProcessor.runLaterPhases()).previewUrls;

    if (options.applyChanges) {
      logger.stdout(ansi.emphasized('Applying changes:'));

      var allEdits = _dartFixListener.sourceChange.edits;
      _applyMigrationSuggestions(allEdits);

      logger.stdout('');
      logger.stdout(
          'Applied ${allEdits.length} ${_pluralize(allEdits.length, 'edit')}.');

      // Note: do not open the web preview if apply-changes is specified, as we
      // currently cannot tell the web preview to disable the "apply migration"
      // button.
      return;
    }

    if (options.webPreview) {
      assert(previewUrls.length == 1,
          'Got unexpected extra preview URLs from server');

      var url = previewUrls.single;
      // TODO(#41809): Open a browser automatically.
      logger.stdout('''
View the migration suggestions by visiting:

  ${ansi.emphasized(url)}

Use this interactive web view to review, improve, or apply the results.
When finished with the preview, hit ctrl-c to terminate this process.

''');

      // Block until sigint (ctrl-c).
      await blockUntilSignalInterrupt();
      nonNullableFix.shutdownServer();
    } else {
      logger.stdout(ansi.emphasized('Diff of changes:'));

      _displayChangeDiff(_dartFixListener);

      logger.stdout('');
      logger.stdout('To apply these changes, re-run the tool with '
          '--${CommandLineOptions.applyChangesFlag}.');
    }
  }

  /// Determines whether a migrated version of the file at [path] should be
  /// output by the migration too.  May be overridden by a derived class.
  ///
  /// This method should return `false` for files that are being considered by
  /// the migration tool for information only (for example generated files, or
  /// usages of the code-to-be-migrated by one one of its clients).
  ///
  /// By default returns `true` if the file is contained within the context
  /// root.  This means that if a client overrides [computePathsToProcess] to
  /// return additional paths that aren't inside the user's project, but doesn't
  /// override this method, then those additional paths will be analyzed but not
  /// migrated.
  bool shouldBeMigrated(DriverBasedAnalysisContext context, String path) {
    return context.contextRoot.isAnalyzed(path);
  }

  /// Perform the indicated source edits to the given source, returning the
  /// resulting transformed text.
  String _applyEdits(SourceFileEdit sourceFileEdit, String source) {
    List<SourceEdit> edits = _sortEdits(sourceFileEdit);
    return SourceEdit.applySequence(source, edits);
  }

  void _applyMigrationSuggestions(List<SourceFileEdit> edits) {
    // Apply the changes to disk.
    for (SourceFileEdit sourceFileEdit in edits) {
      String relPath =
          pathContext.relative(sourceFileEdit.file, from: options.directory);
      int count = sourceFileEdit.edits.length;
      logger.stdout('  $relPath ($count ${_pluralize(count, 'change')})');

      String source;
      var file = resourceProvider.getFile(sourceFileEdit.file);
      try {
        source = file.readAsStringSync();
      } catch (_) {}

      if (source == null) {
        logger.stdout('    Unable to retrieve source for file.');
      } else {
        source = _applyEdits(sourceFileEdit, source);

        try {
          file.writeAsStringSync(source);
        } catch (e) {
          logger.stdout('    Unable to write source for file: $e');
        }
      }
    }
    applyHook();
  }

  void _displayChangeDiff(DartFixListener migrationResults) {
    Map<String, List<DartFixSuggestion>> fileSuggestions = {};
    for (DartFixSuggestion suggestion in migrationResults.suggestions) {
      String file = suggestion.location.file;
      fileSuggestions.putIfAbsent(file, () => <DartFixSuggestion>[]);
      fileSuggestions[file].add(suggestion);
    }

    // present a diff-like view
    var diffStyle = DiffStyle(logger.ansi);
    for (SourceFileEdit sourceFileEdit in migrationResults.sourceChange.edits) {
      String file = sourceFileEdit.file;
      String relPath = pathContext.relative(file, from: options.directory);
      var edits = sourceFileEdit.edits;
      int count = edits.length;

      logger.stdout('');
      logger.stdout('${ansi.emphasized(relPath)} '
          '($count ${_pluralize(count, 'change')}):');

      String source;
      try {
        source = resourceProvider.getFile(file).readAsStringSync();
      } catch (_) {}

      if (source == null) {
        logger.stdout('  (unable to retrieve source for file)');
      } else {
        for (var line
            in diffStyle.formatDiff(source, _sourceEditsToAtomicEdits(edits))) {
          logger.stdout('  $line');
        }
      }
    }
  }

  void _exceptionReported(String detail) {
    if (_hasExceptions) return;
    _hasExceptions = true;
    if (options.ignoreExceptions) {
      logger.stdout('''
Exception(s) occurred during migration.  Attempting to perform
migration anyway due to the use of --${CommandLineOptions.ignoreExceptionsFlag}.

To see exception details, re-run without --${CommandLineOptions.ignoreExceptionsFlag}.
''');
    } else {
      if (_hasAnalysisErrors) {
        logger.stderr('''
Aborting migration due to an exception.  This may be due to a bug in
the migration tool, or it may be due to errors in the source code
being migrated.  If possible, try to fix errors in the source code and
re-try migrating.  If that doesn't work, consider filing a bug report
at:
''');
      } else {
        logger.stderr('''
Aborting migration due to an exception.  This most likely is due to a
bug in the migration tool.  Please consider filing a bug report at:
''');
      }
      logger.stderr('https://github.com/dart-lang/sdk/issues/new');
      logger.stderr('''
To attempt to perform migration anyway, you may re-run with
--${CommandLineOptions.ignoreExceptionsFlag}.

Exception details:
''');
      logger.stderr(detail);
      throw MigrationExit(1);
    }
  }

  void _logErrors(AnalysisResult analysisResult) {
    logger.stdout('');

    var issueCount = analysisResult.errors.length;
    logger.stdout(
        '$issueCount analysis ${_pluralize(issueCount, 'issue')} found:');

    _IssueRenderer renderer =
        _IssueRenderer(logger, options.directory, pathContext, lineInfo);
    for (AnalysisError error in analysisResult.errors) {
      renderer.render(error);
    }

    logger.stdout('');
    logger.stdout('Note: analysis errors will result in erroneous migration '
        'suggestions.');

    _hasAnalysisErrors = true;
    if (options.ignoreErrors) {
      logger.stdout('Continuing with migration suggestions due to the use of '
          '--${CommandLineOptions.ignoreErrorsFlag}.');
    } else {
      // Fail with how to continue.
      logger.stdout('');
      if (analysisResult.hasImportErrors) {
        logger
            .stdout('Unresolved URIs found.  Did you forget to run "pub get"?');
        logger.stdout('');
      }
      logger.stdout(
          'Please fix the analysis issues (or, force generation of migration '
          'suggestions by re-running with '
          '--${CommandLineOptions.ignoreErrorsFlag}).');
    }
  }

  Future<MigrationState> _rerunFunction() async {
    logger.stdout(ansi.emphasized('Re-analyzing project...'));

    _dartFixListener.reset();
    _fixCodeProcessor.prepareToRerun();
    var analysisResult = await _fixCodeProcessor.runFirstPhase();
    if (analysisResult.hasErrors) {
      _logErrors(analysisResult);
      return MigrationState(
          _fixCodeProcessor._task.migration,
          _fixCodeProcessor._task.includedRoot,
          _dartFixListener,
          _fixCodeProcessor._task.instrumentationListener,
          analysisResult);
    } else {
      logger.stdout(ansi.emphasized('Re-generating migration suggestions...'));
      return await _fixCodeProcessor.runLaterPhases();
    }
  }

  List<SourceEdit> _sortEdits(SourceFileEdit sourceFileEdit) {
    // Sort edits in reverse offset order.
    List<SourceEdit> edits = sourceFileEdit.edits.toList();
    edits.sort((a, b) {
      return b.offset - a.offset;
    });
    return edits;
  }

  static Map<int, List<AtomicEdit>> _sourceEditsToAtomicEdits(
      List<SourceEdit> edits) {
    return {
      for (var edit in edits)
        edit.offset: [AtomicEdit.replace(edit.length, edit.replacement)]
    };
  }
}

/// Exception thrown by [MigrationCli] if the client should exit.
class MigrationExit {
  /// The exit code that the client should set.
  final int exitCode;

  MigrationExit(this.exitCode);
}

/// An abstraction over the static methods on [Process].
///
/// Used in tests to run mock processes.
abstract class ProcessManager {
  const factory ProcessManager.system() = SystemProcessManager;

  /// Run a process synchronously, as in [Process.runSync].
  ProcessResult runSync(String executable, List<String> arguments,
      {String workingDirectory});
}

/// A [ProcessManager] that directs all method calls to static methods of
/// [Process], in order to run real processes.
class SystemProcessManager implements ProcessManager {
  const SystemProcessManager();

  ProcessResult runSync(String executable, List<String> arguments,
          {String workingDirectory}) =>
      Process.runSync(executable, arguments,
          workingDirectory: workingDirectory ?? Directory.current.path);
}

class _BadArgException implements Exception {
  final String message;

  _BadArgException(this.message);
}

class _FixCodeProcessor extends Object {
  static const numPhases = 3;

  final DriverBasedAnalysisContext context;

  /// The task used to migrate to NNBD.
  NonNullableFix _task;

  Set<String> pathsToProcess;

  ProgressBar _progressBar;

  final MigrationCliRunner _migrationCli;

  _FixCodeProcessor(this.context, this._migrationCli)
      : pathsToProcess = _migrationCli.computePathsToProcess(context);

  bool get isPreviewServerRunnning => _task?.isPreviewServerRunning ?? false;

  LineInfo getLineInfo(String path) =>
      context.currentSession.getFile(path).lineInfo;

  void prepareToRerun() {
    var driver = context.driver;
    pathsToProcess = _migrationCli.computePathsToProcess(context);
    pathsToProcess.forEach(driver.changeFile);
  }

  /// Call the supplied [process] function to process each compilation unit.
  Future<void> processResources(
      Future<void> Function(ResolvedUnitResult result) process) async {
    var driver = context.currentSession;
    var pathsProcessed = <String>{};
    for (var path in pathsToProcess) {
      if (pathsProcessed.contains(path)) continue;
      switch (await driver.getSourceKind(path)) {
        case SourceKind.PART:
          // Parts will either be found in a library, below, or if the library
          // isn't [isIncluded], will be picked up in the final loop.
          continue;
          break;
        case SourceKind.LIBRARY:
          var result = await driver.getResolvedLibrary(path);
          if (result != null) {
            for (var unit in result.units) {
              if (!pathsProcessed.contains(unit.path)) {
                await process(unit);
                pathsProcessed.add(unit.path);
              }
            }
          }
          break;
        default:
          break;
      }
    }

    for (var path in pathsToProcess.difference(pathsProcessed)) {
      var result = await driver.getResolvedUnit(path);
      if (result == null || result.unit == null) {
        continue;
      }
      await process(result);
    }
  }

  void registerCodeTask(NonNullableFix task) {
    _task = task;
  }

  Future<AnalysisResult> runFirstPhase() async {
    // Process package
    _task.processPackage(context.contextRoot.root);

    var analysisErrors = <AnalysisError>[];

    // All tasks should be registered; [numPhases] should be finalized.
    _progressBar = ProgressBar(_migrationCli.logger, pathsToProcess.length);

    // Process each source file.
    await processResources((ResolvedUnitResult result) async {
      _progressBar.tick();
      List<AnalysisError> errors = result.errors
          .where((error) => error.severity == Severity.error)
          .toList();
      if (errors.isNotEmpty) {
        analysisErrors.addAll(errors);
        _migrationCli.lineInfo[result.path] = result.lineInfo;
      }
      if (_migrationCli.options.ignoreErrors || analysisErrors.isEmpty) {
        await _task.prepareUnit(result);
      }
    });

    var unmigratedDependencies = _task.migration.unmigratedDependencies;
    if (unmigratedDependencies.isNotEmpty) {
      if (_migrationCli.options.skipImportCheck) {
        _migrationCli.logger.stdout(unmigratedDependenciesWarning);
      } else {
        throw ExperimentStatusException.unmigratedDependencies(
            unmigratedDependencies);
      }
    }

    return AnalysisResult(analysisErrors, _migrationCli.lineInfo,
        _migrationCli.pathContext, _migrationCli.options.directory);
  }

  Future<MigrationState> runLaterPhases() async {
    _progressBar = ProgressBar(
        _migrationCli.logger, pathsToProcess.length * (numPhases - 1));

    await processResources((ResolvedUnitResult result) async {
      _progressBar.tick();
      await _task.processUnit(result);
    });
    await processResources((ResolvedUnitResult result) async {
      _progressBar.tick();
      if (_migrationCli.shouldBeMigrated(context, result.path)) {
        await _task.finalizeUnit(result);
      }
    });
    _progressBar.complete();
    _migrationCli.logger.stdout(_migrationCli.ansi
        .emphasized('Compiling instrumentation information...'));
    var state = await _task.finish();
    if (_migrationCli.options.webPreview) {
      await _task.startPreviewServer(state, _migrationCli.applyHook);
    }
    state.previewUrls = _task.previewUrls;

    return state;
  }
}

/// Given a Logger and an analysis issue, render the issue to the logger.
class _IssueRenderer {
  final Logger logger;
  final String rootDirectory;
  final Context pathContext;
  final Map<String, LineInfo> lineInfo;

  _IssueRenderer(
      this.logger, this.rootDirectory, this.pathContext, this.lineInfo);

  void render(AnalysisError issue) {
    // severity • Message ... at foo/bar.dart:6:1 • (error_code)
    var lineInfoForThisFile = lineInfo[issue.source.fullName];
    var location = lineInfoForThisFile.getLocation(issue.offset);

    final Ansi ansi = logger.ansi;

    logger.stdout(
      '  ${ansi.error(issue.severity.name)} • '
      '${ansi.emphasized(_removePeriod(issue.message))} '
      'at ${pathContext.relative(issue.source.fullName, from: rootDirectory)}'
      ':${location.lineNumber}:${location.columnNumber} '
      '• (${issue.errorCode.name.toLowerCase()})',
    );
  }
}

extension on Severity {
  /// Returns the simple name of the Severity, as a String.
  String get name {
    switch (this) {
      case Severity.error:
        return 'error';
      case Severity.warning:
        return 'warning';
      case Severity.info:
        return 'info';
    }
    return '???';
  }
}
