// 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 =
      new 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 (String line in input) {
      _parseLine(line);
    }
  }

  /**
   * Parse a single [line] from the result of the git diff command.
   */
  void _parseLine(String line) {
    DiffHunk currentHunk = hunks.isEmpty ? null : hunks.last;
    if (line.startsWith('@@')) {
      Match match = hunkHeaderRegExp.matchAsPrefix(line);
      int srcLine = int.parse(match.group(1));
      int dstLine = int.parse(match.group(2));
      hunks.add(new 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) {
      String filePath = record.srcPath ?? record.dstPath;
      for (String inclusionPath in inclusionPaths) {
        if (path.isWithin(inclusionPath, filePath)) {
          for (Glob 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) {
    int length = string.length;
    int 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) {
    int length = input.length;
    int 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
    String srcSha = input.substring(startIndex, startIndex + SHA_LENGTH);
    startIndex += SHA_LENGTH + 1;
    // Parse field 8
    String dstSha = input.substring(startIndex, startIndex + SHA_LENGTH);
    startIndex += SHA_LENGTH + 1;
    // Parse field 10
    int endIndex = _findEnd(input, startIndex);
    String status = input.substring(startIndex, endIndex);
    startIndex = endIndex + 1;
    // Parse field 12
    endIndex = _findEnd(input, startIndex);
    String srcPath = _makeAbsolute(input.substring(startIndex, endIndex));
    startIndex = endIndex + 1;
    // Parse field 14
    String dstPath = null;
    if (status.startsWith('C') || status.startsWith('R')) {
      endIndex = _findEnd(input, startIndex);
      dstPath = _makeAbsolute(input.substring(startIndex, endIndex));
    }
    // Create the record.
    diffRecords.add(
        new 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 = null});

  /**
   * 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) {
    ProcessResult result = _run(['diff', '-U0', srcBlob, dstBlob]);
    List<String> diffResults =
        LineSplitter.split(result.stdout as String).toList();
    return new 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.
    ProcessResult result = _run([
      'diff',
      '--raw',
      '--no-abbrev',
      '--no-renames',
      '-z',
      srcCommit,
      dstCommit
    ]);
    return new 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() {
    ProcessResult result = _run(['rev-list', '--first-parent', 'HEAD']);
    List<String> commitIds =
        LineSplitter.split(result.stdout as String).toList();
    return new 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 new 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);
}
