// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:io' as io show Directory, File, stdout;

import 'package:path/path.dart' as path;
import 'package:process/process.dart';
import 'package:process_runner/process_runner.dart';

/// Utility methods for working with a git repository.
final class GitRepo {
  /// The git repository rooted at `root`.
  GitRepo.fromRoot(this.root, {
    this.verbose = false,
    StringSink? logSink,
    ProcessManager processManager = const LocalProcessManager(),
  }) :
      _processManager = processManager,
      logSink = logSink ?? io.stdout;

  /// Whether to produce verbose log output.
  ///
  /// If true, output of git commands will be printed to [logSink].
  final bool verbose;

  /// Where to send verbose log output.
  ///
  /// Defaults to [io.stdout].
  final StringSink logSink;

  /// The root of the git repo.
  final io.Directory root;

  /// The delegate to use for running processes.
  final ProcessManager _processManager;

  /// Returns a list of all non-deleted files which differ from the nearest
  /// merge-base with `main`. If it can't find a fork point, uses the default
  /// merge-base.
  ///
  /// This is only computed once and cached. Subsequent invocations of the
  /// getter will return the same result.
  late final Future<List<io.File>> changedFiles = _changedFiles();

  Future<List<io.File>> _changedFiles() async {
    final ProcessRunner processRunner = ProcessRunner(
      defaultWorkingDirectory: root,
      processManager: _processManager,
    );
    await _fetch(processRunner);
    // Find the merge base between the current branch and the branch that was
    // checked out at the time of the last fetch. The merge base is the common
    // ancestor of the two branches, and the output is the hash of the merge
    // base.
    ProcessRunnerResult mergeBaseResult = await processRunner.runProcess(
      <String>['git', 'merge-base', '--fork-point', 'FETCH_HEAD', 'HEAD'],
      failOk: true,
    );
    if (mergeBaseResult.exitCode != 0) {
      if (verbose) {
        logSink.writeln('git merge-base --fork-point failed, using default merge-base');
        logSink.writeln('Output:\n${mergeBaseResult.stdout}');
      }
      mergeBaseResult = await processRunner.runProcess(<String>[
        'git',
        'merge-base',
        'FETCH_HEAD',
        'HEAD',
      ]);
    }
    final String mergeBase = mergeBaseResult.stdout.trim();
    final ProcessRunnerResult masterResult = await processRunner.runProcess(<String>[
      'git',
      'diff',
      '--name-only',
      '--diff-filter=ACMRT',
      mergeBase,
    ]);
    return _gitOutputToList(masterResult);
  }

  /// Returns a list of non-deleted files which differ between the HEAD
  /// commit and its parent.
  ///
  /// This is only computed once and cached. Subsequent invocations of the
  /// getter will return the same result.
  late final Future<List<io.File>> changedFilesAtHead = _changedFilesAtHead();

  Future<List<io.File>> _changedFilesAtHead() async {
    final ProcessRunner processRunner = ProcessRunner(
      defaultWorkingDirectory: root,
      processManager: _processManager,
    );
    await _fetch(processRunner);
    final ProcessRunnerResult diffTreeResult = await processRunner.runProcess(
      <String>[
        'git',
        'diff-tree',
        '--no-commit-id',
        '--name-only',
        '--diff-filter=ACMRT', // Added, copied, modified, renamed, or type-changed.
        '-r',
        'HEAD',
      ],
    );
    return _gitOutputToList(diffTreeResult);
  }

  Future<void> _fetch(ProcessRunner processRunner) async {
    final ProcessRunnerResult fetchResult = await processRunner.runProcess(
      <String>['git', 'fetch', 'upstream', 'main'],
      failOk: true,
    );
    if (fetchResult.exitCode != 0) {
      if (verbose) {
        logSink.writeln('git fetch upstream main failed, using origin main');
        logSink.writeln('Output:\n${fetchResult.stdout}');
      }
      await processRunner.runProcess(<String>[
        'git',
        'fetch',
        'origin',
        'main',
      ]);
    }
  }

  List<io.File> _gitOutputToList(ProcessRunnerResult result) {
    final String diffOutput = result.stdout.trim();
    if (verbose) {
      logSink.writeln('git diff output:\n$diffOutput');
    }
    final Set<String> resultMap = <String>{};
    resultMap.addAll(diffOutput.split('\n').where(
      (String str) => str.isNotEmpty,
    ));
    return resultMap.map<io.File>(
      (String filePath) => io.File(path.join(root.path, filePath)),
    ).toList();
  }
}
