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

import 'package:args/command_runner.dart';

import '../io.dart';
import '../style_fix.dart';
import 'formatter_options.dart';
import 'options.dart';
import 'output.dart';
import 'show.dart';
import 'summary.dart';

class FormatCommand extends Command {
  @override
  String get name => 'format';

  @override
  String get description => 'Idiomatically format Dart source code.';

  @override
  String get invocation =>
      '${runner.executableName} $name [options...] <files or directories...>';

  FormatCommand({bool verbose = false}) {
    defineOptions(argParser, oldCli: false, verbose: verbose);
  }

  @override
  Future<int> run() async {
    if (argResults['version']) {
      print(dartStyleVersion);
      return 0;
    }

    var show = const {
      'all': Show.all,
      'changed': Show.changed,
      'none': Show.none
    }[argResults['show']];

    var output = const {
      'write': Output.write,
      'show': Output.show,
      'none': Output.none,
      'json': Output.json,
    }[argResults['output']];

    var summary = Summary.none;
    switch (argResults['summary'] as String) {
      case 'line':
        summary = Summary.line();
        break;
      case 'profile':
        summary = Summary.profile();
        break;
    }

    // If the user is sending code through stdin, default the output to stdout.
    if (!argResults.wasParsed('output') && argResults.rest.isEmpty) {
      output = Output.show;
    }

    // If the user wants to print the code and didn't indicate how the files
    // should be printed, default to only showing the code.
    if (!argResults.wasParsed('show') &&
        (output == Output.show || output == Output.json)) {
      show = Show.none;
    }

    // If the user wants JSON output, default to no summary.
    if (!argResults.wasParsed('summary') && output == Output.json) {
      summary = Summary.none;
    }

    // Can't use --verbose with anything but --help.
    if (argResults['verbose'] && !argResults['help']) {
      usageException('Can only use --verbose with --help.');
    }

    // Can't use any summary with JSON output.
    if (output == Output.json && summary != Summary.none) {
      usageException('Cannot print a summary with JSON output.');
    }

    int pageWidth;
    try {
      pageWidth = int.parse(argResults['line-length']);
    } on FormatException catch (_) {
      usageException('--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 (_) {
      usageException('--indent must be a non-negative integer, was '
          '"${argResults['indent']}".');
    }

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

        fixes.add(fix);
      }
    }

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

    var followLinks = argResults['follow-links'];
    var setExitIfChanged = argResults['set-exit-if-changed'] as bool;

    // If stdin isn't connected to a pipe, then the user is not passing
    // anything to stdin, so let them know they made a mistake.
    if (argResults.rest.isEmpty && stdin.hasTerminal) {
      usageException('Missing paths to code to format.');
    }

    if (argResults.rest.isEmpty && output == Output.write) {
      usageException('Cannot use --output=write when reading from stdin.');
    }

    if (argResults.wasParsed('stdin-name') && argResults.rest.isNotEmpty) {
      usageException('Cannot pass --stdin-name when not reading from stdin.');
    }
    var stdinName = argResults['stdin-name'] as String;

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

    if (argResults.rest.isEmpty) {
      formatStdin(options, selection, stdinName);
    } else {
      formatPaths(options, argResults.rest);
      options.summary.show();
    }

    return 0;
  }
}
