// Copyright (c) 2015, 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.

/// A stress test for the analysis server.
import 'dart:io';
import 'dart:math' as math;

import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/ast/token.dart';
import 'package:analyzer/error/listener.dart' as error;
import 'package:analyzer/src/dart/scanner/reader.dart';
import 'package:analyzer/src/dart/scanner/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/util/glob.dart';
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:args/args.dart';
import 'package:path/path.dart' as path;

import '../utilities/git.dart';
import '../utilities/logger.dart';
import '../utilities/server.dart';
import 'operation.dart';

/// Run the simulation based on the given command-line [arguments].
Future<void> main(List<String> arguments) async {
  var driver = Driver();
  await driver.run(arguments);
}

/// The driver class that runs the simulation.
class Driver {
  /// The value of the [OVERLAY_STYLE_OPTION_NAME] indicating that modifications
  /// to a file should be represented by an add overlay, followed by zero or
  /// more change overlays, followed by a remove overlay.
  static String CHANGE_OVERLAY_STYLE = 'change';

  /// The name of the command-line flag that will print help text.
  static String HELP_FLAG_NAME = 'help';

  /// The value of the [OVERLAY_STYLE_OPTION_NAME] indicating that modifications
  /// to a file should be represented by an add overlay, followed by zero or
  /// more additional add overlays, followed by a remove overlay.
  static String MULTIPLE_ADD_OVERLAY_STYLE = 'multipleAdd';

  /// The name of the command-line option used to specify the style of
  /// interaction to use when making `analysis.updateContent` requests.
  static String OVERLAY_STYLE_OPTION_NAME = 'overlay-style';

  /// The name of the pubspec file.
  static const String PUBSPEC_FILE_NAME = 'pubspec.yaml';

  /// The name of the branch used to clean-up after making temporary changes.
  static const String TEMP_BRANCH_NAME = 'temp';

  /// The name of the command-line flag that will cause verbose output to be
  /// produced.
  static String VERBOSE_FLAG_NAME = 'verbose';

  /// The style of interaction to use for analysis.updateContent requests.
  late OverlayStyle overlayStyle;

  /// The absolute path of the repository.
  late String repositoryPath;

  /// The absolute paths to the analysis roots.
  late List<String> analysisRoots;

  /// The git repository.
  late GitRepository repository;

  /// The connection to the analysis server.
  late Server server;

  /// A list of the glob patterns used to identify the files being analyzed by
  /// the server.
  late List<Glob> fileGlobs;

  /// An object gathering statistics about the simulation.
  late Statistics statistics;

  /// A flag indicating whether verbose output should be provided.
  bool verbose = false;

  /// The logger to which verbose logging data will be written.
  late Logger logger;

  /// Initialize a newly created driver.
  Driver() {
    statistics = Statistics(this);
  }

  /// Allow the output from the server to be read and processed.
  Future<void> readServerOutput() async {
    await Future.delayed(Duration(milliseconds: 2));
  }

  /// Run the simulation based on the given command-line arguments ([args]).
  Future<void> run(List<String> args) async {
    //
    // Process the command-line arguments.
    //
    if (!_processCommandLine(args)) {
      return null;
    }
    if (verbose) {
      stdout.writeln();
      stdout.writeln('-' * 80);
      stdout.writeln();
    }
    //
    // Simulate interactions with the server.
    //
    await _runSimulation();
    //
    // Print out statistics gathered while performing the simulation.
    //
    if (verbose) {
      stdout.writeln();
      stdout.writeln('-' * 80);
    }
    stdout.writeln();
    statistics.print();
    if (verbose) {
      stdout.writeln();
      server.printStatistics();
    }
    exit(0);
  }

