// 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.
 */
library analysis_server.test.stress.replay.replay;

import 'dart:async';
import 'dart:io';

import 'package:analysis_server/plugin/protocol/protocol.dart';
import 'package:analyzer/src/generated/error.dart' as error;
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/scanner.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/util/glob.dart';
import 'package:args/args.dart';
import 'package:path/path.dart' as path;

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

/**
 * Run the simulation based on the given command-line [arguments].
 */
Future main(List<String> arguments) async {
  Driver driver = new 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 style of interaction to use for analysis.updateContent requests.
   */
  OverlayStyle overlayStyle;

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

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

  /**
   * The git repository.
   */
  GitRepository repository;

  /**
   * The connection to the analysis server.
   */
  Server server = new Server();

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

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

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

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

  /**
   * Create and return a parser that can be used to parse the command-line
   * arguments.
   */
  ArgParser _createArgParser() {
    ArgParser parser = new 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');
    return parser;
  }

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

  /**
   * Return the absolute paths of all of the pubspec files in all of the
   * analysis roots.
   */
  Iterable<String> _findPubspecsInAnalysisRoots() {
    List<String> pubspecFiles = <String>[];
    for (String directoryPath in analysisRoots) {
      Directory directory = new Directory(directoryPath);
      List<FileSystemEntity> children =
          directory.listSync(recursive: true, followLinks: false);
      for (FileSystemEntity child in children) {
        String 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) {
    List<int> breakOffsets = <int>[];
    Scanner scanner = new Scanner(null, new CharSequenceReader(text),
        error.AnalysisErrorListener.NULL_LISTENER);
    Token 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;
      int offset = token.offset;
      int 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) {
    StringBuffer buffer = new StringBuffer();
    for (int 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) {
    ArgParser parser = _createArgParser();
    ArgResults results;
    try {
      results = parser.parse(args);
    } catch (exception) {
      _showUsage(parser);
      return false;
    }

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

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

    List<String> arguments = results.arguments;
    if (arguments.length < 2) {
      _showUsage(parser);
      return false;
    }
    repositoryPath = path.normalize(arguments[0]);
    repository = new GitRepository(repositoryPath);

    analysisRoots = arguments
        .sublist(1)
        .map((String analysisRoot) => path.normalize(analysisRoot))
        .toList();
    for (String 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 _replayChanges() async {
    //
    // Get the revision history of the repo.
    //
    LinearCommitHistory history = repository.getCommitHistory();
    statistics.commitCount = history.commitIds.length;
    LinearCommitHistoryIterator iterator = history.iterator();
    //
    // Iterate over the history, applying changes.
    //
    bool firstCheckout = true;
    ErrorMap expectedErrors = null;
    Iterable<String> changedPubspecs;
    while (iterator.moveNext()) {
      //
      // Checkout the commit on which the changes are based.
      //
      String 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();
      }
      expectedErrors = await server.computeErrorMap(server.analyzedDartFiles);
      for (String filePath in changedPubspecs) {
        _runPub(filePath);
      }
      //
      // Apply the changes.
      //
      CommitDelta commitDelta = iterator.next();
      commitDelta.filterDiffs(analysisRoots, fileGlobs);
      if (commitDelta.hasDiffs) {
        statistics.commitsWithChangeInRootCount++;
        _replayDiff(commitDelta);
      }
      changedPubspecs = commitDelta.filesMatching(PUBSPEC_FILE_NAME);
      stdout.write('.');
    }
    server.removeAllOverlays();
    stdout.writeln();
  }

  /**
   * Replay the changes between two commits, as represented by the given
   * [commitDelta].
   */
  void _replayDiff(CommitDelta commitDelta) {
    List<FileEdit> editList = <FileEdit>[];
    for (DiffRecord record in commitDelta.diffRecords) {
      FileEdit edit = new 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 (FileEdit edit in editList) {
      List<String> 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 (ServerOperation operation in edit.getOperations()) {
        operation.perform(server);
      }
    }
  }

  /**
   * Run `pub` on the pubspec with the given [filePath].
   */
  void _runPub(String filePath) {
    String directoryPath = path.dirname(filePath);
    if (new 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 _runSimulation() async {
    Stopwatch stopwatch = new Stopwatch();
    statistics.stopwatch = 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>[
      new Glob(path.context.separator, '**.dart'),
      new Glob(path.context.separator, '**.html'),
      new Glob(path.context.separator, '**.htm'),
      new Glob(path.context.separator, '**/.analysisOptions')
    ];
    try {
      await _replayChanges();
    } finally {
      server.sendServerShutdown();
      repository.checkout('master');
    }
    stopwatch.stop();
  }

  /**
   * Display usage information, preceeded by the [errorMessage] if one is given.
   */
  void _showUsage(ArgParser parser, [String errorMessage = null]) {
    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 portion 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.
   */
  String filePath;

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

  /**
   * The line info for the file before any edits have been applied.
   */
  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].
   */
  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 = new LineInfo(<int>[0]);
    } else if (record.isCopy || record.isRename || record.isTypeChange) {
      throw new ArgumentError('Unhandled change of type ${record.status}');
    } else {
      content = new File(filePath).readAsStringSync();
      lineInfo = new LineInfo(StringUtilities.computeLineStarts(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() {
    List<ServerOperation> operations = <ServerOperation>[];
    void addUpdateContent(var overlay) {
      operations.add(new 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(new AddContentOverlay(content));
    for (List<SourceEdit> editList in editLists.reversed) {
      for (SourceEdit edit in editList.reversed) {
        var overlay = null;
        if (overlayStyle == OverlayStyle.change) {
          overlay = new ChangeContentOverlay([edit]);
        } else if (overlayStyle == OverlayStyle.multipleAdd) {
          currentContent = edit.apply(currentContent);
          overlay = new AddContentOverlay(currentContent);
        } else {
          throw new StateError(
              'Failed to handle overlay style = $overlayStyle');
        }
        if (overlay != null) {
          addUpdateContent(overlay);
        }
      }
    }
    addUpdateContent(new 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;

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

  /**
   * The number of commits in the repository that touched one of the files in
   * one of the analysis roots.
   */
  int commitsWithChangeInRootCount = 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);
  }

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

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