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

import 'package:args/args.dart';
import 'package:dart_style/src/dart_formatter.dart';
import 'package:dart_style/src/formatter_exception.dart';
import 'package:dart_style/src/formatter_options.dart';
import 'package:dart_style/src/io.dart';

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

  parser.addFlag("help", abbr: "h", negatable: false,
      help: "Shows usage information.");
  parser.addOption("line-length", abbr: "l",
      help: "Wrap lines longer than this.",
      defaultsTo: "80");
  parser.addFlag("dry-run", abbr: "n", negatable: false,
      help: "Show which files would be modified but make no changes.");
  parser.addFlag("overwrite", abbr: "w", negatable: false,
      help: "Overwrite input files with formatted output.");
  parser.addFlag("machine", abbr: "m", negatable: false,
      help: "Produce machine-readable JSON output.");
  parser.addFlag("follow-links", negatable: false,
      help: "Follow links to files and directories.\n"
            "If unset, links will be ignored.");
  parser.addFlag("transform", abbr: "t", negatable: false,
      help: "Unused flag for compability with the old formatter.");

  var argResults;
  try {
    argResults = parser.parse(args);
  } on FormatException catch (err) {
    printUsage(parser, err.message);
    exitCode = 64;
    return;
  }

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

  if (argResults["dry-run"] && argResults["overwrite"]) {
    printUsage(parser,
        "Cannot use --dry-run and --overwrite at the same time.");
    exitCode = 64;
    return;
  }

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

    printUsage(parser,
        "Cannot use --$chosen and --$other at the same time.");
    exitCode = 64;
    return true;
  }

  var reporter = OutputReporter.print;
  if (argResults["dry-run"]) {
    if (checkForReporterCollision("dry-run", "overwrite")) return;
    if (checkForReporterCollision("dry-run", "machine")) return;

    reporter = OutputReporter.dryRun;
  } else if (argResults["overwrite"]) {
    if (checkForReporterCollision("overwrite", "machine")) return;

    if (argResults.rest.isEmpty) {
      printUsage(parser,
          "Cannot use --overwrite without providing any paths to format.");
      exitCode = 64;
      return;
    }

    reporter = OutputReporter.overwrite;
  } else if (argResults["machine"]) {
    reporter = OutputReporter.printJson;
  }

  var pageWidth;

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

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

  var options = new FormatterOptions(reporter,
      pageWidth: pageWidth, followLinks: followLinks);

  if (argResults.rest.isEmpty) {
    formatStdin(options);
  } else {
    formatPaths(options, argResults.rest);
  }
}

/// Reads input from stdin until it's closed, and the formats it.
void formatStdin(FormatterOptions options) {
  var input = new StringBuffer();
  stdin.transform(new Utf8Decoder()).listen(input.write, onDone: () {
    var formatter = new DartFormatter(pageWidth: options.pageWidth);
    try {
      var source = input.toString();
      var output = formatter.format(source, uri: "stdin");
      options.reporter.showFile(null, "<stdin>", output,
          changed: source != output);
      return true;
    } on FormatterException catch (err) {
      stderr.writeln(err.message());
    } catch (err, stack) {
      stderr.writeln('''Hit a bug in the formatter when formatting stdin.
Please report at: github.com/dart-lang/dart_style/issues
$err
$stack''');
    }
  });
}

/// Formats all of the files and directories given by [paths].
void formatPaths(FormatterOptions options, List<String> paths) {
  for (var path in paths) {
    var directory = new Directory(path);
    if (directory.existsSync()) {
      if (!processDirectory(options, directory)) {
        exitCode = 65;
      }
      continue;
    }

    var file = new File(path);
    if (file.existsSync()) {
      if (!processFile(options, file)) {
        exitCode = 65;
      }
    } else {
      stderr.writeln('No file or directory found at "$path".');
    }
  }
}

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

  var message = "Reformats whitespace in Dart source files.";
  if (error != null) {
    message = error;
    output = stdout;
  }

  output.write("""$message

Usage: dartformat [-n|-w] [files or directories...]

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