// Copyright (c) 2020, 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.

import 'package:args/args.dart';
import 'package:args/command_runner.dart';
import 'package:cli_util/cli_logging.dart';
import 'package:dartdev/src/commands/fix.dart';
import 'package:dartdev/src/core.dart';
import 'package:dartdev/src/utils.dart';

Future<int?> main(List<String> args) async {
  var runner = FixRunner(logger: Logger.standard());
  var result = await runner.runFix(args);
  return result.returnCode;
}

class CapturedProgress extends Progress {
  final LoggerOutput output;

  bool canceled = false;
  bool finished = false;

  CapturedProgress(this.output, String message) : super(message) {
    output.progress.writeln(message);
  }

  @override
  void cancel() {
    canceled = true;
  }

  @override
  void finish({String? message, bool showTiming = false}) {
    // todo (pq): consider capturing / tracking finish display updates.
    finished = true;
  }
}

class CapturingLogger implements Logger {
  final LoggerOutput output = LoggerOutput();

  @override
  final Ansi ansi = Ansi(Ansi.terminalSupportsAnsi);

  @override
  bool isVerbose;

  CapturingLogger({this.isVerbose = false});

  @override
  void flush() {
    // deprecated.
  }

  @override
  Progress progress(String message) => CapturedProgress(output, message);

  @override
  void stderr(String message) {
    output.stderr.writeln(message);
  }

  @override
  void stdout(String message) {
    output.stdout.writeln(message);
  }

  @override
  void trace(String message) {
    output.trace.writeln(message);
  }

  @override
  void write(String message) {
    output.stdout.write(message);
  }

  @override
  void writeCharCode(int charCode) {
    output.stdout.writeCharCode(charCode);
  }
}

class FixResult<T extends Logger> {
  /// The value returned by [FixCommand.run].
  final int? returnCode;

  /// The logger used in driving fixes.
  final T logger;

  FixResult(this.logger, this.returnCode);
}

class FixRunner<T extends Logger> extends CommandRunner<int> {
  final _supportedOptions = ['dry-run', 'apply'];

  T logger;

  @override
  final ArgParser argParser = globalDartdevOptionsParser();

  FixRunner({required this.logger})
      : super('fix_runner',
            'A command-line utility for testing the `dart fix` command.') {
    addCommand(FixCommand());
    _supportedOptions.forEach(argParser.addOption);
  }

  @override
  Future<int?> runCommand(ArgResults topLevelResults) async {
    var result = await super.runCommand(topLevelResults);
    return result;
  }

  Future<FixResult<T>> runFix(List<String> args) async {
    log = logger;
    var argResults = argParser.parse(['fix', ...args]);
    var result = await runCommand(argResults);
    return FixResult(logger, result);
  }
}

class LoggerOutput {
  /// Messages reported to progress.
  final StringBuffer progress = StringBuffer();

  /// Messages reported to stdout.
  final StringBuffer stdout = StringBuffer();

  /// Messages reported to stderr.
  final StringBuffer stderr = StringBuffer();

  /// Messages reported to trace.
  final StringBuffer trace = StringBuffer();
}
