// Copyright (c) 2017, 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/dart/element/element.dart';
import 'package:dartdoc/src/dartdoc_options.dart';
import 'package:dartdoc/src/logging.dart';
import 'package:dartdoc/src/model.dart';
import 'package:dartdoc/src/package_meta.dart';
import 'package:dartdoc/src/tuple.dart';

abstract class PackageWarningOptionContext implements DartdocOptionContextBase {
  bool get allowNonLocalWarnings =>
      optionSet['allowNonLocalWarnings'].valueAt(context);
  // allowWarningsInPackages, ignoreWarningsInPackages, errors, warnings, and ignore
  // are only used indirectly via the synthetic packageWarningOptions option.
  PackageWarningOptions get packageWarningOptions =>
      optionSet['packageWarningOptions'].valueAt(context);
  bool get verboseWarnings => optionSet['verboseWarnings'].valueAt(context);
}

Future<List<DartdocOption>> createPackageWarningOptions() async {
  return <DartdocOption>[
    new DartdocOptionArgOnly<bool>('allowNonLocalWarnings', false,
        negatable: true,
        help: 'Show warnings from packages we are not documenting locally.'),

    // Options for globally enabling/disabling all warnings and errors
    // for individual packages are command-line only.  This will allow
    // meta-packages like Flutter to control whether warnings are displayed for
    // packages they don't control.
    new DartdocOptionArgOnly<List<String>>('allowWarningsInPackages', null,
        help:
            'Package names to display warnings for (ignore all others if set).'),
    new DartdocOptionArgOnly<List<String>>('allowErrorsInPackages', null,
        help: 'Package names to display errors for (ignore all others if set)'),
    new DartdocOptionArgOnly<List<String>>('ignoreWarningsInPackages', null,
        help:
            'Package names to ignore warnings for.  Takes priority over allow-warnings-in-packages'),
    new DartdocOptionArgOnly<List<String>>('ignoreErrorsInPackages', null,
        help:
            'Package names to ignore errors for. Takes priority over allow-errors-in-packages'),
    // Options for globally enabling/disabling warnings and errors across
    // packages.  Loaded from dartdoc_options.yaml, but command line arguments
    // will override.
    new DartdocOptionArgFile<List<String>>('errors', null,
        help:
            'Additional warning names to force as errors.  Specify an empty list to force defaults (overriding dartdoc_options.yaml)\nDefaults:\n' +
                (packageWarningDefinitions.values
                        .where((d) =>
                            d.defaultWarningMode == PackageWarningMode.error)
                        .toList()
                          ..sort())
                    .map((d) => '   ${d.warningName}: ${d.shortHelp}')
                    .join('\n')),
    new DartdocOptionArgFile<List<String>>('ignore', null,
        help:
            'Additional warning names to ignore.  Specify an empty list to force defaults (overriding dartdoc_options.yaml).\nDefaults:\n' +
                (packageWarningDefinitions.values
                        .where((d) =>
                            d.defaultWarningMode == PackageWarningMode.ignore)
                        .toList()
                          ..sort())
                    .map((d) => '   ${d.warningName}: ${d.shortHelp}')
                    .join('\n')),
    new DartdocOptionArgFile<List<String>>('warnings', null,
        help:
            'Additional warning names to show as warnings (instead of error or ignore, if not warning by default).\nDefaults:\n' +
                (packageWarningDefinitions.values
                        .where((d) =>
                            d.defaultWarningMode == PackageWarningMode.warn)
                        .toList()
                          ..sort())
                    .map((d) => '   ${d.warningName}: ${d.shortHelp}')
                    .join('\n')),
    // Synthetic option uses a factory to build a PackageWarningOptions from all the above flags.
    new DartdocOptionSyntheticOnly<PackageWarningOptions>(
        'packageWarningOptions', PackageWarningOptions.fromOptions),
  ];
}

class PackageWarningDefinition implements Comparable<PackageWarningDefinition> {
  final String warningName;
  final String shortHelp;
  final List<String> longHelp;
  final PackageWarning kind;
  final PackageWarningMode defaultWarningMode;

  const PackageWarningDefinition(this.kind, this.warningName, this.shortHelp,
      {List<String> longHelp, PackageWarningMode defaultWarningMode})
      : this.longHelp = longHelp ?? const [],
        this.defaultWarningMode = defaultWarningMode ?? PackageWarningMode.warn;

  @override
  int compareTo(PackageWarningDefinition other) {
    return warningName.compareTo(other.warningName);
  }
}

/// Same as [packageWarningDefinitions], except keyed by the warning name.
final Map<String, PackageWarningDefinition> packageWarningsByName =
    new Map.fromEntries(packageWarningDefinitions.values
        .map((definition) => new MapEntry(definition.warningName, definition)));

