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

library dartdoc.bin;

import 'dart:async';
import 'dart:io';

import 'package:args/args.dart';
import 'package:dartdoc/dartdoc.dart';
import 'package:dartdoc/src/html/html_generator.dart';
import 'package:dartdoc/src/logging.dart';
import 'package:dartdoc/src/tool_runner.dart';
import 'package:stack_trace/stack_trace.dart';

class DartdocProgramOptionContext extends DartdocGeneratorOptionContext
    with LoggingContext {
  DartdocProgramOptionContext(DartdocOptionSet optionSet, Directory dir)
      : super(optionSet, dir);

  bool get asyncStackTraces => optionSet['asyncStackTraces'].valueAt(context);
  bool get generateDocs => optionSet['generateDocs'].valueAt(context);
  bool get help => optionSet['help'].valueAt(context);
  bool get version => optionSet['version'].valueAt(context);
}

Future<List<DartdocOption>> createDartdocProgramOptions() async {
  return <DartdocOption>[
    DartdocOptionArgOnly<bool>('asyncStackTraces', false,
        help: 'Display coordinated asynchronous stack traces (slow)',
        negatable: true),
    DartdocOptionArgOnly<bool>('generateDocs', true,
        help:
            'Generate docs into the output directory (or only display warnings if false).',
        negatable: true),
    DartdocOptionArgOnly<bool>('help', false,
        abbr: 'h', help: 'Show command help.', negatable: false),
    DartdocOptionArgOnly<bool>('version', false,
        help: 'Display the version for $name.', negatable: false),
  ];
}

/// Analyzes Dart files and generates a representation of included libraries,
/// classes, and members. Uses the current directory to look for libraries.
Future<void> main(List<String> arguments) async {
  DartdocOptionSet optionSet =
      await DartdocOptionSet.fromOptionGenerators('dartdoc', [
    createDartdocOptions,
    createDartdocProgramOptions,
    createLoggingOptions,
    createGeneratorOptions,
  ]);

  try {
    optionSet.parseArguments(arguments);
  } on FormatException catch (e) {
    stderr.writeln(' fatal error: ${e.message}');
    stderr.writeln('');
    _printUsage(optionSet.argParser);
    // Do not use exit() as this bypasses --pause-isolates-on-exit
    // TODO(jcollins-g): use exit once dart-lang/sdk#31747 is fixed.
    exitCode = 64;
    return;
  }
  if (optionSet['help'].valueAt(Directory.current)) {
    _printHelp(optionSet.argParser);
    exitCode = 0;
    return;
  }
  if (optionSet['version'].valueAt(Directory.current)) {
    _printVersion(optionSet.argParser);
    exitCode = 0;
    return;
  }

  DartdocProgramOptionContext config;
  try {
    config = DartdocProgramOptionContext(optionSet, null);
  } on DartdocOptionError catch (e) {
    stderr.writeln(' fatal error: ${e.message}');
    stderr.writeln('');
    await stderr.flush();
    _printUsage(optionSet.argParser);
    exitCode = 64;
    return;
  }
  startLogging(config);

  Dartdoc dartdoc = config.generateDocs
      ? await Dartdoc.withDefaultGenerators(config)
      : await Dartdoc.withEmptyGenerator(config);
  dartdoc.onCheckProgress.listen(logProgress);
  try {
    await Chain.capture(() async {
      await runZoned(dartdoc.generateDocs,
          zoneSpecification: ZoneSpecification(
              print: (Zone self, ZoneDelegate parent, Zone zone, String line) =>
                  logPrint(line)));
    }, onError: (e, Chain chain) {
      if (e is DartdocFailure) {
        stderr.writeln('\ndartdoc failed: ${e}.');
        exitCode = 1;
        return;
      } else {
        stderr.writeln('\ndartdoc failed: ${e}\n${chain.terse}');
        exitCode = 255;
        return;
      }
    }, when: config.asyncStackTraces);
  } finally {
    // Clear out any cached tool snapshots and temporary directories.
    // ignore: unawaited_futures
    SnapshotCache.instance.dispose();
    // ignore: unawaited_futures
    ToolTempFileTracker.instance.dispose();
  }
  exitCode = 0;
  return;
}

/// Print help if we are passed the help option.
void _printHelp(ArgParser parser) {
  print('Generate HTML documentation for Dart libraries.\n');
  print(parser.usage);
}

/// Print usage information on invalid command lines.
void _printUsage(ArgParser parser) {
  print('Usage: dartdoc [OPTIONS]\n');
  print(parser.usage);
}

/// Print version information.
void _printVersion(ArgParser parser) {
  print('dartdoc version: ${dartdocVersion}');
}
