// Copyright (c) 2018, 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:analyzer/src/util/sdk.dart';
import 'package:args/args.dart';
import 'package:meta/meta.dart';

@visibleForTesting
StringSink errorSink = stderr;

@visibleForTesting
StringSink outSink = stdout;

@visibleForTesting
ExitHandler exitHandler = exit;

@visibleForTesting
typedef void ExitHandler(int code);

/// Command line options for `dartfix`.
class Options {
  String sdkPath;
  List<String> analysisRoots;
  bool verbose;

  static Options parse(List<String> args,
      {printAndFail(String msg) = printAndFail}) {
    final parser = new ArgParser(allowTrailingOptions: true);

    parser
      ..addOption(_sdkPathOption, help: 'The path to the Dart SDK.')
      ..addFlag(_helpOption,
          abbr: 'h',
          help:
              'Display this help message. Add --verbose to show hidden options.',
          defaultsTo: false,
          negatable: false)
      ..addFlag(_verboseOption,
          abbr: 'v',
          defaultsTo: false,
          help: 'Verbose output.',
          negatable: false);

    ArgResults results;
    try {
      results = parser.parse(args);
    } on FormatException catch (e) {
      errorSink.writeln(e.message);
      _showUsage(parser);
      exitHandler(15);
      return null; // Only reachable in testing.
    }

    if (results[_helpOption] as bool) {
      _showUsage(parser);
      exitHandler(0);
      return null; // Only reachable in testing.
    }

    Options options = new Options._fromArgs(results);

    // Check Dart SDK, and infer if unspecified.
    options.sdkPath ??= getSdkPath(args);
    String sdkPath = options.sdkPath;
    if (sdkPath == null) {
      errorSink.writeln('No Dart SDK found.');
      _showUsage(parser);
      return null; // Only reachable in testing.
    }
    if (!(new Directory(sdkPath)).existsSync()) {
      printAndFail('Invalid Dart SDK path: $sdkPath');
      return null; // Only reachable in testing.
    }

    // Check for files and/or directories to analyze.
    if (options.analysisRoots == null || options.analysisRoots.isEmpty) {
      errorSink.writeln('Expected at least one file or directory to analyze.');
      _showUsage(parser);
      exitHandler(15);
      return null; // Only reachable in testing.
    }

    return options;
  }

  Options._fromArgs(ArgResults results)
      : analysisRoots = results.rest,
        sdkPath = results[_sdkPathOption] as String,
        verbose = results[_verboseOption] as bool;

  static _showUsage(ArgParser parser) {
    errorSink.writeln(
        'Usage: $_binaryName [options...] <directory or list of files>');
    errorSink.writeln('');
    errorSink.writeln(parser.usage);
  }
}

const _binaryName = 'dartfix';
const _helpOption = 'help';
const _sdkPathOption = 'dart-sdk';
const _verboseOption = 'verbose';

/// Print the given [message] to stderr and exit with the given [exitCode].
void printAndFail(String message, {int exitCode: 15}) {
  errorSink.writeln(message);
  exitHandler(exitCode);
}
