// 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.

/// Support for interacting with a git repository.
import 'dart:convert';
import 'dart:io';

import 'package:analyzer/src/util/glob.dart';
import 'package:path/path.dart' as path;

import 'logger.dart';

/// A representation of the differences between two blobs.
class BlobDiff {
  /// The regular expression used to identify the beginning of a hunk.
  static final RegExp hunkHeaderRegExp =
      RegExp(r'@@ -([0-9]+)(?:,[0-9]+)? \+([0-9]+)(?:,[0-9]+)? @@');

  /// A list of the hunks in the diff.
  List<DiffHunk> hunks = <DiffHunk>[];

  /// Initialize a newly created blob diff by parsing the result of the git diff
  /// command (the [input]).
  ///
  /// This is only intended to be invoked from [GitRepository.getBlobDiff].
  BlobDiff._(List<String> input) {
    _parseInput(input);
  }

  /// Parse the result of the git diff command (the [input]).
  void _parseInput(List<String> input) {
    for (var line in input) {
      _parseLine(line);
    }
  }

  /// Parse a single [line] from the result of the git diff command.
  void _parseLine(String line) {
    var currentHunk = hunks.isEmpty ? null : hunks.last;
    if (line.startsWith('@@')) {
      var match = hunkHeaderRegExp.matchAsPrefix(line);
      var srcLine = int.parse(match.group(1));
      var dstLine = int.parse(match.group(2));
      hunks.add(DiffHunk(srcLine, dstLine));
    } else if (currentHunk != null && line.startsWith('+')) {
      currentHunk.addLines.add(line.substring(1));
    } else if (currentHunk != null && line.startsWith('-')) {
      currentHunk.removeLines.add(line.substring(1));
    }
  }
}

/// A representation of the differences between two commits.
class CommitDelta {
  /// The length (in characters) of a SHA.
  static final int SHA_LENGTH = 40;

  /// The code-point for a colon (':').
  static final int COLON = ':'.codeUnitAt(0);

  /// The code-point for a nul character.
  static final int NUL = 0;

  /// The code-point for a tab.
  static final int TAB = '\t'.codeUnitAt(0);

  /// The repository from which the commits were taken.
  final GitRepository repository;

  /// The records of the files that were changed.
  final List<DiffRecord> diffRecords = <DiffRecord>[];

  /// Initialize a newly created representation of the differences between two
  /// commits. The differences are computed by parsing the result of a git diff
  /// command (the [diffResults]).
  ///
  /// This is only intended to be invoked from [GitRepository.getBlobDiff].
  CommitDelta._(this.repository, String diffResults) {
    _parseInput(diffResults);
  }

  /// Return `true` if there are differences.
  bool get hasDiffs => diffRecords.isNotEmpty;

  /// Return the absolute paths of all of the files in this commit whose name
  /// matches the given [fileName].
  Iterable<String> filesMatching(String fileName) {
    return diffRecords
        .where((DiffRecord record) => record.isFor(fileName))
        .map((DiffRecord record) => record.srcPath);
  }

  /// Remove any diffs for files that are either (a) outside the given
  /// [inclusionPaths], or (b) are files that do not match one of the given
  /// [globPatterns].
  void filterDiffs(List<String> inclusionPaths, List<Glob> globPatterns) {
    diffRecords.retainWhere((DiffRecord record) {
      var filePath = record.srcPath ?? record.dstPath;
      for (var inclusionPath in inclusionPaths) {
        if (path.isWithin(inclusionPath, filePath)) {
          for (var glob in globPatterns) {
            if (glob.matches(filePath)) {
              return true;
            }
          }
        }
      }
      return false;
    });
  }

  /// Return the index of the first nul character in the given [string] that is
  /// at or after the given [start] index.
  int _findEnd(String string, int start) {
    var length = string.length;
    var end = start;
    while (end < length && string.codeUnitAt(end) != NUL) {
      end++;
    }
    return end;
  }

  /// Return the result of converting the given [relativePath] to an absolute
  /// path. The path is assumed to be relative to the root of the repository.
  String _makeAbsolute(String relativePath) {
    return path.join(repository.path, relativePath);
  }

  /// Parse all of the diff records in the given [input].
  void _parseInput(String input) {
    var length = input.length;
    var start = 0;
    while (start < length) {
      start = _parseRecord(input, start);
    }
  }

