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

// ignore_for_file: analyzer_use_new_elements

import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/dart/element/element2.dart';
import 'package:dartdoc/src/dartdoc_options.dart';
import 'package:dartdoc/src/io_utils.dart';
import 'package:dartdoc/src/model/comment_referable.dart';
import 'package:dartdoc/src/model/kind.dart';
import 'package:dartdoc/src/model/model.dart';
import 'package:dartdoc/src/model_utils.dart';
import 'package:dartdoc/src/package_meta.dart';
import 'package:dartdoc/src/warnings.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as p show Context;
import 'package:pub_semver/pub_semver.dart';

// All hrefs are emitted as relative paths from the output root. We are unable
// to compute them from the page we are generating, and many properties computed
// using hrefs are memoized anyway. To build complete relative hrefs, we emit
// the href with this placeholder, and then replace it with the current page's
// base href afterwards.
// See https://github.com/dart-lang/dartdoc/issues/2090 for further context.
// TODO: Find an approach that doesn't require doing this.
// Unlikely to be mistaken for an identifier, html tag, or something else that
// might reasonably exist normally.
@internal
const String htmlBasePlaceholder = r'%%__HTMLBASE_dartdoc_internal__%%';

/// A [LibraryContainer] that contains [Library] objects related to a particular
/// package.
class Package extends LibraryContainer
    with Nameable, Locatable, Warnable, CommentReferable {
  @override
  final String name;

  @override
  final PackageGraph packageGraph;

  // Creates a package, if necessary, and adds it to the [packageGraph].
  factory Package.fromPackageMeta(
      PackageMeta packageMeta, PackageGraph packageGraph) {
    var packageName = packageMeta.name;
    var expectNonLocal = !packageGraph.packageMap.containsKey(packageName) &&
        packageGraph.allLibrariesAdded;
    var packagePath = packageGraph.resourceProvider.pathContext
        .canonicalize(packageMeta.dir.path);
    var package = packageGraph.packageMap.putIfAbsent(
      packageMeta.name,
      () => Package._(
        packageMeta.name,
        packageGraph,
        packageMeta,
        packagePath,
      ),
    );
    // Verify that we don't somehow decide to document locally a package picked
    // up after all documented libraries are added, because that breaks the
    // assumption that we've picked up all documented libraries and packages
    // before allLibrariesAdded is true.
    assert(
        !(expectNonLocal && package.documentedWhere == DocumentLocation.local),
        "Found more libraries to document after 'allLibrariesAdded' was set to "
        'true');
    return package;
  }

  Package._(this.name, this.packageGraph, this.packageMeta, this.packagePath)
      : config = DartdocOptionContext.fromContext(
          packageGraph.config,
          packageGraph.resourceProvider.getFolder(packagePath),
          packageGraph.resourceProvider,
        );

  @override
  bool get isCanonical => true;

  /// Number of times we have invoked a tool for this package.
  int toolInvocationIndex = 0;

  // The animation IDs that have already been used, indexed by the [href] of the
  // object that contains them.
  Map<String?, Set<String>> usedAnimationIdsByHref = {};

  /// Holds all libraries added to this package.  May include non-documented
  /// libraries, but is not guaranteed to include a complete list of
  /// non-documented libraries unless they are all referenced by documented ones.
  final Set<Library> allLibraries = {};

  bool get hasHomepage => packageMeta.homepage.isNotEmpty;

  String get homepage => packageMeta.homepage;

  @override
  Kind get kind => isSdk ? Kind.sdk : Kind.package;

  @override
  String? get aboveSidebarPath => null;

  @override
  String? get belowSidebarPath => null;

  @override
  List<Locatable> get documentationFrom => [this];

  /// Return true if the code has defined non-default categories for libraries
  /// in this package.
  bool get hasCategories => categories.isNotEmpty;

  @override
  late final String documentationAsHtml = Documentation.forElement(this).asHtml;

  /// The documentation from the README contents.
  @override
  String? get documentation {
    final docFile = packageMeta.getReadmeContents();
    return docFile != null
        ? packageGraph.resourceProvider
            .readAsMalformedAllowedStringSync(docFile)
        : null;
  }

  @override
  bool get hasDocumentation => documentation?.isNotEmpty == true;

  @override
  String get oneLineDoc => '';

  @override
  bool get isDocumented =>
      isFirstPackage || documentedWhere != DocumentLocation.missing;

  /// If we have public libraries, this is the default package, or we are
  /// auto-including dependencies, this package is public.
  @override
  bool get isPublic =>
      _isLocalPublicByDefault || libraries.any((l) => l.isPublic);

  /// Whether this package is local.
  ///
  /// A package can be local in three ways:
  /// * this is the default package,
  /// * this is part of an embedder SDK, or
  /// * [DartdocOptionContext.autoIncludeDependencies] is true, and this
  ///   package is not excluded with `exclude-packages`.
  bool get isLocal {
    // Do not document as local if we excluded this package by name.
    if (_isExcluded) return false;
    // Document as local if this is the default package.
    if (_isLocalPublicByDefault) return true;
    // Assume we want to document an embedded SDK as local if it has libraries
    // defined in the default package.
    // TODO(jcollins-g): Handle case where embedder SDKs can be assembled from
    // multiple locations?
    if (!packageGraph.hasEmbedderSdk) return false;
    if (!packageMeta.isSdk) return false;
    final packagePath = packageGraph.packageMeta.dir.path;
    return libraries.any(
        (l) => _pathContext.isWithin(packagePath, l.element.source.fullName));
  }

  /// True if the global config excludes this package by name.
  bool get _isExcluded => packageGraph.config.isPackageExcluded(name);

  /// True if this is the package being documented by default, or the
  /// global config indicates we are auto-including dependencies.
  bool get _isLocalPublicByDefault =>
      packageMeta == packageGraph.packageMeta ||
      packageGraph.config.autoIncludeDependencies;

  /// Returns the location of documentation for this package, for making
  /// decisions regarding the 'linkToRemote' option and canonicalization.
  late DocumentLocation documentedWhere = () {
    if (isLocal && isPublic) {
      return DocumentLocation.local;
    }
    if (config.linkToRemote &&
        config.linkToUrl.isNotEmpty &&
        isPublic &&
        !packageGraph.config.isPackageExcluded(name)) {
      return DocumentLocation.remote;
    }
    return DocumentLocation.missing;
  }();

  @override
  String get enclosingName => packageGraph.defaultPackageName;

  String get filePath => 'index.html';

  @override
  String get fullyQualifiedName => 'package:$name';

  late final String baseHref = documentedWhere == DocumentLocation.remote
      ? (_remoteBaseHref.endsWith('/') ? _remoteBaseHref : '$_remoteBaseHref/')
      : (config.useBaseHref ? '' : htmlBasePlaceholder);

  String get _remoteBaseHref {
    return config.linkToUrl.replaceAllMapped(_substituteNameVersion, (m) {
      switch (m.group(1)) {
        // Return the prerelease tag of the release if a prerelease, or 'stable'
        // otherwise.  Mostly coded around the Dart SDK's use of dev/stable, but
        // theoretically applicable elsewhere.
        case 'b':
          {
            var version = Version.parse(packageMeta.version);
            var tag = 'stable';
            if (version.isPreRelease) {
              // `version.preRelease` is a `List<dynamic>` with a mix of
              // integers and strings.  Given this, handle
              // "2.8.0-dev.1.0, 2.9.0-1.0.dev", and similar variations.
              tag = version.preRelease.whereType<String>().first;
              // Who knows about non-SDK packages, but SDKs must conform to the
              // known format.
              assert(!packageMeta.isSdk || int.tryParse(tag) == null,
                  'Got an integer as string instead of the expected "dev" tag');
            }
            return tag;
          }
        case 'n':
          return name;
        // The full version string of the package.
        case 'v':
          return packageMeta.version;
        default:
          assert(false, 'Unsupported case: ${m.group(1)}');
          return '';
      }
    });
  }

  static final _substituteNameVersion = RegExp(r'%([bnv])%');

  @override
  String get href => '$baseHref$filePath';

  @override
  String get location => _pathContext.toUri(packageMeta.resolvedDir).toString();

  @override
  Package get package => this;

  /// The default, unnamed category.
  ///
  /// This is initialized by [initializeCategories].
  late final Category defaultCategory;

  /// A map of category name to the category itself.
  ///
  /// This is initialized by [initializeCategories].
  late final Map<String?, Category> nameToCategory;

  /// Adds [categorization] to one or more categories in the [nameToCategory]
  /// map, if it is annotated with `{@category}`, or `[defaultCategory], if not,
  /// via the [addTo] callback.
  void addToCategories(
      Categorization categorization, void Function(Category) addTo) {
    if (!categorization.isCanonical) {
      return;
    }
    var categoryNames = categorization.categoryNames;
    if (categoryNames == null || categoryNames.isEmpty) {
      addTo(defaultCategory);
      return;
    }
    for (var category in categoryNames) {
      addTo(nameToCategory.putIfAbsent(
          category, () => Category(category, this, config)));
    }
  }

  /// Initializes the [defaultCategory] and the [nameToCategory] map, with all
  /// appropriate elements.
  void initializeCategories() {
    defaultCategory = Category(null, this, config);
    nameToCategory = {};
    for (var library in libraries.wherePublic) {
      addToCategories(library, (c) => c.libraries.add(library));
      for (var constant in library.constants) {
        addToCategories(constant, (c) => c.constants.add(constant));
      }
      for (var function in library.functions) {
        addToCategories(function, (c) => c.functions.add(function));
      }
      for (var property in library.properties) {
        addToCategories(property, (c) => c.properties.add(property));
      }
      for (var typedef_ in library.typedefs) {
        addToCategories(typedef_, (c) => c.typedefs.add(typedef_));
      }
      for (var extension in library.extensions) {
        addToCategories(extension, (c) => c.extensions.add(extension));
      }
      for (var extensionType in library.extensionTypes) {
        addToCategories(
            extensionType, (c) => c.extensionTypes.add(extensionType));
      }
      for (var class_ in library.classesAndExceptions) {
        addToCategories(class_, (c) => c.addClass(class_));
      }
      for (var enum_ in library.enums) {
        addToCategories(enum_, (c) => c.enums.add(enum_));
      }
      for (var mixin in library.mixins) {
        addToCategories(mixin, (c) => c.mixins.add(mixin));
      }
    }
  }

  /// The categories, sorted alphabetically by name.
  late final List<Category> categories = [
    defaultCategory,
    ...nameToCategory.values,
  ].where((c) => c.name.isNotEmpty).toList(growable: false)
    ..sort();

  Iterable<Category> get categoriesWithPublicLibraries =>
      categories.where((c) => c.libraries.any((e) => e.isPublic));

  /// The documented categories, sorted either by the 'categoryOrder' option, or
  /// by name.
  ///
  /// In the case that 'categoryOrder' is given, any documented categories which
  /// are not found in 'categoryOrder' are listed after the ones which are,
  /// ordered by name.
  Iterable<Category> get documentedCategoriesSorted {
    if (config.categoryOrder.isEmpty) {
      // Category display order is configurable; leave the category order
      // as defined if the order is specified.
      return categories.whereDocumented;
    }

    var documentedCategories =
        categories.whereDocumented.toList(growable: false);
    return documentedCategories
      ..sort((a, b) {
        var aIndex = config.categoryOrder.indexOf(a.name);
        var bIndex = config.categoryOrder.indexOf(b.name);
        if (aIndex >= 0 && bIndex >= 0) {
          return aIndex.compareTo(bIndex);
        } else if (aIndex < 0 && bIndex >= 0) {
          // `a` is not found in the category order, but `b` is.
          return 1;
        } else if (bIndex < 0 && aIndex >= 0) {
          // `b` is not found in the category order, but `a` is.
          return -1;
        } else {
          // Neither is found in the category order.
          return documentedCategories
              .indexOf(a)
              .compareTo(documentedCategories.indexOf(b));
        }
      });
  }

  bool get hasDocumentedCategories => categories.any((e) => e.isDocumented);

  @override
  final DartdocOptionContext config;

  /// Is this the package at the top of the list?  We display the first
  /// package specially (with "Libraries" rather than the package name).
  bool get isFirstPackage =>
      packageGraph.localPackages.isNotEmpty &&
      identical(packageGraph.localPackages.first, this);

  @override
  bool get isSdk => packageMeta.isSdk;

  final String packagePath;

  String get version => packageMeta.version;

  final PackageMeta packageMeta;

  @override
  Element? get element => null;

  @override
  Element2? get element2 => null;

  @override
  List<String> get containerOrder => config.packageOrder;

  @override
  late final Map<String, CommentReferable> referenceChildren = {
    // Do not override any preexisting data, and insert based on the public
    // library sort order.
    // TODO(jcollins-g): warn when results require package-global lookups like
    // this.
    for (var library in publicLibrariesSorted) ...{
      library.referenceName: library,
      ...library.referenceChildren,
    }
  };

  @override
  Iterable<CommentReferable> get referenceParents => [packageGraph];

  p.Context get _pathContext => packageGraph.resourceProvider.pathContext;

  @override
  String get referenceName => 'package:$name';
}