/// Provides description text and command line flags for warnings.
/// TODO(jcollins-g): Actually use this for command line flags.
final Map<PackageWarning, PackageWarningDefinition> packageWarningDefinitions =
    const {
  PackageWarning.ambiguousDocReference: const PackageWarningDefinition(
      PackageWarning.ambiguousDocReference,
      "ambiguous-doc-reference",
      "A comment reference could refer to two or more different objects"),
  PackageWarning.ambiguousReexport: const PackageWarningDefinition(
      PackageWarning.ambiguousReexport,
      "ambiguous-reexport",
      "A symbol is exported from private to public in more than one library and dartdoc can not determine which one is canonical",
      longHelp: const [
        "Use {@canonicalFor @@name@@} in the desired library's documentation to resolve",
        "the ambiguity and/or override dartdoc's decision, or structure your package ",
        "so the reexport is less ambiguous.  The symbol will still be referenced in ",
        "all candidates -- this only controls the location where it will be written ",
        "and which library will be displayed in navigation for the relevant pages.",
        "The flag --ambiguous-reexport-scorer-min-confidence allows you to set the",
        "threshold at which this warning will appear."
      ]),
  PackageWarning.ignoredCanonicalFor: const PackageWarningDefinition(
      PackageWarning.ignoredCanonicalFor,
      "ignored-canonical-for",
      "A @canonicalFor tag refers to a library which this symbol can not be canonical for"),
  PackageWarning.noCanonicalFound: const PackageWarningDefinition(
      PackageWarning.noCanonicalFound,
      "no-canonical-found",
      "A symbol is part of the public interface for this package, but no library documented with this package documents it so dartdoc can not link to it"),
  PackageWarning.noLibraryLevelDocs: const PackageWarningDefinition(
      PackageWarning.noLibraryLevelDocs,
      "no-library-level-docs",
      "There are no library level docs for this library"),
  PackageWarning.packageOrderGivesMissingPackageName:
      const PackageWarningDefinition(
          PackageWarning.packageOrderGivesMissingPackageName,
          "category-order-gives-missing-package-name",
          "The category-order flag on the command line was given the name of a nonexistent package"),
  PackageWarning.reexportedPrivateApiAcrossPackages: const PackageWarningDefinition(
      PackageWarning.reexportedPrivateApiAcrossPackages,
      "reexported-private-api-across-packages",
      "One or more libraries reexports private API members from outside its own package"),
  PackageWarning.unresolvedDocReference: const PackageWarningDefinition(
      PackageWarning.unresolvedDocReference,
      "unresolved-doc-reference",
      "A comment reference could not be found in parameters, enclosing class, enclosing library, or at the top level of any documented library with the package"),
  PackageWarning.brokenLink: const PackageWarningDefinition(
      PackageWarning.brokenLink,
      "broken-link",
      "Dartdoc generated a link to a non-existent file"),
  PackageWarning.unknownMacro: const PackageWarningDefinition(
      PackageWarning.unknownMacro,
      "unknown-macro",
      "A comment reference contains an unknown macro"),
  PackageWarning.orphanedFile: const PackageWarningDefinition(
      PackageWarning.orphanedFile,
      "orphaned-file",
      "Dartdoc generated files that are unreachable from the index"),
  PackageWarning.unknownFile: const PackageWarningDefinition(
      PackageWarning.unknownFile,
      "unknown-file",
      "A leftover file exists in the tree that dartdoc did not write in this pass"),
  PackageWarning.missingFromSearchIndex: const PackageWarningDefinition(
      PackageWarning.missingFromSearchIndex,
      "missing-from-search-index",
      "A file generated by dartdoc is not present in the generated index.json"),
  PackageWarning.typeAsHtml: const PackageWarningDefinition(
      PackageWarning.typeAsHtml,
      "type-as-html",
      "Use of <> in a comment for type parameters is being treated as HTML by markdown",
      defaultWarningMode: PackageWarningMode.ignore),
  PackageWarning.invalidParameter: const PackageWarningDefinition(
      PackageWarning.invalidParameter,
      "invalid-parameter",
      "A parameter given to a dartdoc directive was invalid.",
      defaultWarningMode: PackageWarningMode.error),
  PackageWarning.toolError: const PackageWarningDefinition(
      PackageWarning.toolError,
      "tool-error",
      "Unable to execute external tool.",
      defaultWarningMode: PackageWarningMode.error),
  PackageWarning.deprecated: const PackageWarningDefinition(
      PackageWarning.deprecated,
      "deprecated",
      "A dartdoc directive has a deprecated format."),
  PackageWarning.unresolvedExport: const PackageWarningDefinition(
      PackageWarning.unresolvedExport,
      "unresolved-export",
      "An export refers to a URI that cannot be resolved.",
      defaultWarningMode: PackageWarningMode.error),
};