  /// Parse a single record from the given [input], assuming that the record
  /// starts at the given [startIndex].
  ///
  /// Each record is formatted as a sequence of fields. The fields are, from the
  /// left to the right:
  ///
  /// 1. a colon.
  /// 2. mode for "src"; 000000 if creation or unmerged.
  /// 3. a space.
  /// 4. mode for "dst"; 000000 if deletion or unmerged.
  /// 5. a space.
  /// 6. sha1 for "src"; 0{40} if creation or unmerged.
  /// 7. a space.
  /// 8. sha1 for "dst"; 0{40} if creation, unmerged or "look at work tree".
  /// 9. a space.
  /// 10. status, followed by optional "score" number.
  /// 11. a tab or a NUL when -z option is used.
  /// 12. path for "src"
  /// 13. a tab or a NUL when -z option is used; only exists for C or R.
  /// 14. path for "dst"; only exists for C or R.
  /// 15. an LF or a NUL when -z option is used, to terminate the record.
  int _parseRecord(String input, int startIndex) {
    // Skip the first five fields.
    startIndex += 15;
    // Parse field 6
    var srcSha = input.substring(startIndex, startIndex + SHA_LENGTH);
    startIndex += SHA_LENGTH + 1;
    // Parse field 8
    var dstSha = input.substring(startIndex, startIndex + SHA_LENGTH);
    startIndex += SHA_LENGTH + 1;
    // Parse field 10
    var endIndex = _findEnd(input, startIndex);
    var status = input.substring(startIndex, endIndex);
    startIndex = endIndex + 1;
    // Parse field 12
    endIndex = _findEnd(input, startIndex);
    var srcPath = _makeAbsolute(input.substring(startIndex, endIndex));
    startIndex = endIndex + 1;
    // Parse field 14
    String dstPath;
    if (status.startsWith('C') || status.startsWith('R')) {
      endIndex = _findEnd(input, startIndex);
      dstPath = _makeAbsolute(input.substring(startIndex, endIndex));
    }
    // Create the record.
    diffRecords
        .add(DiffRecord(repository, srcSha, dstSha, status, srcPath, dstPath));
    return endIndex + 1;
  }
}

/// Representation of a single diff hunk.
class DiffHunk {
  /// The index of the first line that was changed in the src as returned by the
  /// diff command. The diff command numbers lines starting at 1, but it
  /// subtracts 1 from the line number if there are no lines on the source side
  /// of the hunk.
  int diffSrcLine;

  /// The index of the first line that was changed in the dst as returned by the
  /// diff command. The diff command numbers lines starting at 1, but it
  /// subtracts 1 from the line number if there are no lines on the destination
  /// side of the hunk.
  int diffDstLine;

  /// A list of the individual lines that were removed from the src.
  List<String> removeLines = <String>[];

  /// A list of the individual lines that were added to the dst.
  List<String> addLines = <String>[];

  /// Initialize a newly created hunk. The lines will be added after the object
  /// has been created.
  DiffHunk(this.diffSrcLine, this.diffDstLine);

  /// Return the index of the first line that was changed in the dst. Unlike the
  /// [diffDstLine] field, this getter adjusts the line number to be consistent
  /// whether or not there were any changed lines.
  int get dstLine {
    return addLines.isEmpty ? diffDstLine : diffDstLine - 1;
  }

  /// Return the index of the first line that was changed in the src. Unlike the
  /// [diffDstLine] field, this getter adjusts the line number to be consistent
  /// whether or not there were any changed lines.
  int get srcLine {
    return removeLines.isEmpty ? diffSrcLine : diffSrcLine - 1;
  }
}

/// A representation of a single line (record) from a raw diff.
class DiffRecord {
  /// The repository containing the file(s) that were modified.
  final GitRepository repository;

  /// The SHA1 of the blob in the src.
  final String srcBlob;

  /// The SHA1 of the blob in the dst.
  final String dstBlob;

  /// The status of the change. Valid values are:
  /// * A: addition of a file
  /// * C: copy of a file into a new one
  /// * D: deletion of a file
  /// * M: modification of the contents or mode of a file
  /// * R: renaming of a file
  /// * T: change in the type of the file
  /// * U: file is unmerged (you must complete the merge before it can be
  ///      committed)
  /// * X: "unknown" change type (most probably a bug, please report it)
  ///
  /// Status letters C and R are always followed by a score (denoting the
  /// percentage of similarity between the source and target of the move or
  /// copy), and are the only ones to be so.
  final String status;

  /// The path of the src.
  final String srcPath;

  /// The path of the dst if this was either a copy or a rename operation.
  final String dstPath;

  /// Initialize a newly created diff record.
  DiffRecord(this.repository, this.srcBlob, this.dstBlob, this.status,
      this.srcPath, this.dstPath);

  /// Return `true` if this record represents a file that was added.
  bool get isAddition => status == 'A';

  /// Return `true` if this record represents a file that was copied.
  bool get isCopy => status.startsWith('C');

  /// Return `true` if this record represents a file that was deleted.
  bool get isDeletion => status == 'D';

  /// Return `true` if this record represents a file that was modified.
  bool get isModification => status == 'M';