  /// Create and return a parser that can be used to parse the command-line
  /// arguments.
  ArgParser _createArgParser() {
    var parser = ArgParser();
    parser.addFlag(HELP_FLAG_NAME,
        abbr: 'h',
        help: 'Print usage information',
        defaultsTo: false,
        negatable: false);
    parser.addOption(OVERLAY_STYLE_OPTION_NAME,
        help:
            'The style of interaction to use for analysis.updateContent requests',
        allowed: [CHANGE_OVERLAY_STYLE, MULTIPLE_ADD_OVERLAY_STYLE],
        allowedHelp: {
          CHANGE_OVERLAY_STYLE: '<add> <change>* <remove>',
          MULTIPLE_ADD_OVERLAY_STYLE: '<add>+ <remove>'
        },
        defaultsTo: 'change');
    parser.addFlag(VERBOSE_FLAG_NAME,
        abbr: 'v',
        help: 'Produce verbose output for debugging',
        defaultsTo: false,
        negatable: false);
    return parser;
  }

  /// Add source edits to the given [fileEdit] based on the given [blobDiff].
  void _createSourceEdits(FileEdit fileEdit, BlobDiff blobDiff) {
    var info = fileEdit.lineInfo;
    for (var hunk in blobDiff.hunks) {
      var srcStart = info.getOffsetOfLine(hunk.srcLine);
      var srcEnd = info.getOffsetOfLine(
          math.min(hunk.srcLine + hunk.removeLines.length, info.lineCount - 1));
      var addedText = _join(hunk.addLines);
      //
      // Create the source edits.
      //
      var breakOffsets = _getBreakOffsets(addedText);
      var breakCount = breakOffsets.length;
      var sourceEdits = <SourceEdit>[];
      if (breakCount == 0) {
        sourceEdits.add(SourceEdit(srcStart, srcEnd - srcStart + 1, addedText));
      } else {
        var previousOffset = breakOffsets[0];
        var string = addedText.substring(0, previousOffset);
        sourceEdits.add(SourceEdit(srcStart, srcEnd - srcStart + 1, string));
        var reconstruction = string;
        for (var i = 1; i < breakCount; i++) {
          var offset = breakOffsets[i];
          string = addedText.substring(previousOffset, offset);
          reconstruction += string;
          sourceEdits.add(SourceEdit(srcStart + previousOffset, 0, string));
          previousOffset = offset;
        }
        string = addedText.substring(previousOffset);
        reconstruction += string;
        sourceEdits.add(SourceEdit(srcStart + previousOffset, 0, string));
        if (reconstruction != addedText) {
          throw AssertionError();
        }
      }
      fileEdit.addSourceEdits(sourceEdits);
    }
  }

  /// Return the absolute paths of all of the pubspec files in all of the
  /// analysis roots.
  Iterable<String> _findPubspecsInAnalysisRoots() {
    var pubspecFiles = <String>[];
    for (var directoryPath in analysisRoots) {
      var directory = Directory(directoryPath);
      var children = directory.listSync(recursive: true, followLinks: false);
      for (var child in children) {
        var filePath = child.path;
        if (path.basename(filePath) == PUBSPEC_FILE_NAME) {
          pubspecFiles.add(filePath);
        }
      }
    }
    return pubspecFiles;
  }

  /// Return a list of offsets into the given [text] that represent good places
  /// to break the text when building edits.
  List<int> _getBreakOffsets(String text) {
    var breakOffsets = <int>[];
    var featureSet = FeatureSet.latestLanguageVersion();
    var scanner = Scanner(_TestSource(), CharSequenceReader(text),
        error.AnalysisErrorListener.NULL_LISTENER)
      ..configureFeatures(
        featureSetForOverriding: featureSet,
        featureSet: featureSet,
      );
    var token = scanner.tokenize();
    // TODO(brianwilkerson) Randomize. Sometimes add zero (0) as a break point.
    while (token.type != TokenType.EOF) {
      // TODO(brianwilkerson) Break inside comments?
//      Token comment = token.precedingComments;
      var offset = token.offset;
      var length = token.length;
      breakOffsets.add(offset);
      if (token.type == TokenType.IDENTIFIER && length > 3) {
        breakOffsets.add(offset + (length ~/ 2));
      }
      token = token.next!;
    }
    return breakOffsets;
  }