/// Something that package warnings can be called on.  Optionally associated
/// with an analyzer [element].
abstract class Warnable implements Canonicalization {
  void warn(PackageWarning warning,
      {String message, Iterable<Locatable> referredFrom});
  Element get element;
  Warnable get enclosingElement;
  Package get package;
}

/// Something that can be located for warning purposes.
abstract class Locatable {
  List<Locatable> get documentationFrom;
  String get fullyQualifiedName;
  String get href;

  /// A string indicating the URI of this Locatable, usually derived from
  /// [Element.location].
  String get location;
}

// The kinds of warnings that can be displayed when documenting a package.
enum PackageWarning {
  ambiguousDocReference,
  ambiguousReexport,
  ignoredCanonicalFor,
  noCanonicalFound,
  noLibraryLevelDocs,
  packageOrderGivesMissingPackageName,
  reexportedPrivateApiAcrossPackages,
  unresolvedDocReference,
  unknownMacro,
  unknownHtmlFragment,
  brokenLink,
  orphanedFile,
  unknownFile,
  missingFromSearchIndex,
  typeAsHtml,
  invalidParameter,
  toolError,
  deprecated,
  unresolvedExport,
}

/// Used to declare defaults for a particular package warning.
enum PackageWarningMode {
  ignore,
  warn,
  error,
}

/// Warnings it is OK to skip if we can determine the warnable isn't documented.
/// In particular, this set should not include warnings around public/private
/// or canonicalization problems, because those can break the isDocumented()
/// check.
final Set<PackageWarning> skipWarningIfNotDocumentedFor = new Set()
  ..addAll([PackageWarning.unresolvedDocReference, PackageWarning.typeAsHtml]);

class PackageWarningOptions {
  final Map<PackageWarning, PackageWarningMode> warningModes = {};

  PackageWarningOptions() {
    for (PackageWarningDefinition definition
        in packageWarningDefinitions.values) {
      switch (definition.defaultWarningMode) {
        case PackageWarningMode.warn:
          {
            warn(definition.kind);
          }
          break;
        case PackageWarningMode.error:
          {
            error(definition.kind);
          }
          break;
        case PackageWarningMode.ignore:
          {
            ignore(definition.kind);
          }
          break;
      }
    }
  }

  /// [packageMeta] parameter is for testing.
  static PackageWarningOptions fromOptions(
      DartdocSyntheticOption<PackageWarningOptions> option, Directory dir) {
    // First, initialize defaults.
    PackageWarningOptions newOptions = PackageWarningOptions();
    PackageMeta packageMeta = new PackageMeta.fromDir(dir);

    // Interpret errors/warnings/ignore options.  In the event of conflict, warning overrides error and
    // ignore overrides warning.
    for (String warningName in option.parent['errors'].valueAt(dir) ?? []) {
      if (packageWarningsByName[warningName] != null) {
        newOptions.error(packageWarningsByName[warningName].kind);
      }
    }
    for (String warningName in option.parent['warnings'].valueAt(dir) ?? []) {
      if (packageWarningsByName[warningName] != null) {
        newOptions.warn(packageWarningsByName[warningName].kind);
      }
    }
    for (String warningName in option.parent['ignore'].valueAt(dir) ?? []) {
      if (packageWarningsByName[warningName] != null) {
        newOptions.ignore(packageWarningsByName[warningName].kind);
      }
    }

    // Check whether warnings are allowed at all in this package.
    List<String> allowWarningsInPackages =
        option.parent['allowWarningsInPackages'].valueAt(dir);
    List<String> allowErrorsInPackages =
        option.parent['allowErrorsInPackages'].valueAt(dir);
    List<String> ignoreWarningsInPackages =
        option.parent['ignoreWarningsInPackages'].valueAt(dir);
    List<String> ignoreErrorsInPackages =
        option.parent['ignoreErrorsInPackages'].valueAt(dir);
    if (allowWarningsInPackages != null &&
        !allowWarningsInPackages.contains(packageMeta.name)) {
      PackageWarning.values
          .forEach((PackageWarning kind) => newOptions.ignore(kind));
    }
    if (allowErrorsInPackages != null &&
        !allowWarningsInPackages.contains(packageMeta.name)) {
      PackageWarning.values
          .forEach((PackageWarning kind) => newOptions.ignore(kind));
    }
    if (ignoreWarningsInPackages != null &&
        ignoreWarningsInPackages.contains(packageMeta.name)) {
      PackageWarning.values
          .forEach((PackageWarning kind) => newOptions.ignore(kind));
    }
    if (ignoreErrorsInPackages != null &&
        ignoreErrorsInPackages.contains(packageMeta.name)) {
      PackageWarning.values
          .forEach((PackageWarning kind) => newOptions.ignore(kind));
    }
    return newOptions;
  }

