// 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' as io;

import 'package:analysis_server_client/protocol.dart' hide AnalysisError;
import 'package:cli_util/cli_logging.dart' show Progress;
import 'package:path/path.dart' as path;

import '../analysis_server.dart';
import '../core.dart';
import '../sdk.dart';
import '../utils.dart';

class FixCommand extends DartdevCommand {
  static const String cmdName = 'fix';

  static const String cmdDescription =
      '''Apply automated fixes to Dart source code.

This tool looks for and fixes analysis issues that have associated automated fixes.

To use the tool, run either ['dart fix --dry-run'] for a preview of the proposed changes for a project, or ['dart fix --apply'] to apply the changes.''';

  /// The maximum number of times that fixes will be requested from the server.
  static const maxPasses = 4;

  /// A map from the absolute path of a file to the updated content of the file.
  final Map<String, String> fileContentCache = {};

  FixCommand({bool verbose = false}) : super(cmdName, cmdDescription, verbose) {
    argParser.addFlag('dry-run',
        abbr: 'n',
        defaultsTo: false,
        negatable: false,
        help: 'Preview the proposed changes but make no changes.');
    argParser.addFlag(
      'apply',
      defaultsTo: false,
      negatable: false,
      help: 'Apply the proposed changes.',
    );
    argParser.addFlag(
      'compare-to-golden',
      defaultsTo: false,
      negatable: false,
      help:
          'Compare the result of applying fixes to a golden file for testing.',
      hide: !verbose,
    );
  }

  @override
  String get description {
    if (log.ansi.useAnsi) {
      return cmdDescription
          .replaceAll('[', log.ansi.bold)
          .replaceAll(']', log.ansi.none);
    } else {
      return cmdDescription.replaceAll('[', '').replaceAll(']', '');
    }
  }

  @override
  Future<int> run() async {
    final args = argResults!;
    var dryRun = args['dry-run'];
    var inTestMode = args['compare-to-golden'];
    var apply = args['apply'];
    if (!apply && !dryRun && !inTestMode) {
      printUsage();
      return 0;
    }

    var target = _getTarget(args.rest);
    if (!target.existsSync()) {
      var entity = target.isDirectory ? 'Directory' : 'File';
      usageException("$entity doesn't exist: ${target.path}");
    }

    if (inTestMode && !target.isDirectory) {
      usageException('Golden comparison requires a directory argument.');
    }

    var fixPath = target.path;

    var modeText = dryRun ? ' (dry run)' : '';

    final targetName = path.basename(fixPath);
    Progress? computeFixesProgress = log.progress(
        'Computing fixes in ${log.ansi.emphasized(targetName)}$modeText');

    var server = AnalysisServer(
      null,
      io.Directory(sdk.sdkPath),
      [target],
      commandName: 'fix',
      argResults: argResults,
    );

    await server.start(setAnalysisRoots: false);

    server.onExit.then((int exitCode) {
      if (computeFixesProgress != null && exitCode != 0) {
        computeFixesProgress?.cancel();
        computeFixesProgress = null;
        io.exitCode = exitCode;
      }
    });

    server.onCrash.then((_) {
      log.stderr('The analysis server shut down unexpectedly.');
      log.stdout('Please report this at dartbug.com.');
      io.exit(1);
    });

    Future<Map<String, BulkFix>> applyAllEdits() async {
      var detailsMap = <String, BulkFix>{};
      List<SourceFileEdit> edits;
      var pass = 0;
      do {
        var fixes = await server.requestBulkFixes(fixPath, inTestMode);
        _mergeDetails(detailsMap, fixes.details);
        edits = fixes.edits;
        _applyEdits(server, edits);
        pass++;
        // TODO(brianwilkerson) Be more intelligent about detecting infinite
        //  loops so that we can increase [maxPasses].
      } while (pass < maxPasses && edits.isNotEmpty);
      return detailsMap;
    }

    var detailsMap = await applyAllEdits();
    await server.shutdown();

    if (computeFixesProgress != null) {
      computeFixesProgress!.finish(showTiming: true);
      computeFixesProgress = null;
    }

    var dir = target.isDirectory ? target as io.Directory : target.parent;
    if (inTestMode) {
      var result = _compareFixesInDirectory(dir);
      log.stdout('Passed: ${result.passCount}, Failed: ${result.failCount}');
      return result.failCount > 0 ? 1 : 0;
    } else if (detailsMap.isEmpty) {
      log.stdout('Nothing to fix!');
    } else {
      var fileCount = detailsMap.length;
      var fixCount = detailsMap.values
          .expand((detail) => detail.fixes)
          .fold<int>(0,
              (int previousValue, fixes) => previousValue + fixes.occurrences);

      if (dryRun) {
        log.stdout('');
        log.stdout('$fixCount proposed ${_pluralFix(fixCount)} '
            'in $fileCount ${pluralize("file", fileCount)}.');
        _printDetails(detailsMap, dir);
      } else {
        var applyFixesProgress = log.progress('Applying fixes');
        _writeFiles();
        applyFixesProgress.finish(showTiming: true);
        _printDetails(detailsMap, dir);
        log.stdout('$fixCount ${_pluralFix(fixCount)} made in '
            '$fileCount ${pluralize("file", fileCount)}.');
      }
    }

    return 0;
  }