  /// Join the given [lines] into a single string.
  String _join(List<String> lines) {
    var buffer = StringBuffer();
    for (var i = 0; i < lines.length; i++) {
      buffer.writeln(lines[i]);
    }
    return buffer.toString();
  }

  /// Process the command-line [arguments]. Return `true` if the simulation
  /// should be run.
  bool _processCommandLine(List<String> args) {
    var parser = _createArgParser();
    ArgResults results;
    try {
      results = parser.parse(args);
    } catch (exception) {
      _showUsage(parser);
      return false;
    }

    if (results[HELP_FLAG_NAME] as bool) {
      _showUsage(parser);
      return false;
    }

    var overlayStyleValue = results[OVERLAY_STYLE_OPTION_NAME] as String;
    if (overlayStyleValue == CHANGE_OVERLAY_STYLE) {
      overlayStyle = OverlayStyle.change;
    } else if (overlayStyleValue == MULTIPLE_ADD_OVERLAY_STYLE) {
      overlayStyle = OverlayStyle.multipleAdd;
    }

    if (results[VERBOSE_FLAG_NAME] as bool) {
      verbose = true;
      logger = Logger(stdout);
    }

    var arguments = results.rest;
    if (arguments.length < 2) {
      _showUsage(parser);
      return false;
    }
    repositoryPath = path.normalize(arguments[0]);
    repository = GitRepository(repositoryPath, logger: logger);

    analysisRoots = arguments
        .sublist(1)
        .map((String analysisRoot) => path.normalize(analysisRoot))
        .toList();
    for (var analysisRoot in analysisRoots) {
      if (repositoryPath != analysisRoot &&
          !path.isWithin(repositoryPath, analysisRoot)) {
        _showUsage(parser,
            'Analysis roots must be contained within the repository: $analysisRoot');
        return false;
      }
    }
    return true;
  }

  /// Replay the changes in each commit.
  Future<void> _replayChanges() async {
    //
    // Get the revision history of the repo.
    //
    var history = repository.getCommitHistory();
    statistics.commitCount = history.commitIds.length;
    var iterator = history.iterator();
    try {
      //
      // Iterate over the history, applying changes.
      //
      var firstCheckout = true;
      ErrorMap? expectedErrors;
      late Iterable<String> changedPubspecs;
      while (iterator.moveNext()) {
        //
        // Checkout the commit on which the changes are based.
        //
        var commit = iterator.srcCommit;
        repository.checkout(commit);
        if (expectedErrors != null) {
//          ErrorMap actualErrors =
          await server.computeErrorMap(server.analyzedDartFiles);
//          String difference = expectedErrors.expectErrorMap(actualErrors);
//          if (difference != null) {
//            stdout.write('Mismatched errors after commit ');
//            stdout.writeln(commit);
//            stdout.writeln();
//            stdout.writeln(difference);
//            return;
//          }
        }
        if (firstCheckout) {
          changedPubspecs = _findPubspecsInAnalysisRoots();
          server.sendAnalysisSetAnalysisRoots(analysisRoots, []);
          firstCheckout = false;
        } else {
          server.removeAllOverlays();
        }
        await readServerOutput();
        expectedErrors = await server.computeErrorMap(server.analyzedDartFiles);
        for (var filePath in changedPubspecs) {
          _runPub(filePath);
        }
        //
        // Apply the changes.
        //
        var commitDelta = iterator.next();
        commitDelta.filterDiffs(analysisRoots, fileGlobs);
        if (commitDelta.hasDiffs) {
          statistics.commitsWithChangeInRootCount++;
          await _replayDiff(commitDelta);
        }
        changedPubspecs = commitDelta.filesMatching(PUBSPEC_FILE_NAME);
      }
    } finally {
      // Ensure that the repository is left at the most recent commit.
      if (history.commitIds.isNotEmpty) {
        repository.checkout(history.commitIds[0]);
      }
    }
    server.removeAllOverlays();
    await readServerOutput();
    stdout.writeln();
  }