  void ignore(PackageWarning kind) =>
      warningModes[kind] = PackageWarningMode.ignore;
  void warn(PackageWarning kind) =>
      warningModes[kind] = PackageWarningMode.warn;
  void error(PackageWarning kind) =>
      warningModes[kind] = PackageWarningMode.error;

  PackageWarningMode getMode(PackageWarning kind) => warningModes[kind];
}

class PackageWarningCounter {
  final countedWarnings =
      new Map<Element, Set<Tuple2<PackageWarning, String>>>();
  final _items = <Jsonable>[];
  final _displayedWarningCounts = <PackageWarning, int>{};
  final PackageGraph packageGraph;

  PackageWarningCounter(this.packageGraph);

  /// Actually write out the warning.  Assumes it is already counted with add.
  void _writeWarning(PackageWarning kind, PackageWarningMode mode,
      bool verboseWarnings, String name, String fullMessage) {
    if (mode == PackageWarningMode.ignore) {
      return;
    }
    String type;
    if (mode == PackageWarningMode.error) {
      type = "error";
    } else if (mode == PackageWarningMode.warn) {
      type = "warning";
    }
    if (type != null) {
      var entry = "  $type: $fullMessage";
      _displayedWarningCounts.putIfAbsent(kind, () => 0);
      _displayedWarningCounts[kind] += 1;
      if (_displayedWarningCounts[kind] == 1 &&
          verboseWarnings &&
          packageWarningDefinitions[kind].longHelp.isNotEmpty) {
        // First time we've seen this warning.  Give a little extra info.
        final String separator = '\n            ';
        final String nameSub = r'@@name@@';
        String verboseOut =
            '$separator${packageWarningDefinitions[kind].longHelp.join(separator)}'
                .replaceAll(nameSub, name);
        entry = '$entry$verboseOut';
      }
      assert(entry == entry.trimRight());
      _items.add(new _JsonWarning(type, kind, fullMessage, entry));
    }
    for (var item in _items) {
      logWarning(item);
    }
    _items.clear();
  }

  /// Returns true if we've already warned for this.
  bool hasWarning(Warnable element, PackageWarning kind, String message) {
    Tuple2<PackageWarning, String> warningData = new Tuple2(kind, message);
    if (countedWarnings.containsKey(element?.element)) {
      return countedWarnings[element?.element].contains(warningData);
    }
    return false;
  }

  /// Adds the warning to the counter, and writes out the fullMessage string
  /// if configured to do so.
  void addWarning(Warnable element, PackageWarning kind, String message,
      String fullMessage) {
    assert(!hasWarning(element, kind, message));
    // TODO(jcollins-g): Make addWarning not accept nulls for element.
    PackageWarningOptionContext config =
        element?.config ?? packageGraph.defaultPackage.config;
    PackageWarningMode warningMode = config.packageWarningOptions.getMode(kind);
    if (!config.allowNonLocalWarnings &&
        element != null &&
        !element.package.isLocal) {
      warningMode = PackageWarningMode.ignore;
    }
    if (warningMode == PackageWarningMode.warn)
      warningCount += 1;
    else if (warningMode == PackageWarningMode.error) errorCount += 1;
    Tuple2<PackageWarning, String> warningData = new Tuple2(kind, message);
    countedWarnings.putIfAbsent(element?.element, () => new Set());
    countedWarnings[element?.element].add(warningData);
    _writeWarning(kind, warningMode, config.verboseWarnings,
        element?.fullyQualifiedName, fullMessage);
  }

  int errorCount = 0;
  int warningCount = 0;

  @override
  String toString() {
    String errors = '$errorCount ${errorCount == 1 ? "error" : "errors"}';
    String warnings =
        '$warningCount ${warningCount == 1 ? "warning" : "warnings"}';
    return [errors, warnings].join(', ');
  }
}

class _JsonWarning extends Jsonable {
  final String type;
  final PackageWarning kind;
  final String message;

  @override
  final String text;

  _JsonWarning(this.type, this.kind, this.message, this.text);

  @override
  Map<String, dynamic> toJson() => {
        'type': type,
        'kind': packageWarningDefinitions[kind].warningName,
        'message': message,
        'text': text
      };
}
