// 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:async';
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/java_engine.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 {
  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 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.
   */
  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;

  /**
   * 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;

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

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

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

  /**
   * Allow the output from the server to be read and processed.
   */
  Future<void> readServerOutput() async {
    await new Future.delayed(new 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);
    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');
    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) {
    LineInfo info = fileEdit.lineInfo;
    for (DiffHunk hunk in blobDiff.hunks) {
      int srcStart = info.getOffsetOfLine(hunk.srcLine);
      int srcEnd = info.getOffsetOfLine(
          math.min(hunk.srcLine + hunk.removeLines.length, info.lineCount - 1));
      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)
      ..configureFeatures(FeatureSet.forTesting(sdkVersion: '2.2.2'));
    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;
    }

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

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

    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<void> _replayChanges() async {
    //
    // Get the revision history of the repo.
    //
    LinearCommitHistory history = repository.getCommitHistory();
    statistics.commitCount = history.commitIds.length;
    LinearCommitHistoryIterator iterator = history.iterator();
    try {
      //
      // 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();
        }
        await readServerOutput();
        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++;
          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 {
    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()) {
        statistics.editCount++;
        operation.perform(server);
        await readServerOutput();
      }
    }
  }

  /**
   * 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<void> _runSimulation() async {
    server = new Server(logger: logger);
    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 {
      // 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 = 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 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.
   */
  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;

  /**
   * 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) {
    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';
    }
    return '$seconds.$milliseconds';
  }
}