  void _applyEdits(AnalysisServer server, List<SourceFileEdit> edits) {
    var overlays = <String, AddContentOverlay>{};
    for (var edit in edits) {
      var filePath = edit.file;
      var content = fileContentCache.putIfAbsent(filePath, () {
        var file = io.File(filePath);
        return file.existsSync() ? file.readAsStringSync() : '';
      });
      var newContent = SourceEdit.applySequence(content, edit.edits);
      fileContentCache[filePath] = newContent;
      overlays[filePath] = AddContentOverlay(newContent);
    }
    server.updateContent(overlays);
  }

  /// Return `true` if any of the fixes fail to create the same content as is
  /// found in the golden file.
  _TestResult _compareFixesInDirectory(io.Directory directory) {
    var result = _TestResult();
    //
    // Gather the files of interest in this directory and process
    // subdirectories.
    //
    var dartFiles = <io.File>[];
    var expectFileMap = <String, io.File>{};
    for (var child in directory.listSync()) {
      if (child is io.Directory) {
        var childResult = _compareFixesInDirectory(child);
        result.passCount += childResult.passCount;
        result.failCount += childResult.failCount;
      } else if (child is io.File) {
        var name = child.name;
        if (name.endsWith('.dart')) {
          dartFiles.add(child);
        } else if (name.endsWith('.expect')) {
          expectFileMap[child.path] = child;
        }
      }
    }
    for (var originalFile in dartFiles) {
      var filePath = originalFile.path;
      var baseName = path.basename(filePath);
      var expectFileName = '$baseName.expect';
      var expectFilePath = path.join(path.dirname(filePath), expectFileName);
      var expectFile = expectFileMap.remove(expectFilePath);
      if (expectFile == null) {
        result.failCount++;
        log.stdout(
            'No corresponding expect file for the Dart file at "$filePath".');
        continue;
      }
      try {
        var expectedCode = expectFile.readAsStringSync();
        var actualIsOriginal = !fileContentCache.containsKey(filePath);
        var actualCode = actualIsOriginal
            ? originalFile.readAsStringSync()
            : fileContentCache[filePath]!;
        // Use a whitespace insensitive comparison.
        if (_compressWhitespace(actualCode) !=
            _compressWhitespace(expectedCode)) {
          result.failCount++;
          // TODO(brianwilkerson) Do a better job of displaying the differences.
          //  It's very hard to see the diff with large files.
          _reportFailure(
            filePath,
            actualCode,
            expectedCode,
            actualIsOriginal: actualIsOriginal,
          );
        } else {
          result.passCount++;
        }
      } on io.FileSystemException {
        result.failCount++;
        log.stdout('Failed to process "$filePath".');
        log.stdout(
            '  Ensure that the file and its expect file are both readable.');
      }
    }
    //
    // Report any `.expect` files that have no corresponding `.dart` file.
    //
    for (var unmatchedExpectPath in expectFileMap.keys) {
      result.failCount++;
      log.stdout(
          'No corresponding Dart file for the expect file at "$unmatchedExpectPath".');
    }
    return result;
  }

