// 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.
import 'dart:io';

import 'package:args/args.dart';
import 'package:dart_style/src/cli/formatter_options.dart';
import 'package:dart_style/src/cli/options.dart';
import 'package:dart_style/src/cli/output.dart';
import 'package:dart_style/src/cli/show.dart';
import 'package:dart_style/src/cli/summary.dart';
import 'package:dart_style/src/io.dart';
import 'package:dart_style/src/style_fix.dart';

void main(List<String> args) async {
  var parser = ArgParser(allowTrailingOptions: true);

  defineOptions(parser,
      oldCli: true, verbose: args.contains('--verbose') || args.contains('-v'));

  ArgResults argResults;
  try {
    argResults = parser.parse(args);
  } on FormatException catch (err) {
    usageError(parser, err.message);
  }

  if (argResults['help']) {
    printUsage(parser);
    return;
  }

  if (argResults['version']) {
    print(dartStyleVersion);
    return;
  }

  if (argResults['verbose'] && !argResults['help']) {
    usageError(parser, 'Can only use --verbose with --help.');
  }

  List<int>? selection;
  try {
    selection = parseSelection(argResults, 'preserve');
  } on FormatException catch (exception) {
    usageError(parser, exception.message);
  }

  if (argResults['dry-run'] && argResults['overwrite']) {
    usageError(
        parser, 'Cannot use --dry-run and --overwrite at the same time.');
  }

  void checkForReporterCollision(String chosen, String other) {
    if (!argResults[other]) return;

    usageError(parser, 'Cannot use --$chosen and --$other at the same time.');
  }

  var show = Show.legacy;
  var summary = Summary.none;
  var output = Output.show;
  var setExitIfChanged = false;
  if (argResults['dry-run']) {
    checkForReporterCollision('dry-run', 'overwrite');
    checkForReporterCollision('dry-run', 'machine');

    show = Show.dryRun;
    output = Output.none;
  } else if (argResults['overwrite']) {
    checkForReporterCollision('overwrite', 'machine');

    if (argResults.rest.isEmpty) {
      usageError(parser,
          'Cannot use --overwrite without providing any paths to format.');
    }

    show = Show.overwrite;
    output = Output.write;
  } else if (argResults['machine']) {
    output = Output.json;
  }

  if (argResults['profile']) summary = Summary.profile();

  setExitIfChanged = argResults['set-exit-if-changed'];

  int pageWidth;
  try {
    pageWidth = int.parse(argResults['line-length']);
  } on FormatException catch (_) {
    usageError(
        parser,
        '--line-length must be an integer, was '
        '"${argResults['line-length']}".');
  }

  int indent;
  try {
    indent = int.parse(argResults['indent']);
    if (indent < 0 || indent.toInt() != indent) throw FormatException();
  } on FormatException catch (_) {
    usageError(
        parser,
        '--indent must be a non-negative integer, was '
        '"${argResults['indent']}".');
  }

  var followLinks = argResults['follow-links'];

  var fixes = <StyleFix>[];
  if (argResults['fix']) fixes.addAll(StyleFix.all);
  for (var fix in StyleFix.all) {
    if (argResults['fix-${fix.name}']) {
      if (argResults['fix']) {
        usageError(parser, '--fix-${fix.name} is redundant with --fix.');
      }

      fixes.add(fix);
    }
  }

  if (argResults.wasParsed('stdin-name') && argResults.rest.isNotEmpty) {
    usageError(parser, 'Cannot pass --stdin-name when not reading from stdin.');
  }

  var options = FormatterOptions(
      indent: indent,
      pageWidth: pageWidth,
      followLinks: followLinks,
      fixes: fixes,
      show: show,
      output: output,
      summary: summary,
      setExitIfChanged: setExitIfChanged);

  if (argResults.rest.isEmpty) {
    await formatStdin(options, selection, argResults['stdin-name'] as String);
  } else {
    formatPaths(options, argResults.rest);
  }

  options.summary.show();
}

/// Prints [error] and usage help then exits with exit code 64.
Never usageError(ArgParser parser, String error) {
  printUsage(parser, error);
  exit(64);
}

void printUsage(ArgParser parser, [String? error]) {
  var output = stdout;

  var message = 'Idiomatically format Dart source code.';
  if (error != null) {
    message = error;
    output = stdout;
  }

  output.write('''$message

Usage:   dartfmt [options...] [files or directories...]

Example: dartfmt -w .
         Reformats every Dart file in the current directory tree.

${parser.usage}
''');
}