  /// Replay the changes between two commits, as represented by the given
  /// [commitDelta].
  Future<void> _replayDiff(CommitDelta commitDelta) async {
    var editList = <FileEdit>[];
    for (var record in commitDelta.diffRecords) {
      var edit = FileEdit(overlayStyle, record);
      _createSourceEdits(edit, record.getBlobDiff());
      editList.add(edit);
    }
    //
    // TODO(brianwilkerson) Randomize.
    // Randomly select operations from different files to simulate a user
    // editing multiple files simultaneously.
    //
    for (var edit in editList) {
      var currentFile = <String>[edit.filePath];
      server.sendAnalysisSetPriorityFiles(currentFile);
      server.sendAnalysisSetSubscriptions({
        AnalysisService.FOLDING: currentFile,
        AnalysisService.HIGHLIGHTS: currentFile,
        AnalysisService.IMPLEMENTED: currentFile,
        AnalysisService.NAVIGATION: currentFile,
        AnalysisService.OCCURRENCES: currentFile,
        AnalysisService.OUTLINE: currentFile,
        AnalysisService.OVERRIDES: currentFile
      });
      for (var operation in edit.getOperations()) {
        statistics.editCount++;
        operation.perform(server);
        await readServerOutput();
      }
    }
  }

  /// Run `pub` on the pubspec with the given [filePath].
  void _runPub(String filePath) {
    var directoryPath = path.dirname(filePath);
    if (Directory(directoryPath).existsSync()) {
      Process.runSync(
          '/Users/brianwilkerson/Dev/dart/dart-sdk/bin/pub', ['get'],
          workingDirectory: directoryPath);
    }
  }

  /// Run the simulation by starting up a server and sending it requests.
  Future<void> _runSimulation() async {
    server = Server(logger: logger);
    var stopwatch = statistics.stopwatch;
    stopwatch.start();
    await server.start();
    server.sendServerSetSubscriptions([ServerService.STATUS]);
    server.sendAnalysisSetGeneralSubscriptions(
        [GeneralAnalysisService.ANALYZED_FILES]);
    // TODO(brianwilkerson) Get the list of glob patterns from the server after
    // an API for getting them has been implemented.
    fileGlobs = <Glob>[
      Glob(path.context.separator, '**.dart'),
      Glob(path.context.separator, '**.html'),
      Glob(path.context.separator, '**.htm'),
      Glob(path.context.separator, '**/.analysisOptions')
    ];
    try {
      await _replayChanges();
    } finally {
      // TODO(brianwilkerson) This needs to be moved into a Zone in order to
      // ensure that it is always run.
      server.sendServerShutdown();
      repository.checkout('master');
    }
    stopwatch.stop();
  }

  /// Display usage information, preceded by the [errorMessage] if one is given.
  void _showUsage(ArgParser parser, [String? errorMessage]) {
    if (errorMessage != null) {
      stderr.writeln(errorMessage);
      stderr.writeln();
    }
    stderr.writeln('''
Usage: replay [options...] repositoryPath analysisRoot...

Uses the commit history of the git repository at the given repository path to
simulate the development of a code base while using the analysis server to
analyze the code base.

The repository path must be the absolute path of a directory containing a git
repository.

There must be at least one analysis root, and all of the analysis roots must be
the absolute path of a directory contained within the repository directory. The
analysis roots represent the portions of the repository that will be analyzed by
the analysis server.

OPTIONS:''');
    stderr.writeln(parser.usage);
  }
}

/// A representation of the edits to be applied to a single file.
class FileEdit {
  /// The style of interaction to use for analysis.updateContent requests.
  OverlayStyle overlayStyle;

  /// The absolute path of the file to be edited.
  late String filePath;

  /// The content of the file before any edits have been applied.
  late String content;

  /// The line info for the file before any edits have been applied.
  late LineInfo lineInfo;

  /// The lists of source edits, one list for each hunk being edited.
  List<List<SourceEdit>> editLists = <List<SourceEdit>>[];

  /// The current content of the file. This field is only used if the overlay
  /// style is [OverlayStyle.multipleAdd].
  late String currentContent;