  /// Compress sequences of whitespace characters into a single space.
  String _compressWhitespace(String code) =>
      code.replaceAll(RegExp(r'\s+'), ' ');

  io.FileSystemEntity _getTarget(List<String> arguments) {
    var argumentCount = arguments.length;
    if (argumentCount > 1) {
      usageException('Only one file or directory is expected.');
    }

    var basePath =
        argumentCount == 0 ? io.Directory.current.absolute.path : arguments[0];
    var normalizedPath = path.canonicalize(path.normalize(basePath));
    return io.FileSystemEntity.isDirectorySync(normalizedPath)
        ? io.Directory(normalizedPath)
        : io.File(normalizedPath);
  }

  /// Merge the fixes from the current round's [details] into the [detailsMap].
  void _mergeDetails(Map<String, BulkFix> detailsMap, List<BulkFix> details) {
    for (var detail in details) {
      var previousDetail = detailsMap[detail.path];
      if (previousDetail != null) {
        _mergeFixCounts(previousDetail.fixes, detail.fixes);
      } else {
        detailsMap[detail.path] = detail;
      }
    }
  }

  void _mergeFixCounts(
      List<BulkFixDetail> oldFixes, List<BulkFixDetail> newFixes) {
    var originalOldLength = oldFixes.length;
    newFixLoop:
    for (var newFix in newFixes) {
      var newCode = newFix.code;
      // Iterate over the original content of the list, not any of the newly
      // added fixes, because the newly added fixes can't be a match.
      for (var i = 0; i < originalOldLength; i++) {
        var oldFix = oldFixes[i];
        if (oldFix.code == newCode) {
          oldFix.occurrences += newFix.occurrences;
          continue newFixLoop;
        }
      }
      oldFixes.add(newFix);
    }
  }

  String _pluralFix(int count) => count == 1 ? 'fix' : 'fixes';

  void _printDetails(Map<String, BulkFix> detailsMap, io.Directory workingDir) {
    String relative(String absolutePath) {
      return path.relative(absolutePath, from: workingDir.path);
    }

    log.stdout('');

    final bullet = log.ansi.bullet;

    var modifiedFilePaths = detailsMap.keys.toList();
    modifiedFilePaths
        .sort((first, second) => relative(first).compareTo(relative(second)));
    for (var filePath in modifiedFilePaths) {
      var detail = detailsMap[filePath]!;
      log.stdout(relative(detail.path));
      final fixes = detail.fixes.toList();
      fixes.sort((a, b) => a.code.compareTo(b.code));
      for (var fix in fixes) {
        log.stdout('  ${fix.code} $bullet '
            '${fix.occurrences} ${_pluralFix(fix.occurrences)}');
      }
      log.stdout('');
    }
  }

  /// Report that the [actualCode] produced by applying fixes to the content of
  /// [filePath] did not match the [expectedCode].
  void _reportFailure(String filePath, String actualCode, String expectedCode,
      {required bool actualIsOriginal}) {
    log.stdout('Failed when applying fixes to $filePath');
    log.stdout('Expected:');
    log.stdout(expectedCode);
    log.stdout('');
    if (actualIsOriginal) {
      log.stdout('Actual (original code was unchanged):');
    } else {
      log.stdout('Actual:');
    }
    log.stdout(actualCode);
  }

  /// Write the modified contents of files in the [fileContentCache] to disk.
  void _writeFiles() {
    for (var entry in fileContentCache.entries) {
      var file = io.File(entry.key);
      file.writeAsStringSync(entry.value);
    }
  }
}

/// The result of running tests in a given directory.
class _TestResult {
  /// The number of tests that passed.
  int passCount = 0;

  /// The number of tests that failed.
  int failCount = 0;

  /// Initialize a newly created result object.
  _TestResult();
}

extension on io.FileSystemEntity {
  bool get isDirectory => this is io.Directory;
}