  /// Return `true` if this record represents a file that was renamed.
  bool get isRename => status.startsWith('R');

  /// Return `true` if this record represents an entity whose type was changed
  /// (for example, from a file to a directory).
  bool get isTypeChange => status == 'T';

  /// Return a representation of the individual blobs within this diff.
  BlobDiff getBlobDiff() => repository.getBlobDiff(srcBlob, dstBlob);

  /// Return `true` if this diff applies to a file with the given name.
  bool isFor(String fileName) =>
      (srcPath != null && fileName == path.basename(srcPath)) ||
      (dstPath != null && fileName == path.basename(dstPath));

  @override
  String toString() => srcPath ?? dstPath;
}

/// A representation of a git repository.
class GitRepository {
  /// The absolute path of the directory containing the repository.
  final String path;

  /// The logger to which git commands should be written, or `null` if the
  /// commands should not be written.
  final Logger logger;

  /// Initialize a newly created repository to represent the git repository at
  /// the given [path].
  ///
  /// If a [commandSink] is provided, any calls to git will be written to it.
  GitRepository(this.path, {this.logger});

  /// Checkout the given [commit] from the repository. This is done by running
  /// the command `git checkout <sha>`.
  void checkout(String commit) {
    _run(['checkout', commit]);
  }

  /// Return details about the differences between the two blobs identified by
  /// the SHA1 of the [srcBlob] and the SHA1 of the [dstBlob]. This is done by
  /// running the command `git diff <blob> <blob>`.
  BlobDiff getBlobDiff(String srcBlob, String dstBlob) {
    var result = _run(['diff', '-U0', srcBlob, dstBlob]);
    var diffResults = LineSplitter.split(result.stdout as String).toList();
    return BlobDiff._(diffResults);
  }

  /// Return details about the differences between the two commits identified by
  /// the [srcCommit] and [dstCommit]. This is done by running the command
  /// `git diff --raw --no-abbrev --no-renames -z <sha> <sha>`.
  CommitDelta getCommitDiff(String srcCommit, String dstCommit) {
    // Consider --find-renames instead of --no-renames if rename information is
    // desired.
    var result = _run([
      'diff',
      '--raw',
      '--no-abbrev',
      '--no-renames',
      '-z',
      srcCommit,
      dstCommit
    ]);
    return CommitDelta._(this, result.stdout as String);
  }

  /// Return a representation of the history of this repository. This is done by
  /// running the command `git rev-list --first-parent HEAD`.
  LinearCommitHistory getCommitHistory() {
    var result = _run(['rev-list', '--first-parent', 'HEAD']);
    var commitIds = LineSplitter.split(result.stdout as String).toList();
    return LinearCommitHistory(this, commitIds);
  }

  /// Synchronously run the given [executable] with the given [arguments].
  /// Return the result of running the process.
  ProcessResult _run(List<String> arguments) {
    logger?.log('git', 'git', arguments: arguments);
    return Process.runSync('git', arguments,
        stderrEncoding: utf8, stdoutEncoding: utf8, workingDirectory: path);
  }
}

/// A representation of the history of a Git repository. This only represents a
/// single linear path in the history graph.
class LinearCommitHistory {
  /// The repository whose history is being represented.
  final GitRepository repository;

  /// The id's (SHA's) of the commits in the repository, with the most recent
  /// commit being first and the oldest commit being last.
  final List<String> commitIds;

  /// Initialize a commit history for the given [repository] to have the given
  /// [commitIds].
  LinearCommitHistory(this.repository, this.commitIds);

  /// Return an iterator that can be used to iterate over this commit history.
  LinearCommitHistoryIterator iterator() {
    return LinearCommitHistoryIterator(this);
  }
}

/// An iterator over the history of a Git repository.
class LinearCommitHistoryIterator {
  /// The commit history being iterated over.
  final LinearCommitHistory history;

  /// The index of the current commit in the list of [commitIds].
  int currentCommit;

  /// Initialize a newly created iterator to iterate over the commits with the
  /// given [commitIds];
  LinearCommitHistoryIterator(this.history) {
    currentCommit = history.commitIds.length;
  }

  /// Return the SHA1 of the commit after the current commit (the 'dst' of the
  /// [next] diff).
  String get dstCommit => history.commitIds[currentCommit - 1];

  /// Return the SHA1 of the current commit (the 'src' of the [next] diff).
  String get srcCommit => history.commitIds[currentCommit];

  /// Advance to the next commit in the history. Return `true` if it is safe to
  /// ask for the [next] diff.
  bool moveNext() {
    if (currentCommit <= 1) {
      return false;
    }
    currentCommit--;
    return true;
  }

  /// Return the difference between the current commit and the commit that
  /// followed it.
  CommitDelta next() => history.repository.getCommitDiff(srcCommit, dstCommit);
}