  /// Initialize a collection of edits to be associated with the file at the
  /// given [filePath].
  FileEdit(this.overlayStyle, DiffRecord record) {
    filePath = record.srcPath!;
    if (record.isAddition) {
      content = '';
      lineInfo = LineInfo(<int>[0]);
    } else if (record.isCopy || record.isRename || record.isTypeChange) {
      throw ArgumentError('Unhandled change of type ${record.status}');
    } else {
      content = File(filePath).readAsStringSync();
      lineInfo = LineInfo.fromContent(content);
    }
    currentContent = content;
  }

  /// Add a list of source edits that, taken together, transform a single hunk
  /// in the file.
  void addSourceEdits(List<SourceEdit> sourceEdits) {
    editLists.add(sourceEdits);
  }

  /// Return a list of operations to be sent to the server.
  List<ServerOperation> getOperations() {
    var operations = <ServerOperation>[];
    void addUpdateContent(Object overlay) {
      operations.add(Analysis_UpdateContent(filePath, overlay));
    }

    // TODO(brianwilkerson) Randomize.
    // Make the order of edits random. Doing so will require updating the
    // offsets of edits after the selected edit point.
    addUpdateContent(AddContentOverlay(content));
    for (var editList in editLists.reversed) {
      for (var edit in editList.reversed) {
        Object overlay;
        if (overlayStyle == OverlayStyle.change) {
          overlay = ChangeContentOverlay([edit]);
        } else if (overlayStyle == OverlayStyle.multipleAdd) {
          currentContent = edit.apply(currentContent);
          overlay = AddContentOverlay(currentContent);
        } else {
          throw StateError('Failed to handle overlay style = $overlayStyle');
        }
        addUpdateContent(overlay);
      }
    }
    addUpdateContent(RemoveContentOverlay());
    return operations;
  }
}

/// The possible styles of interaction to use for analysis.updateContent
/// requests.
enum OverlayStyle { change, multipleAdd }

/// A set of statistics related to the execution of the simulation.
class Statistics {
  /// The driver driving the simulation.
  final Driver driver;

  /// The stopwatch being used to time the simulation.
  Stopwatch stopwatch = Stopwatch();

  /// The total number of commits in the repository.
  int commitCount = 0;

  /// The number of commits in the repository that touched one of the files in
  /// one of the analysis roots.
  int commitsWithChangeInRootCount = 0;

  /// The total number of edits that were applied.
  int editCount = 0;

  /// Initialize a newly created set of statistics.
  Statistics(this.driver);

  /// Print the statistics to [stdout].
  void print() {
    stdout.write('Replay commits in ');
    stdout.writeln(driver.repositoryPath);
    stdout.write('  replay took ');
    stdout.writeln(_printTime(stopwatch.elapsedMilliseconds));
    stdout.write('  analysis roots = ');
    stdout.writeln(driver.analysisRoots);
    stdout.write('  number of commits = ');
    stdout.writeln(commitCount);
    stdout.write('  number of commits with a change in an analysis root = ');
    stdout.writeln(commitsWithChangeInRootCount);
    stdout.write('  number of edits = ');
    stdout.writeln(editCount);
  }

  /// Return a textual representation of the given duration, represented in
  /// [milliseconds].
  String _printTime(int milliseconds) {
    var seconds = milliseconds ~/ 1000;
    milliseconds -= seconds * 1000;
    var minutes = seconds ~/ 60;
    seconds -= minutes * 60;
    var hours = minutes ~/ 60;
    minutes -= hours * 60;

    if (hours > 0) {
      return '$hours:$minutes:$seconds.$milliseconds';
    } else if (minutes > 0) {
      return '$minutes:$seconds.$milliseconds';
    }
    return '$seconds.$milliseconds';
  }
}

class _TestSource implements Source {
  @override
  String get fullName => '/package/lib/test.dart';

  @override
  dynamic noSuchMethod(Invocation invocation) => super.noSuchMethod(invocation);
}
